Skip to content

feat: keep plan, results, and build evidence on the metadata branch; ship the spec with the PR - #398

Merged
danielhanold merged 28 commits into
mainfrom
feat/keep-plan-results-and-build-evidence-on-the-metadata-branch
Oct 6, 2026
Merged

danielhanold merged 28 commits into
mainfrom
feat/keep-plan-results-and-build-evidence-on-the-metadata-branch

Conversation

@danielhanold

@danielhanold danielhanold commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

↩ Change 0530 — Keep plan, results, and build evidence on the metadata branch, and ship the spec with the PR

Moves a change's plan, results, and build evidence off the PR. Plan and results are written to the docket metadata branch by change.attach-plan / change.attach-results (now --markdown); build evidence lives in a ## Build evidence section of the change record, read by the finalize merge gate, clear-block, the rebase no-op skip, and run.verify. The feature branch's first commit is a spec copy (workspace.commit-spec), so a PR carries the spec plus code. Same-branch links become relative; the post-merge backlink commit to main, artifact.backlink, the Docket-Plan-Path trailer, and finalize.skip_results_only_delta are retired. ADR-0141.

Cutover: finish every in-progress/implemented change on the current binary before installing this one; then run docket repository repair once. This PR itself was built on the previous flow (its plan and results ride this branch, evidence is in this description), as the spec requires.

Review (deep tier) — dispositions

# Severity Finding State
1 important Attach idempotency key ignored the record revision, so attaching X, Y, X replayed the first X and left Y fixed — 349f786
2 important implement-next Step 4/5 refreshed the claim with a revision the child's attach had already moved fixed — 19b8cea
3 minor Killed legacy records would get dead relative plan/results rows after repair fixed — 756d75d
4 minor CLI reference omitted workspace commit-spec fixed — 4349e27
5 minor edge-paths/SKILL prose said the PR-body back-link is skill-side fixed — 4349e27

command: go run ./cmd/docket development test
result: green
head_sha: a17fd60
ran_at: 2026-10-06T09:49:42Z

Docket-Plan-Path: docs/superpowers/plans/2026-10-05-keep-plan-results-and-build-evidence-on-the-metadata-branch.md
pr publish keeps verifying --evidence against the head but weaves only the
backlink block into the PR body (assemblePRBody drops its record
parameter); an authored build-evidence block is preserved as authored bytes.
finalize publish and evidence recertify no longer edit the PR: after the PR
reprobe the change record's "## Build evidence" write is the publication
(publishResultFromRecord replaces publishResultFromEnsure). Removed
finalizePublishEnsurer, mapPublishEnsureFailure, mapRecertifyEnsureFailure,
and the reasons body-assembly-failed (publish/recertify), pr-editor-unavailable,
pr-edit-contended, and pr-edit-unknown. evidence.recertify is metadata-write
only.

Test changes:
- EvidenceRecertifyEditContended -> RecordContended (the record moved under
  the write).
- EvidenceRecertifyEditFailureThenRetry -> RecordFailureThenRetry (a failed
  record write, then convergence).
- Deleted EvidenceRecertifyEditUnrecognizedDisposition: it only exercised the
  PR-edit disposition mapping's default arm, which no longer exists.
- Deleted the dispositionEnsureGitHub and flakyEnsureGitHub fakes and
  fakePublishGitHub.lastEnsuredBody (no PR edit left to drive).
…s backlink

change.attach-plan now carries the plan Markdown (--markdown <file|->) and,
in one metadata transaction, writes docs/superpowers/plans/<file> on the
metadata branch behind its freshly rendered backlink (any submitted backlink
block is replaced), sets plan: and updated:, and re-renders the artifact
block and board. A re-plan at the linked path replaces the content; an
identical re-attach declares nothing.

New typed refusals: empty-markdown, authored-input-too-large,
artifact-path-mismatch (plan: already names another path), and
artifact-path-occupied (a file at the path whose backlink targets another
change). Malformed backlink markers and placeholder-only slots still refuse.
The feature-head, descends-from-base, single-artifact-delta, and plan-path
trailer checks are removed with their reasons and helpers.

run.verify reads the plan on the metadata tip; status checks the plan on
the metadata branch with an integration-branch fallback for records closed
before plans moved. attach-results is unchanged until it moves next.
…rs follow

change.attach-results now carries the results Markdown (--markdown <file|->)
and runs the same metadata transaction as attach-plan: it writes the results
file on the metadata branch behind its freshly rendered backlink, sets
results: and updated:, and re-renders the artifact block and board in one
commit. A later checkpoint at the linked path replaces the content; the
feature branch is never read or written, so a checkpoint after the gate
leaves the tested head (and its evidence) intact. Checkpoint-phase content
validation still refuses raw template scaffolding (results-content-invalid),
now before anything is read.

The feature-head driver is deleted with everything only it used: --commit,
ChangeAttachRequest.Commit, the WorkspaceDeps parameter, readAttachBlob,
verifyBacklink, and the commit-not-head, untracked-file, symlinked-plan,
missing-backlink, backlink-mismatch, and artifact-unreadable reasons, plus
the now-unminted empty-commit finding code. Both CLI verbs share one flag
set (--id --revision --path --markdown).

mark-implemented (condition 5) and run.verify read results on the pinned
metadata tip; a results file present only at the feature head is
results-identity-broken. status checks results on the metadata branch with
an integration-branch fallback for records closed before results moved.
The run-fence ownership fixtures now serve the plan and results on the
metadata branch too.
…branch

