Skip to content

Releases: drevendev/Devostasis

Devostasis 0.1.9

Choose a tag to compare

@drevendev drevendev released this 30 Sep 20:04
3bd60db

Four things in one release. First, the adoption of the research judgements
that had been delivered and not adopted, which the roadmap's standing
obligation puts before queued work: one Integrity and one Clutter rule
version, one accepted diagnostic under an existing rule, eight accepted exact
vectors and thirty-one cases of three judgements, plus the vector kinds those
cases needed. Second, the review pass of 2026-09-22 (issue #30). Third, the
repairs of the research audits of 2026-09-20 to 2026-09-24, which were
handed off on Drive and had no record in this repository until the review
of 2026-09-25 catalogued them in issue #35. Fourth, the review of
2026-09-30 (issue #48), which found defects in this release's own new code
(among them an Integrity superset that could omit the band it emitted,
replaced by the accepted totality rule) and older ones in verification,
collection, the store and the command line, and filed what needs a decision
as #38 to #47. No threshold, window or gauge changed; the two band rules
that changed did so under accepted judgements, and their rule_id moved
with them.

  • Integrity rule integrity.bands.v1+ci-unit-004. Four accepted
    judgements, one rule version, one RULE_VERSION_BOUNDARY per project.
    PV-REV-INTEGRITY-UNKNOWN-001 (issue #13): a newest in-scope revision whose
    current verdict is UNKNOWN never inherits an older decisive verdict; the
    Vital is UNKNOWN with no band, the decisive history stays in derived,
    and CURRENT_VERDICT_UNKNOWN:<revision> names the cause. Positively
    observed NOT_EXECUTED and NON_VERIFY_TERMINAL keep the accepted
    fallback. Before this, four passes and a newest startup_failure produced
    CLEAN / AVAILABLE / EXACT, and since 0.1.8 a false IMPROVED.
    PV-REV-TEST-003 (issue #12 finding 3): a required revision series that is
    PARTIAL is UNKNOWN with no band, its counts visible and marked; the
    DEGRADED path with a fixed three-band tail called a superset is gone.
    PV-REV-TEST-VECTORS-002 (issue #21): one to three decisive revisions carry
    sample_strength = SPARSE and CI_SPARSE_SAMPLE, four or more
    ESTABLISHED. PV-INTEGRITY-TOTALITY-001 (accepted by
    PV-REV-INT-TOTALITY-001, #33): a newest revision still being verified is
    spoken for by no older verdict; the history names a band only when it
    already satisfies FAILING on its own (four or more decisive revisions, a
    quarter or more failed), DEGRADED / FAILING / EXACT, and every other
    history is UNKNOWN with no band, diagnosed CI_CURRENT_VERIFY_UNRESOLVED.
    This rule version first carried a possible_bands derived from the
    completions instead; the review of 2026-09-30 found it could omit the band
    it emitted (777 of 7,029 shapes, the commonest being one workflow passed
    and one still running) and could miss bands a completion reaches, and the
    accepted contract defines no reachability algorithm at all. A positively
    unconfigured repository with only non-decisive recent records is
    UNINSTRUMENTED with CI_UNINSTRUMENTED_WITH_RECENT_NONDECISIVE_HISTORY;
    an unusable series is UNKNOWN even beside "not configured"; a verdict
    outside the vocabulary is UNKNOWN, never a fallback to an older pass; a
    record whose contribution contradicts its history is a defect. Cases
    INT-UNKNOWN-01..06, INT-TOTAL-01..06 and 08..13, T2, R1, R2 are
    executable vectors.
  • Pulse diagnoses issue-only activity (PULSE_ISSUE_ONLY_ACTIVITY,
    permanent case T5, issue #22), under pulse.bands.v1 as the accepted vector
    requires: provenance, not a judgement about productivity. It is emitted
    only when every channel was positively observed: with a channel unobserved
    or a required enumeration capped, "every observed event came from issues"
    would be a claim about evidence nobody has.
  • Clutter rule clutter.bands.v1: incomplete evidence is a confirmed burden
    floor, never a manufactured band.
    Adopts PV-CLUTTER-INCOMPLETE-001
    (accepted by PV-REV-CLUTTER-INCOMPLETE-001, cases CLU-INCOMPLETE-01..20,
    all executable) and the reading PV-ISSUE-026-RECONCILE-001 gave issue
    #26. An explicitly UNAVAILABLE issue or branch component, or a PARTIAL
    count with an observed subset, no longer yields a band from the rest: the
    band is the floor the observed facts prove. Observed stale work and
    classified stale branches prove it; the ratio proves it only over a
    complete issue and change-request domain; an UNCLASSIFIED branch count
    proves nothing. A PARTIAL count counts as an observed subset only when
    its coverage says so (complete = false,
    value_semantics = OBSERVED_SUBSET_COUNT, which the derivation now records
    on every count aggregate of an incomplete inventory and on nothing else);
    without that proof, with other semantics or with malformed coverage the
    component is unresolved and diagnosed CLUTTER_PARTIAL_NOT_TRUSTED
    (review PV-REV-PR-031-003, cases CLU-PARTIAL-TRUST-01..08; before, any
    fresh PARTIAL value was promoted to a floor on its status alone, so a
    saved observation set could prove HEAVY with an estimate).
    HEAVY is DEGRADED / EXACT (terminal), CLUTTERED and
    LIGHT are DEGRADED lower bounds with a conservative superset, and a
    floor of nothing is UNKNOWN with no band. Before, an unavailable
    component with nothing else observed produced DEGRADED CLEAN, a band
    made from absence; on the fleet's store that is exactly one project, whose
    issues are disabled and which has no stale residue: it becomes UNKNOWN,
    which is what the evidence supports. The #26 case, a capped branch head
    resolution, proves a floor only with explicit CLASSIFIED retention
    semantics (>= 20 HEAVY exact, 6..19 CLUTTERED, 1..5 LIGHT, zero
    UNKNOWN); the GitHub adapter does not emit retention semantics, so on
    GitHub that case stays UNKNOWN until issue #22 decides whether it should.
    Permanent case T7 (issue #22), the UNCLASSIFIED upper bound with
    CLUTTER_BRANCH_PURPOSE_UNCLASSIFIED, moves under the same rule id
    unchanged, and when the work items alone reach the band the full count
    reaches, that band is DEGRADED / EXACT as the contract's section 5 says.
    One RULE_VERSION_BOUNDARY on Clutter per project; no threshold or window
    moved. The GitHub adapter still does not emit retention_semantics:
    emitting UNCLASSIFIED would make Clutter DEGRADED for every project with
    a stale branch and take the accepted ordering away from it, so that is a
    fleet-wide decision left with issue #22, not a default.
  • The accepted exact vectors are in the corpus as the research process
    wrote them: T2, R1, R2 (PV-REV-TEST-VECTORS-002), R4
    (PV-REV-TEST-VECTORS-004), R3 (PV-REV-TEST-VECTORS-005), T4, T5, T7
    (PV-REV-TEST-VECTORS-007). Seven of the seventy named cases without a test
    now have one; sixty-three remain.
  • Two vector kinds and one shape, in answer to the format findings. The
    ci kind (issue #20) starts at the provider-native normalization: workflow
    runs, their earlier attempts and check suites as the provider reports them,
    through the outcome map to canonical revision records and, when the case
    asks, into Integrity. R5..R10 can now be materialized at the boundary they
    are about; INT-UNKNOWN-02 and 03 already are. The activity kind
    carries ACT-COV-01..05 of PV-REV-ACTIVITY-COVERAGE-001 (issue #9), the
    runtime of which 0.1.7 already had. variants lets one case hold several
    evidence shapes to one expectation, for vital and ci cases, which is
    the one-identifier multi-variant mechanism T8 and R9 need (issue #23);
    vital cases may also assert shared_signal_groups and
    dependency_group_ids (part of T6). Every kind fails closed as before; a
    provider without a normalization is an error, never a skip.
  • An observation not later than the previous bundle is INCOMPARABLE
    (issue #17, NON_MONOTONIC_OBSERVATION:<previous>-><current>). It was
    COMPARABLE, its delta reported IMPROVED and WORSENED with the
    direction inverted while citing the accepted order, and activity.json
    carried an interval that ended before it started. The bundle is still
    written and immutable; it claims no direction and no interval, and
    build_activity refuses a backwards interval outright. Where such a bundle
    lands is the monotonic-write policy of issue #12 finding 6, still to be
    decided.
  • The comparison reads the immutable bundle the index names, not
    latest/
    (issue #28). A compacted or damaged convenience copy no longer
    turns the next run into a HISTORY_GAP; a copy that names a different
    bundle than the index is still refused, so finding 6 stays visible. Without
    an index the newest immutable bundle is found by scanning. The fleet
    surfaces link to the immutable report when the copy is gone. RPT-3 now
    corrupts the immutable copy, which is what its sentence always meant.
  • Verification binds the manifest's metadata to what the identity hashes
    (issue #12 finding 4). semantic_config, the field the comparison reads,
    must be the projection of the validated stored config
    (SEMANTIC_CONFIG_MISMATCH); every identity field the manifest repeats must
    be present in both copies and agree with the preimage
    (IDENTITY_FIELD_MISMATCH), with the fields a bundle must carry and the
    renderers it may name decided by its exact lineage
    (UNSUPPORTED_ARTIFACT_LINEAGE, RENDERER_VERSION_NOT_IN_LINEAGE;
    PV-AUDIT-MANIFEST-PREIMAGE-BINDING-001, whose concrete case was a bundle
    that lost its manifest renderer_version, kept its id, skipped the report
    replay and verified with any report at all); the manifest receipt
    must hash to source_receipts_digest and be the receipt inside
    observations.json (RECEIPT_DIGEST_MISMATCH, RECEIPT_COPY_MISMATCH);
    and snapshot.json must name the evidence the bundle carries
    (OBSERVATIONS_DIGEST_MISMATCH). A manifest o...
Read more

Devostasis 0.1.8

Choose a tag to compare

@drevendev drevendev released this 07 Sep 17:44
a8726f5

Roadmap targets B5 and B1: the first accepted band ordering, and the format
and runner that make a conformance case executable. No threshold, window or
gauge changed, and no rule was retuned.

  • Band ordering (target B5, PV-BAND-ORDER-001). Three Vitals now declare
    which of two of their own bands is better: Clutter
    CLEAN > LIGHT > CLUTTERED > HEAVY, Flow MOVING > CONGESTED > GRIDLOCKED
    for a live queue, Integrity CLEAN > FLAKY > FAILING and
    SPARSE > SPARSE_MIXED. delta.json therefore emits IMPROVED and
    WORSENED where the order applies. Pulse, Horizon, Direction and Debt
    declare no order at all, and neither does NO_QUEUE against a live queue or
    an Integrity evidence state against a verdict: those transitions stay
    CHANGED. No order is declared across Vitals or across projects, and none of
    this is a step towards an aggregate.
  • A direction is only ever reported about exact measurements. The pair must
    be COMPARABLE, the rule_id unchanged and both sides AVAILABLE with
    EXACT band semantics; a DEGRADED band is a bound, and a move between
    bounds is not an improvement. The rule version boundary and observability
    transitions keep precedence, and a gauge that moved inside a band is still
    UNCHANGED. Every row that could have been ordered but was not says why:
    BAND_ORDER_NOT_DECLARED, BAND_ORDER_INCOMPARABLE or
    BAND_ORDER_NOT_ELIGIBLE.
  • devostasis.delta.v2 carries the two new classes and names the ordering
    it applied in band_order_contract and band_order_version, so a stored
    delta says under which order its classes were decided. This is the fourth
    and, with the consumer surface now frozen, the last planned move of bundle
    identity: every row of the consumer surface in the ROADMAP is stable.
  • Executable conformance vectors (target B1). A conformance case can now be
    written as JSON and executed: devostasis.vectors.v1 with a vital kind
    that evaluates one Vital over raw observation envelopes and a delta kind
    that compares two snapshots, a runner, a devostasis vectors command and a
    published schema (docs/spec/vectors.md). It fails
    closed: an unknown kind, an unknown key, an unknown comparison status, a
    malformed envelope or a duplicate case id is an error, never a skipped case
    that looks like a pass. The schema declares the partial evidence envelope a
    vector actually states, and a test holds it to the envelopes the corpus
    writes, so the runner and the published schema cannot accept different files.
  • The ordering ships as fifteen vectors, not as prose. ORDER-01..15 live
    in tests/vectors/band-order.json, run inside the ordinary test suite and in
    CI through the command line, and the conformance table cites them as
    vector:ORDER-nn. A third drift guard now checks both directions: a citation
    without a vector fails, and a vector nobody cites fails.
  • Those fifteen carry the meanings the contract gives them. The first
    version of this release derived the cases from the contract's rules instead
    of transcribing its Required conformance cases section, which moved every
    identifier from ORDER-02 onward onto a different claim — a research
    identifier is never reused, and conformance.md says so on the same page.
    PV-SPEC-001 found it; the cases are now transcribed, and the two accepted
    pairs the corpus never executed (NO_QUEUE against GRIDLOCKED,
    SPARSE_MIXED to FAILING) are executed. Semantics did not change: the
    ordering itself was conformant, and no band, threshold or rule moved.
    The split, adjacency and precedence cases this implementation wanted beyond
    the accepted set are kept under local DEV-ORDER ids, which belong to no
    research unit. A fourth guard holds each ORDER-nn to the accepted case name
    and to the band pairs that case names, because the first two guards pass
    happily while every identifier means something else.
  • A vector case can state more than one pair. given.comparisons is a
    list, each entry with its own expect, and the case passes only when all of
    them do. Accepted cases are written that way — "GRIDLOCKED → CONGESTED → MOVING follows the WORSENED/IMPROVED direction" is six comparisons, "every
    unequal Pulse band pair" is twelve — and splitting one across several vectors
    would split its identifier. ORDER-01..15 now execute 85 comparisons between
    them. devostasis.vectors.v1 is unchanged for the single-pair shape it
    already had.
  • The vectors of PV-TEST-001 are still owed by the research process. The 70
    named cases without a test remain open (debt D-1), but what was missing on
    our side is now built, so those vectors arrive executable instead of needing
    translation.
  • A documented pin that names a tag nobody published is now a red build.
    tests/test_release_pins.py proves the pins agree with pyproject.toml; it
    cannot prove the tag they name exists, because on a release branch that tag
    legitimately does not exist yet. Nothing closed the window afterwards, and
    0.1.8 fell into it: every pin said v0.1.8 while master carried no such tag,
    so the install command in the README failed for anyone who ran it. A new
    Released pins resolve workflow runs daily on master and resolves every
    documented pin against the remote. Daily rather than per push, because the
    window is legitimate for as long as it takes to tag a merge and not a day
    longer. The self-observation workflow could never have caught this: it passes
    devostasis-ref: ${{ github.sha }}, which is right for its purpose and means
    the one live exercise of observe-self.yml overrides the input that goes
    stale (issue #18).
  • Bookkeeping: the 0.1.7 section still said "unreleased" after v0.1.7 was
    tagged and released, which is the exact drift debt D-4 names.

Alongside the two targets, the defects the external review of 0.1.7 found
(#12, finding 5). Each was
reproduced before it was fixed. No contract, threshold or rule changed.

  • A malformed title no longer ends a fleet run. _title crashed with
    IndexError on a title that is only whitespace and with AttributeError on
    one of the wrong type. Neither is a RegisterError, so neither reached the
    collector's error boundary. _title is now total for provider payload — a
    commit message, change-request or issue title of the wrong type is a missing
    title — while a register title of the wrong type is a RegisterError and
    reaches the snapshot as ERROR / INVALID_REGISTER, which is what the
    register contract says it should be.
  • Linkage evidence is the exception, and it is now declared. A title or
    body of the wrong type is a missing title everywhere except where the target
    marker lives: _target_refs joined the raw fields, so a non-string there
    raised TypeError under planning.source = file, and reading it as an
    absent link would report a project unlinked on evidence nobody could parse.
    Unreadable title, body or milestone is now LinkageEvidenceError, a
    CollectionError, so the project fails explicitly with its reason while the
    rest of the fleet is still observed. A change request with no marker is
    still simply unlinked, because absent evidence is a fact and unreadable
    evidence is not.
  • A successful response that is not JSON is a declared provider failure.
    UrllibTransport.get raised json.JSONDecodeError out of every handler on
    an HTTP 200 with an unreadable body. It is now ApiFailure with
    MALFORMED_RESPONSE, so it becomes an observation status like every other
    provider failure.
  • One project's failure costs one project. run_all had no boundary of its
    own, so anything run_project did not anticipate stopped every project
    queued behind it, skipped the entity-tag cache write and left the fleet index
    stale. Each project now fails on its own, keeping its reason and its
    unsuccessful outcome, so the run still exits non-zero.

Devostasis 0.1.7

Choose a tag to compare

@drevendev drevendev released this 06 Sep 16:15
575abdd

A review of what already exists. No new capability, six defects fixed, one open question filed, two guards added. No rule, threshold, window or gauge changed.

Incomplete evidence looking complete, twice. The release collector always reported AVAILABLE with a recent_only coverage flag, so a repository with more than thirty releases had the newest thirty recorded as the whole truth; a full page is now PARTIAL with the cap reason, like every other enumeration. Downstream, a PARTIAL release inventory left no coverage note in activity.json, so even a flagged truncation read as complete in the report. No Vital reads releases, so no band was ever wrong.

Activity could declare an interval wider than its evidence. The report declares the interval since the previous bundle, as the reporting contract requires, but the inventories behind it reach back 28 days. After a longer outage the report claimed the whole gap and the unobserved part read as "nothing happened". It now carries INTERVAL_EXCEEDS_EVIDENCE_WINDOW:evidence_from=<timestamp>. Whether collection should widen to the interval instead is a question for the reporting contract, filed as issue #9.

Three smaller defects. A 304 answered to a request that carried no entity tag was treated as a successful empty body, and is now an explicit failure. A cached entry whose body was null kept its tag, so every later 304 read as a miss and refetched forever. all_projects collected a rename list that nothing consumed.

Two guards against drift. The conformance table may not cite a test that has disappeared, the specification index must link every page, and every contract identifier the runtime writes into a bundle must be findable in the specification. The last check immediately found five member schema identifiers documented nowhere, now listed in the bundle specification. That is the mechanical half of the drift debt; the semantic half stays manual.

Verified against 231 tests and all 218 bundles of the observed fleet.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.7 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.6

Choose a tag to compare

@drevendev drevendev released this 06 Sep 15:08
47de188

Spend provider quota only on what changed. No rule, threshold, window or gauge changed.

A fleet run asked the same questions every day and paid full rate-limit price for answers that had not moved, and a rate-limited day degraded bands to UNKNOWN rather than reusing the previous answer. Three limits now shape how evidence is fetched, and none of them changes what it means.

  • Conditional requests. --cache <dir> keeps the entity tags of previous runs (devostasis.http-cache.v1). An unchanged answer comes back as 304 Not Modified, replays the stored body, and costs a round trip but no rate-limit quota. A missing or corrupt cache costs requests, never correctness.
  • Bounded retries. A retryable failure waits only as long as the provider asked, through Retry-After or the rate-limit reset, and only while a single wait and a total waiting budget allow it. A primary rate limit resets on the hour, so waiting it out inside a run would be a hang: that case becomes an explicit ERROR / RATE_LIMITED observation and the run moves on.
  • A request budget per project, --request-budget <n>, so one very active repository cannot starve the rest of a fleet. When it bites, a partially enumerated inventory is PARTIAL and one that never started is UNKNOWN, both with the reason REQUEST_BUDGET_EXHAUSTED, and the receipt carries a matching capability note. A short list is never reported as complete.

Receipt devostasis.receipt.v2 no longer records the request count. The receipt is identity-bearing, so without this change turning the cache on would have silently moved every bundle_id for unchanged evidence. How the evidence was fetched belongs to the client rather than to the evidence; the counts moved to the bundle's post-identity run_meta, which now also carries billed_requests, conditional_hits and retries. Bundles written under devostasis.receipt.v1 remain verifiable, because verification uses each bundle's stored preimage.

Bundle identities therefore change once for identical evidence. Comparability is unaffected: the receipt is not part of the semantic configuration.

Twenty tests cover the three limits, including one that builds the same repository with a cold and a warm cache and asserts the bundle identities match.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.6 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.5

Choose a tag to compare

@drevendev drevendev released this 06 Sep 14:49
b46fd24

A project is its immutable id, not its path (RPT-7). No rule, threshold, window or gauge changed.

Renaming or transferring a repository used to split its history in two: the old directory became an orphan nobody read again, and the new one started at BASELINE as if the project had just been born. The immutable project id was already recorded in every bundle and used by nothing.

  • The history store now locates a project by project_identity.immutable_project_id and treats the locator as the human-readable place to put it. A renamed or transferred repository is relocated once to its new locator instead of starting a second history, and the move is recorded in the project index as a renames entry.
  • Ambiguity fails closed. A locator already held by a different project is refused rather than merged, and the conflict is detected before any history is read, so latest() can never compare against the wrong project. A repository whose old name is immediately reused by a new repository therefore yields two separate histories, because the ids differ.
  • An adapter that cannot prove an immutable id keeps the previous behaviour: the locator is the identity and a rename starts a BASELINE. Without proof that two names are the same project, losing continuity is more honest than guessing.
  • Bundles are unchanged, including the project_key each records: a bundle keeps the locator it was observed under, and moving the directory does not rewrite it. Every relocated bundle still verifies.

Twelve conformance tests for RPT-7 cover rename, transfer, an old name reused by a new repository, a locator held by another project, a conflict reported by latest(), a missing immutable id, an unchanged locator, the fleet surfaces after a rename, and verification of relocated bundles.

Also in this release: calibration finding 9, found by observing this repository. Direction counts active change requests linked to an open target, so closing a delivered target un-links the pull requests that delivered it while they are still inside the 28-day window. Never closing a target would keep the band higher than finishing the work. The finding is measured rather than reasoned and is recorded for the research process with three candidate readings.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.5 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.4

Choose a tag to compare

@drevendev drevendev released this 06 Sep 14:26
4c14bc7

The fleet as data, not only as Markdown. No rule, threshold, window or gauge changed.

A history store now carries projects/index.json beside projects/README.md, under the contract devostasis.fleet.v1 (schema schemas/fleet-index.schema.json). One entry per project: locator and immutable project id, observed_at, bundle_id, previous_bundle_id, comparison_status, the project's own attention order, one row per Vital with band, evaluation status, gauge and demand level, and relative paths to the report and to the immutable bundle the entry came from. It is written by every fleet run and by devostasis index.

jq -r '.projects[] | select(.vitals.integrity.level == "CRITICAL") | .locator' projects/index.json

Three properties make it safe to consume:

  • it adds no meaning, since every value comes from the latest bundle, which stays authoritative for provenance, coverage and the reasoning behind a band;
  • there is no aggregate;
  • there is no cross-project ordering, and cross_project_order is explicitly null, because no accepted contract says what it means for one project's CRITICAL to outrank another's. A consumer that wants a fleet-wide priority applies its own policy and owns that decision.

Two failure modes are handled rather than assumed. A bundle written before the demand interface existed yields null levels and an empty attention order rather than invented ones. The document carries no generation timestamp and is ordered by project key, so a run that changes nothing rewrites the same bytes and a version-controlled store stays quiet.

This is the last change to the consumer surface that the implementation owns. The remaining one is the band ordering contract, which decides whether delta.json ever emits IMPROVED and WORSENED, and it belongs to the research process.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.4 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.3

Choose a tag to compare

@drevendev drevendev released this 06 Sep 12:32
40bb4b1

Devostasis declares its own plan and debt, so its report about itself stops saying UNDECLARED and UNINSTRUMENTED and starts saying something a consumer can act on. No rule, threshold, window or gauge changed.

  • .devostasis/targets.json and .devostasis/debt.json: this repository's planning targets and registered maintenance obligations, maintained by hand and mirroring the phases in ROADMAP.md. They are also the worked example an adopter copies, replacing the fictional paths the specification used until now.
  • Self-observation reads them: the caller passes planning-source file, both register paths and a debt mapping_version, so the workflow and the fleet observation see the same metadata and cannot disagree.
  • CONTRIBUTING documents the Target: <id> line that links a pull request to a target, the rule that a due date is written only when it is real, and the boundary between a target and a debt item.
  • The deployment guide names this repository as the worked example and states that registers are read from the default branch, so a register on a working branch is REGISTER_NOT_FOUND until it merges.
  • Every documented pin names v0.1.3, including the reusable workflow's default install ref, and tests/test_release_pins.py fails the build when a pin, the package version or the changelog section falls behind.
  • tests/test_own_registers.py turns a typo in either register into a red build instead of three Vitals quietly going UNKNOWN.

Measured against the real register content rather than assumed: Horizon becomes DECLARED with ten open targets, Debt becomes PRESENT with five open items and none stale, and Direction follows the markers on active pull requests. Horizon stops at DECLARED rather than VISIBLE because no target carries a due date, and none does because none of the dates would be real.

This is the first real-repository evidence for planning.source = file and debt.source = file; until now both contracts existed only in synthetic fixtures. A project's history is INCOMPARABLE once when its configuration adopts the registers, because the semantic configuration changed.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.3 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.2

Choose a tag to compare

@drevendev drevendev released this 06 Sep 08:04
7318597

The first research judgements, adopted against real bundles. No numeric threshold or window changed.

  • Flow rule flow.bands.v1: a positively observed empty queue is NO_QUEUE whatever the historical merge median, and the classifier consumes the exact rational median merge latency in seconds (604800 s and 1209600 s are the exact conversions of 168 h and 336 h). The whole-hour value stays as a derived presentation projection.
  • Pulse rule pulse.bands.v1: a capped required enumeration is evaluated over every admissible completion of the missing tail, giving one forced band, every reachable band in possible_bands, or UNKNOWN.
  • Delta: a Vital whose rule version changed since the previous bundle is INCOMPARABLE on its own (RULE_VERSION_BOUNDARY) while the bundle stays COMPARABLE; historical bands are never reinterpreted.
  • Demand devostasis.demand.v2: the attention order is level rank, then canonical Vital order. The cross-Vital gauge tie-break of v1 is removed, because gauges of different Vitals measure different phenomena; attention_key is gone.
  • Verification adopts the stored effective config as the semantic authority of a bundle: fail-closed schema validation, the canonical member profile derived from it and checked against manifest, members and identity markers, and report replay only after those pass. Bundles of both effective-config schemas still verify.
  • Renderer devostasis.render.v4; the GitHub CI outcome map is confirmed (timed_out is a verification failure, startup_failure is UNKNOWN).
  • Documentation: gauges accepted for presentation and same-Vital ordering only; reporting decisions on permission-domain stores, optional report.html, retention, and self-observation output being convenience rather than durable history.

Bundle identities change for every project. History stays COMPARABLE; Flow and Pulse report RULE_VERSION_BOUNDARY once, on the first bundle after the upgrade.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.2 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.1

Choose a tag to compare

@drevendev drevendev released this 05 Sep 20:57
84f580d

Self-observation for any repository.

  • Reusable workflow observe-self.yml: a repository observes itself with its own GITHUB_TOKEN (no secret), uploads the bundle as an artifact, writes the status card and attention order to the job summary, and exposes attention, attention-order, levels, bands, gauges, bundle-id and comparison-status as outputs. Optional read-only comparison against a history store.
  • devostasis run --repo owner/name observes one repository from flags; devostasis actions-summary writes the job summary and step outputs.
  • Devostasis observes itself weekly with the workflow it ships.
  • No contract, policy or bundle change: bundles of 0.1.0 and 0.1.1 are identical for identical evidence.

Usage: uses: drevendev/devostasis/.github/workflows/observe-self.yml@v0.1.1 (see docs/deployment.md).

Generated with Claude Code.

Devostasis 0.1.0

Choose a tag to compare

@drevendev drevendev released this 05 Sep 20:18
c532242

First release: deterministic, model-free vital signs for software repositories.

Highlights

  • Seven Vitals under the accepted PV-VITALS-V1-002 taxonomy: Pulse, Flow, Integrity, Clutter, Horizon, Direction, Debt. Named bands, explicit UNKNOWN and DEGRADED bounds, declared correlations, no aggregate score.
  • Observation contract RAW-OBS-V0: every fact carries a status (AVAILABLE, PARTIAL, UNAVAILABLE, FORBIDDEN, UNKNOWN, ERROR), a freshness and a receipt. Zero is only ever a positively observed value.
  • Integrity implements PV-CI-UNIT-004: revision-level verdicts, provider-native parent identity, greatest-attempt current state, failure-sticky history. Retry-until-green cannot erase a failure.
  • Read-only GitHub adapter on the standard library, sized for very active repositories; pagination caps become PARTIAL, tier and permission failures become UNAVAILABLE / FORBIDDEN.
  • Immutable bundles (devostasis.bundle.v2): manifest, snapshot, delta, activity, observations, gauges, demand, persisted effective config and a deterministic Markdown report; SHA-256 identity over an acyclic preimage; devostasis verify needs nothing outside the bundle.
  • Gauges (devostasis.gauge.v1): 0-100 position of every band on the scale of its phenomenon, persisted as gauges.json.
  • Demand interface (devostasis.demand.v1): one level per Vital from an overridable band-to-level table plus an attention order, UNRESOLVED for missing evidence, no sum.
  • Register files: planning targets and debt items from targets.json and debt.json in the observed repository, change requests linked by a Target: <id> marker; label-based debt mapping and GitHub milestones also supported.
  • Display configuration: which Vitals, which card components (bar, number, band), which report sections.
  • Append-only history store with BASELINE / COMPARABLE / HISTORY_GAP / INCOMPARABLE comparison, activity since the previous successful bundle, and a fleet overview.
  • CLI: observe, evaluate, run, build, verify, render, index, gauges, demand.
  • 127 conformance and unit tests named after the research cases they implement; CI on Python 3.12, 3.13 and 3.14.

Install

pip install git+https://github.com/drevendev/devostasis@v0.1.0

See docs/deployment.md for the daily GitHub Actions setup with a companion history repository, and ROADMAP.md for what is deliberately deferred (GitLab, instruments, HTML report, custom templates, themes).

🤖 Generated with Claude Code