docs(adr): seed manifest as durable per-root state#546
Merged
Conversation
The watermark tag formatter PolyphonyTags.RunStartedAt(DateTimeOffset) was called only in tests; production never wrote the tag. Per docs/decisions/run-reset.md the watermark is supposed to be stamped by reset (originally polyphony reset state, collapsed into polyphony reset root by AB#3308). The pattern->projection rewrite preserved the delete half of the state phase (ProjectionResetCatalog.cs:24, AdoWorkItemTagDeleter.cs:74-77) but dropped the stamp half. As a result, every detect-state / state next-ready call saw runStartedAt=null, the `mergedAt <= watermark` filter never fired, and any root with a prior merged plan PR was stuck in merged_unseeded forever. Introduces IRunWatermarkStamper / RunWatermarkStamper(ITwigClient) and wires it into ProjectionResetExecutor as the action of the state phase: when Execute && !SkipState, after the per-resource delete loop body, stamp a fresh polyphony:run-started-at=<UtcNow> tag (mirroring AdoWorkItemTagDeleter's sync-show-patch-sync pattern, defensively stripping any pre-existing watermark tags first). Fail-loud posture: twig exceptions propagate to the executor's outer catch, which records `state` in stepsFailed. Symmetric to PlanObserver.ReadRunStartedAtAsync's fail-closed read posture. Tests (9 added): - RunWatermarkStamperTests: no-prior, replaces, dedups duplicates, enforces sync-show-patch-sync order, throws when twig.show returns null. - ProjectionResetExecutorTests: Execute mode stamps once; dry-run doesn't stamp; SkipState doesn't stamp; stamper throw marks state phase failed. Dogfood verification: cloudvault root 62365430, reset --execute --allow-unjournaled stamps polyphony:run-started-at=2026-05-25T... and plan detect-state flips from merged_unseeded to not_started. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Polyphony PRs are agent-authored under the operator's PAT, so the PR's author_identity is the human operator. The prior rule 'comment author == PR author identity -> exclude' silently dropped the operator's own review threads -- exactly the human-in-the-loop intervention the loop must respect. Marker presence (PrCommentMarker) is the deterministic signal for bot-vs-human under a shared identity; identity-equality is not. Removes the identity-exclusion rule from the analyzer prompt in all three workflows (plan-level, github-pr, ado-pr) and from their load-bearing header comments. Vote rules no longer use the 'non-author reviewer' qualifier -- self-approval / self-changes-requested is a platform branch-protection concern, not the analyzer's. ADR: docs/decisions/pr-feedback-identity-classification.md Validation: all four lints (sentiment-loop-consistency, github-pr, ado-pr, plan-level) and all 76 Pester tests across their .Tests.ps1 files pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds ADR `seed-manifest-as-durable-state.md` capturing the design synthesized
from the four-lens debate (Bach/Mahler/Mozart/Sibelius/Beethoven) and
greenlit by Daniel on 2026-05-29.
Key decisions encoded:
- Seed manifest at `.polyphony/state/{rootId}/seed-manifest.json`
with atomic writes (`.tmp` + rename).
- `polyphony:plan-child-id` marker as the canonical reconciliation
primitive (no title hashing).
- Rich `plan_generation` linkage `{id, parent, cause, created_at}`
with manifest items carrying `introduced_in` for orphan detection
across renegotiation.
- Script-internal retry (3 attempts on exit codes 3 and 5; code 1
permanent) — `max_attempts` is not available on `type: script`
conductor nodes.
- New `seeding_blocked` terminal, distinct from `workflow_abandoned`
(which is reserved for operator-volitional abandonment).
- GitHub explicitly out of scope; ADO-only execution.
- Verb evolution on `plan write-plan` and `plan seed-children` — no
new verb names.
Open follow-up questions documented in §11 of the ADR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Captures the design for the seed manifest — durable per-root JSON state
that makes polyphony seeding restart-friendly without trusting corrupt
state.
Greenlit by Daniel on 2026-05-29 after a four-lens team debate
(architecture / engine / verb-error / platform).
What's in the ADR
polyphony:plan-child-id)plan_generationlinkage for renegotiation orphan detectionseeding_blockedterminal vs.workflow_abandonedRelated
polyphony-verb-error-boundary.md(exit codes)gate-compression-pattern.md(the gate this design replaces)Status
Accepted. Implementation work tracked separately — this PR is the ADR only.