Plan and results live on the metadata branch, so the archive transaction's
retargetArtifactBacklinks already repoints every artifact backlink in the one
close-out commit. The integration-ref legs are retired: closeoutBacklinkOp and
runCloseoutBacklinkLeg (close-out), cleanupBacklinkOp and
finalizeCleanupBacklinkRepair (cleanup), sweepAssessBacklinkLeg (sweep), the
scoped backlinkArtifactLoader and backlinkLegDetail, backlinkLegRetarget /
backlinkLegHasWork, OperationFinalizeCloseoutBacklink, and both
final-backlink-pending reason constants. The PR-description backlink leg stays.
finalize.cleanup no longer declares the metadata-write effect (it commits
nothing).

New guard internal/repoguard/integration_push_test.go
(TestNoIntegrationPushOutsidePRMerge): every transaction.Request literal under
internal/app must target MetadataBranchName, and every direct
PushLease/PushCreateLease call must sit in an allowlisted function.

Tests deleted, with reasons:
- TestIntegrationFinalizeCloseoutBacklinkLegIgnoresUnrelatedCorpusErrors,
  TestIntegrationFinalizeCloseoutBacklinkPendingFindingNamesTheCause,
  TestIntegrationFinalizeCleanupBacklinkRepairIgnoresUnrelatedCorpusErrors:
  they pinned the scoped loader and pending finding of the retired
  integration-ref legs.
- finalize_backlink_loader_test.go: its subject file is deleted.
- TestAssessStaleBacklinkLegIsActionable,
  TestAssessMissingManifestWithStaleBacklinkIsActionable,
  TestAssessMalformedMarkersAreUnknownNeverNoWork: they assessed the retired
  sweep integration backlink leg.

Converted: setupCloseoutFixture seeds plan/results on the metadata branch with
relative backlinks; TestIntegrationFinalizeCloseoutBacklinkLegDocketMode became
TestIntegrationFinalizeCloseoutArchiveRetargetsAllArtifactBacklinks (one
metadata commit retargets spec/plan/results; origin/main stays the merge
commit); matrixCloseout, TestIntegrationFinalizeStateBytePreservation and
TestIntegrationFinalizeArchive* read plan/results on docket and assert no
integration commit; the clean-tombstone sweep assessment now proves a stale
integration-branch plan is no work; TestFinalLifecycleCodeSpellings drops the
two retired constants; retired-vocabulary row 57 has no successor.
…h the PR

Living docs describe the current layout: plan, results, and build evidence
on the metadata branch (evidence in the record's ## Build evidence section),
the spec copy as the feature branch's first commit, relative same-branch
links converted by repository repair, close-out retargeting every backlink
in the archive commit with no integration-branch push. Glossary entries
rewritten; the artifact backlink example, the retired `docket artifact`
noun, and the stale verify-run alias line are removed.

Residual retired-token hits (git grep -F over the whole tree):
- Docket-Plan-Path: docs/codex/fixtures/root-entry/certification.md (dated
  2026-09-01 certification record, point-in-time); testdata/bash-upgrade
  tarballs (frozen corpus).
- Docket-Results-Path, closeout-backlink, prBodyEvidence, lifecycleBranch,
  commitPlanFile: no hits outside point-in-time records.
- artifact.backlink: internal/repoguard/budgets_test.go re-baseline history
  comment (historical rationale).
- artifact backlink: internal/app/finalize_closeout_integration_test.go
  comment describing the metadata-branch retarget (current behavior).
- final-backlink-pending: retired-vocabulary guard row only.
- skip_results_only_delta: the obsolete-key tombstone (config schema,
  decode, tests), prose-contract absent pins, the upgrade guide's
  "ignores it, remove it" row, and frozen testdata corpora.
Review finding (important): change_attach.go changeAttachMetadata keyed its
idempotency RequestID and digest on (kind, id, path, content) only. The
engine's scanForRequest searches the whole metadata ancestry, so attaching
X, then Y, then X again replayed the first X receipt and left Y stored while
the caller saw applied. Fold the submitted revision into the digest payload
and (hashed) into the RequestID: a lost-response retry at the same revision
still replays, while earlier bytes at a later revision are a new request.

TestIntegrationWorkflowRepoChangeAttachRevertToEarlierContent pins both.
…atch claim refresh

Review finding (important): Step 4 refreshed the claim with the pre-dispatch
revision after the plan-writer's change.attach-plan had already moved the
record, so the refresh came back contended and stopped the build. The parent
now verifies the return, re-reads the revision on the re-synced tree, and
refreshes with it; the post-build refresh in Step 5 does the same, since a
build checkpoint (change.attach-results) also moves the record.
…ture branch

Review finding (legacyIntegrationArtifacts): a pre-cutover killed record
with plan:/results: set rendered relative metadata-branch links to files
that only ever lived on its feature branch, so repository check/repair
would rewrite them into dead links. legacyArtifactBranch now keeps a killed
record without a "## Build evidence" section on its feature branch, the
pre-cutover rendering; a killed record with the section stays relative.
F4: cli.md workspace summary names the commit-spec verb.
F5: edge-paths/SKILL.md say pr.publish owns the PR-body back-link and
plan/results links blocks; drop the stale skill-side claim. Regenerate
embedded twins.
The shared non-JSON file reader always said "reading --record", so a bad
--markdown, --evidence, or --request path was reported against a flag the
caller never passed. Each caller now hands the reader its own flag name.
Recertify can no longer edit a PR, so the refusal tests' no-PR-edit asserts
could never fail. They now assert the record, recertify's only durable
write, is unchanged.
@danielhanold
danielhanold merged commit d5b75d3 into main Oct 6, 2026
1 check passed
@danielhanold
danielhanold deleted the feat/keep-plan-results-and-build-evidence-on-the-metadata-branch branch October 6, 2026 09:57
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.

1 participant