Skip to content

The direction graph reads back, and the reading repairs nothing (#417 part c) - #457

Merged
tonite31 merged 1 commit into
mainfrom
feat/417-objective-check
Sep 5, 2026
Merged

tonite31 merged 1 commit into
mainfrom
feat/417-objective-check

Conversation

@tonite31

@tonite31 tonite31 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Accepted issue

Closes #417

  • A maintainer added status:accepted to the issue
  • A maintainer assigned the issue to me
  • My branch is named <type>/<issue-number>-<short-description>
  • Every commit includes my DCO Signed-off-by trailer

Part (c) of the three-part delivery in the approved #417 design v2.1. Part (a)
shipped the link model as #452 and part (b) the carry, guards, retarget, dates
and judgment provenance as #456; both are on main and this branch is based on
them. Sequencing dependency (a) → (b) → (c) is satisfied.

Problem

Issue #417 recorded four graph inconsistencies in a real project: work left on
a superseded milestone while its successor had none; recurring maintenance
turned into a product checkpoint dated past its objective; a checkpoint keeping
an assumption after the decision changed; completed work never reconciled with
a successor's criteria.

Parts (a) and (b) refuse the creation of three of those. They reconcile none
of the stores that already hold them, and the design forbids automatic cleanup.
Until this branch, no command answered any of the four: a session read
self context, saw a tidy list of open outcomes, and treated a drifted graph
as current truth.

Result

self objective check [--project <slug>] [--json] — one read verb that states
seven kinds of finding and changes nothing.

Structural (commands repair the relationship, a person chooses which):

  1. live work whose every current contribution is to an outcome that is over;
  2. a successor checkpoint with no live work beside a predecessor that has some;
  3. a live checkpoint dated past its objective;
  4. live work with no contribution, no standalone declaration and no run link.

Review-needed (a person rejudges the meaning):

  1. a coverage judgment made under a former parent, or an assumption on a
    decision that was replaced;
  2. an objective whose whole live checkpoint workload is runbook occurrences.

Information only:

  1. done work with reported evidence that could be cited for an uncovered
    criterion — listed with the milestone met template carrying a literal
    cN, because the tool pairs nothing.

Every command a finding prints is one this branch dispatches and one that acts
on the condition the finding states; a run of the printed command is a test
cell for each. A prose decision is never offered as clearing a structural
condition it does not change. Where a lineage ends closed, no relink is
offered — only the standalone declaration and the retire — so no printed
command leads to a second refusal. A unit whose current contributions are
several closed outcomes gets one self work unlink per closed target, in
the same stable order as the finding's own summary, so withdrawing every
obsolete edge and declaring standalone reaches a reconciled state in one pass
(see F1 below — the independent review found this printed one unlink only;
the fix is on this branch and the independent follow-up review has verified
it).

Nothing is inferred from prose. Maintenance is read off the relates edge
self runbook link writes, never out of a record's wording or its dates. Where
a unit contributes to another project's objective and this machine cannot read
that project, the answer states target state not checked and the header
counts it apart from the findings, so an unreadable log is never reported as
all clear.

self status and self context each carry one direction line — the count, and
the scoped command — so a session knows whether to run the check without
running it first.

Guidance for all of it lands on the three entry routes: the CLI pages
(self objective --help, self help goals, self help work), the managed
block connect.ts writes, and the plugin's tool description and README.

Design rules

  • I consulted ARCHITECTURE.md before writing code
  • No module imports from a layer above it; no new import cycle
  • No new flat top-level subsystem — a new subsystem owns a directory with a commands.ts
  • No core module gained an import from a subsystem directory
  • No new path around a single gate (event append, sanitization, completion refusal, process ledger); any new or migrated command surface in this PR parses through args.ts parseCommand
  • New events extend an owned namespace rather than minting a sibling
  • Helpers reused, not re-derived; functions within 20-30 lines
  • Tests are checkout-agnostic: no assumed default branch, no assumed local main, no assumed git config, no macOS-only tools
  • Artifact shape honored where touched: {name, sha256, bytes}, name not path

Three notes for the reviewer, each a deliberate structural choice:

  • apps/cli/src/check.ts joins the render layer, and ARCHITECTURE.md's
    layering table is updated in the same PR. It is a projection of a folded
    model rather than a render, which is what reachability.ts already is. It
    cannot live in @superself/fold: finding 4 reads which records answer as a
    runbook run, and that derivation is this tree's runbooks.ts, which the
    package deliberately does not hold. What the package would have given for
    free — the purity guarantee — is asserted instead by a cell that reads the
    module's own source against the same five rules
    apps/fold/test/purity.test.mjs holds the package to.
  • No second implementation of a closure rule. milestoneClosure and
    exitStanding are extracted out of objectives.ts's own derivation, which
    now calls them, and carriedJudgments is exported rather than recomputed. So
    the check and the milestone page cannot disagree about what is closed, what is
    open, or which judgment stands.
  • No event, no verb, no namespace. This branch adds no writer at all.

Verification

  • pnpm typecheck
  • pnpm build
  • pnpm structure — dead exports 0 (base 0)
  • pnpm smoke
  • pnpm testCI's verify job is green on the F1 fix head
    4ace65a
    , alongside dco and contribution-policy, and was green on
    594eedb (5m39s) before it. This session is not alone on its machine, so
    per CONTRIBUTING it ran the other four gates locally plus the suites it
    touched, listed below, and left the full tier to CI. The current head
    a7a0431 differs from 4ace65a by exactly one blob — the finalized
    review receipt — with no production, test or workflow file changed, so
    verify's green on 4ace65a is the result for all executable content on
    this branch. CI is re-running on a7a0431; the coordinator owns that
    gate.
  • Added or updated regression coverage where appropriate

Suites run locally, one node --test process each:

Suite Result
apps/cli/test/objective-check.test.mjs (52 cells, cell 53 added for F1) 52/52
guards-carry.test.mjs, contract.test.mjs, guide.test.mjs 73/73
docs.test.mjs 14/14
context.test.mjs 15/15
render-gate-documents.test.mjs, render-gate-tty.test.mjs, golden.test.mjs passing
tokens.test.mjs, waiting-render.test.mjs, instruction-context.test.mjs, skill-context.test.mjs, workspace-direction.test.mjs passing
integrity.test.mjs 14/14
apps/fold/test/determinism.test.mjs, purity.test.mjs 9/9

The case table is
docs/maintainers/case-tables/417-check.md,
written before the code; every test names its cell number.

Four existing test surfaces changed, each because a printed contract changed
and not to loosen an assertion:

  • guards-carry.test.mjs cell 54 — "no entry route advertises the check part
    (c) has not shipped" — is retired, because part (c) has shipped it. Cell
    53 beside it still resolves every command every route names against the typed
    contract, so the rule that cell enforced is unchanged and still proved.
  • render-gate-documents.test.mjs stage 4 cell 6 pins the order of the piped
    self status lines; direction: is added to the pinned order, beside the
    objective roll-up it is a reading of.
  • The golden fixture is regenerated: self status, self context, the root
    usage page and self help work each print one more thing, which is the
    intended outcome of this branch.
  • integrity.test.mjs's pre-cutover captures: context.txt and status.txt
    gain exactly the one direction line each, and every other capture is
    byte-identical. The direction line reaches every store, so a pre-cutover one
    is not exempt from it; what E1 claims is that an old binary's log still
    folds the same, and G5 asserts that about records rather than about a
    page's furniture. Both rebaselined captures read ok, which is the
    substantive evidence in the diff — the check states no finding at all
    against a legacy log, so it invents no drift out of history it cannot have
    caused. (This was CI's one failure on the first push; the fix is the
    rebaseline plus the reason, recorded in the test file and as cell 57.)

Risk review

  • Local data or migration impact: none. No event type, no payload field, no
    store file, no migration. The branch adds no writer: objective check returns
    a payload block and appends nothing, and a cell asserts the store is
    byte-identical after a plain run and a --json run.
  • Pairing or security-boundary impact: none. check.ts imports no
    credential, no rail and no transport, reaches no network, and reads no
    machine at all.
  • SPFN upstream-boundary impact: none.
  • Platforms exercised: Linux (Node 22.23) on the dev VM. Not exercised on
    macOS; the new suite is checkout-agnostic and uses node plus git only.
  • Visual change: terminal output only. self status gains a DIRECTION
    heading, self context gains one head line, and self objective check is a
    new page; the golden fixture diff in this PR is the record of the piped bytes.

Content quality gate

The English command guidance on all three entry routes is a content unit under
.agents/skills/content-quality-gate.

The independent review has happened, and the one finding it blocked on is
fixed and independently verified.
In the first round a reviewer distinct from
the author read all seven content files, ran self objective check and the
commands it prints against scratch workspaces, re-ran the touched suites, and
ruled both length questions the author left open, returning revise on F1
alone. In the second round a follow-up reviewer distinct from both the
implementing author and the fix author read the correction, reproduced the
failure and the pass, and resolved F1. Neither reviewer wrote any production
code or copy.

F1 — resolved and independently verified. Was the one blocker; low
severity, bounded correction.
obsoleteFinding printed one
self work unlink, for the first closed target only, while the finding's
summary named every closed target. self help goals and the plugin README
both stated that "each one clears the finding it was printed under", which a
reachable state falsified: a live unit contributing to two dropped
checkpoints, with every printed line run verbatim, still carried the finding
afterwards — naming the second checkpoint. The reproduction transcript is in
the receipt.

This head applies the review's preferred correction: obsoleteFinding now
maps over every closed target and prints one self work unlink each, in the
same stable order as the summary; a new cell (53 in the case table and test
file) builds a unit with two closed contributions — a dropped objective and a
dropped milestone — runs every printed unlink and then the standalone
declaration, and asserts the obsolete-contributions and no-disposition
findings are both gone and the unit was never retired. The two entry-page
sentences (self help goals, plugin README.md) are narrowed to say the
printed steps for the chosen route clear the finding, not that each command
alone does, since a multi-target route needs every unlink plus the standalone
before the finding clears. docs/reference/cli.md made no per-command
claim and needed no change. Diff against the reviewed head c5b72cab is five
files: check.ts, guide.ts, README.md, the test file (one new cell), and
the case table (one new row) — no other content or production file moved.

Locally: apps/cli built clean (tsc) and
node --test apps/cli/test/objective-check.test.mjs passed 52/52, including
the new cell. The whole-suite/pnpm test gate was left to CI per the branch
rule against repeating full local runs, and CI's verify job is green on
4ace65a.

What the independent follow-up reviewer checked, and did not take on
report.
It read the delta c5b72cab..4ace65a itself and confirmed that the
check.ts change is one line for one; that the summary and the new unlink list
are built from the same singly-sorted array, so their order cannot diverge;
that first still supplies only the finding's objective and detail, as
before; and that no other finding, grouping or successor behaviour is touched.
It established that no pre-existing case changes answer — for a unit with one
closed target the new closed.map emits exactly the line the old first.label
emitted, and every pre-existing obsolete-contributions cell asserts command
membership rather than an exact list — so the first round's 51/51 carries over
without a rerun.

It then ran cell 53 by name against the shipped build (# pass 1 # fail 0),
and again against a build with only the fixed line reverted to its first.label
form, where it failed on exactly the assertion naming both closed targets. The
regression is load-bearing rather than merely green. The scratch reversion
touched only untracked dist/, was restored byte-exactly (SHA-256 verified),
and left the tree clean.

ready is now certified, and not by the author. The receipt records the F1
resolution, both runs, a fresh digest over the seven content files, and the
first round's evidence and author/reviewer identities unchanged. Four of the
seven files are byte-identical to the state the first round certified, so that
evidence carries over; the three that changed are the three F1 named, and each
was re-read in full. One non-blocking follow-up is recorded rather than fixed:
the rewrap of the corrected guide.ts paragraph leaves one short line mid-
paragraph, which changes no meaning, order or action, and the gate forbids
blocking on surface polish. It is worth rewrapping the next time guide.ts is
edited.

The two open length questions are ruled, both Keep. The managed block
measures 136 lines, 32 bullets, 9,609 characters at this commit; the added
bullet earns its ~12 lines because it is read at the one moment the reader has
not yet run anything. The superself_work description measures 1,559
characters against 179–243 for its four siblings; it is kept, with the
recorded reservation that its six-item finding enumeration is the half a future
revision should cut first once the listing budget is measured. Neither is a
blocker: no factual error, no unsupported claim, every command in them
dispatchable.

One receipt correction. The author's draft recorded that the tool
description omits findings 3 and 7; it omits finding 7 only. The receipt now
states the omission as it is.

Two things the review confirmed rather than assumed. The part (b) review's
carriedJudgments flag — newest coverage claim by physical log position — does
not reach this branch's answer: recordCoverage is the only coverage writer
and emits entity.covered alone, and those claims are sorted by
(ts, event id) in entities.ts before they reach the projection, which cell
36 demonstrates over a carried-and-rechecked fixture. And the health summary's
available set is the same list objective check itself folds, so the count
on self status cannot disagree with the command it points at.

Draft, and what is left to the coordinator

Opened as a draft. The coordinator controls the merge. The independent content
review is now on the record — see the gate section above — and the reviewer
wrote no production code or copy: the only blob it changed is the receipt.

F1's mechanical fix and the independent follow-up review are both on this
branch, which remains one squashed commit (head a7a0431) against the same
b863977 base. The follow-up reviewer's only blob is the receipt; every other
file at a7a0431 is byte-identical to 4ace65a, the head CI's verify job
passed. The review's own stop condition — the F1 row, a cell reference and a
fresh digest — is met, and it called for no further reviewer round beyond that.

Left to the coordinator: the verify re-run on a7a0431, and the merge. Not
done here and not to be read as done: no merge, no release, no tag, and issue
#417 is not manually closed — the closing keyword in this body is the only
mechanism, and it fires on merge.

@tonite31
tonite31 force-pushed the feat/417-objective-check branch 3 times, most recently from c5b72ca to 4ace65a Compare September 5, 2026 16:17
`self objective check [--project <slug>] [--json]` states seven kinds of
finding over a project's direction graph and changes nothing. Part (c) of
issue #417's approved design v2.1, on top of the link model (#452) and the
carry, guards and judgment provenance (#456).

Structural: work whose every current contribution is to an outcome that is
over; a successor checkpoint with no live work beside a predecessor that
still has some; a checkpoint dated past its objective; work that states no
disposition at all. To review: a coverage judgment made under a former
parent, or an assumption on a decision that was replaced; an objective whose
whole live checkpoint workload is runbook occurrences. Information only:
done work that could be cited as evidence for an uncovered criterion.

Every line the check prints is a supported command; for the route a reader
chooses, the printed steps clear the finding they were printed under.
Nothing is inferred from prose — maintenance is read off the `runbook link`
edge — nothing is paired to a criterion, and a contribution whose owning
project this machine cannot read is reported as `target state not checked`
rather than passed over as all clear.

The projection reads no machine: no clock, no filesystem, no `process`. It
reads only log-determined fields, so `missed` and `at-risk` never reach it,
and its order is total and locale-free. `self status` and `self context`
carry the count.

Reviewed independently at 594eedb by the `review-457` agent, which wrote no
production code or copy: `docs/content-reviews/direction-check.en.md` carries
that review, verdict `revise` on one finding — a live unit whose current
contributions are several closed outcomes was not answered in one pass,
because the obsolete-contributions finding printed a single `work unlink`,
for the first closed target only, while two entry pages promised every
printed command clears the finding it was printed under.

This commit applies the review's preferred bounded correction:
`obsoleteFinding` now prints one `self work unlink` per closed target, in the
same stable order as the finding's own summary, and cell 53 exercises the
multi-target route end to end — every printed unlink, then standalone,
reaches a reconciled state with no unit retired. The two entry-page sentences
are narrowed to match what is actually printed: the steps for the chosen
route clear the finding, not each command alone. The receipt is finalized in
this commit by the independent follow-up reviewer `review-457-f1`, which
wrote no production code or copy: it records F1 as resolved, cell 53 passing
against the shipped build and failing against a build with only the fixed
line reverted, and a fresh digest over the seven content files. Verdict
`ready`.

Closes #417

Signed-off-by: rayim <rayim@inflike.com>
@tonite31
tonite31 force-pushed the feat/417-objective-check branch from 4ace65a to a7a0431 Compare September 5, 2026 16:25
@tonite31
tonite31 marked this pull request as ready for review September 5, 2026 16:26
@tonite31
tonite31 merged commit ae9ef9c into main Sep 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Enforce one objective, milestone, and work-management contract across Agents

2 participants