Flag provenance sessions with an unverified document origin - #96
Merged
adalton merged 2 commits intoAug 4, 2026
Merged
Conversation
WalkthroughChangesProvenance origin tracking
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 12✅ Passed checks (12 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
tchughesiv
marked this pull request as ready for review
August 4, 2026 20:41
tchughesiv
marked this pull request as draft
August 4, 2026 20:58
- `provenance_kind()` only checks whether every event in a log is
`commit`; it never checks what the *first* event actually was. A
session starting at `/respond`, `/revise`, or a manual-edit record
(no prior `/draft` or `commit` snapshot) rendered `provenance_kind:
"session"` — identical to a document that went through `/draft`
correctly — with no disclaimer and no distinguishing signal.
- Add an explicit `origin_untracked` boolean, computed independently
of `provenance_kind()`: false for an empty log or a `commit_only`
log (already covered by its own disclaimer), otherwise true unless
the log's first-ever event was `draft`. Wired into the machine-
readable metrics comment and into a new conditionally-rendered
footer disclaimer line.
- Fix is fully contained in `_shared/scripts/provenance.py` — no
`respond.md`/`revise.md` instruction changes needed. Once the
shared script flags `origin_untracked`, every workflow-level path
that can reach the bug (including `/respond`'s PR-number/file-path
fallback) is honestly labeled.
- Bump `_shared/provenance-schema.md` 0.1.0 -> 0.2.0 (MINOR: new
field + new conditional footer line, not a wording-only change).
Cascade-bump `prd`/`design` SKILL.md (PATCH: 0.6.3 -> 0.6.4,
0.6.0 -> 0.6.1) since both transitively consume the shared script.
- **Independent boolean over a synthetic commit event** (the issue's
other suggested fix). Verified by code trace that inserting a
synthetic `commit` event before the first authoring event would
not change the rendered output in the common case —
`provenance_kind()` and `build_footer()` would need rewriting
anyway, at which point the explicit flag is simpler and doesn't
mutate the existing, tested event-list shape.
- **Covers `manual-edit` as well as `respond`/`revise`**, beyond the
issue's literal text — diagnosis found a fifth reachable path via
`record-manual-edit.md` (invoked from inside `revise.md`) that
produces the identical bug shape.
- **Self-review correction before this commit**: an independent
same-model review caught that the first-draft `origin_untracked()`
(checking only `events[0]["phase"] not in ("draft", "commit")`)
still misclassified a log that started as a bare `commit`
safety-net snapshot and later picked up a real authoring event
(e.g. `[commit, revise]`) as origin-tracked. Corrected to treat
origin as tracked only when the log is still `commit_only` or its
first event was `draft`.
- [x] 40/40 unit tests pass (`python3 -m unittest discover -s
_shared/scripts -p 'test_*.py'`), including 21 new regression
tests for respond/revise/manual-edit-first, draft-first and
commit-only controls, and the commit-then-authoring composite case
- [x] Deterministic manual reproduction re-run against the fix in an
isolated scratch repo: bug case now renders the disclaimer; both
control cases render unchanged
- [x] Full CI-equivalent validation gate green: pre-review-checks.py
(228 pass, 1 pre-existing unrelated warning), skillsaw lint
(0 errors), markdownlint-cli2 (0 errors), validate-versions.sh
(0 errors), lychee link check (0 errors)
- [x] Verified zero file/logic overlap with companion PR flightctl#95 (issue
flightctl#93) via `git merge-tree` simulation — only expected friction is a
trivial version-number conflict on `prd/SKILL.md`/`design/SKILL.md`
Fixes flightctl#94
Assisted-by: Claude Opus 4.6 (1M) <noreply@anthropic.com>
tchughesiv
force-pushed
the
bugfix/94-provenance-origin-untracked
branch
from
August 4, 2026 21:11
d52e683 to
c6d1762
Compare
… sessions provenance.json is gitignored and session-local. If that local log is missing when a phase resumes (fresh clone, new worktree, cleaned .artifacts/, a CI runner), the next captured event becomes a fresh events[0] even when the document was genuinely drafted earlier. The flag also doesn't self-heal since capture_event only appends. Document the mechanism and the manual recovery step. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Tommy Hughes <tohughes@redhat.com>
tchughesiv
marked this pull request as ready for review
August 4, 2026 21:28
adalton
approved these changes
Aug 4, 2026
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.
Title
[#94]: flag provenance sessions with an unverified document origin
Problem
The provenance footer (
## Provenancein published PRD/design docs) is meant to flag documents whose structure was never verified against the template from origin. Butprovenance_kind()only checks whether every event in the log iscommit— it never checks what the first event actually was. A session that starts at/respond,/revise, or a manual-edit record (no prior/draftorcommitsnapshot) rendersprovenance_kind: "session", identical to a document that went through/draftcorrectly — with no disclaimer, no distinguishing signal. Reviewers and automated triage tooling consuming the footer have no way to tell the two apart. Already happened in production:osac-project/enhancement-proposals#124.Root Cause
provenance_kind()(_shared/scripts/provenance.py) is a binary classifier —commit_onlyvssession— with no check onevents[0]["phase"]. Five reachable call sites can produce a log whose first-ever event isrespond,revise, ormanual-edit:prd/skills/respond.md,design/skills/respond.md,prd/skills/revise.md,design/skills/revise.md(all callcapture-provenance-eventunconditionally), and_shared/recipes/record-manual-edit.md(invoked from insiderevise.md's manual-edit detection). The existingcommit-snapshot safety net inrender_footer()only fires whenprovenance.jsondoesn't exist yet — but every one of those five paths createsprovenance.jsonviacapturebefore the corresponding render step runs, so the safety net is structurally unreachable from them. Full analysis in.artifacts/bugfix/94/root-cause.md.Fix
Added an explicit, independently-computed
origin_untrackedboolean:Wired into
build_metrics_payload()(neworigin_untrackedfield in the machine-readable comment) andbuild_footer()(new disclaimer line, conditionally appended, mirroringCOMMIT_ONLY_NOTE's pattern). Purely additive — no existing branch, field, or test assertion changes shape for any previously-correct case.An independent self-review round (before this PR was opened) caught a gap in the first-draft version of this function: it originally checked only
events[0].get("phase") not in ("draft", "commit"), which meant a document that started as a barecommitsafety-net snapshot (never drafted) and later picked up a real authoring event — e.g.[commit, revise]— was still classified as origin-tracked, silently reproducing the same bug via an uncovered path. Corrected to the version above, which treats a log as tracked only if it's stillcommit_only(covered by its own disclaimer) or its first-ever event wasdraft.Files changed:
_shared/scripts/provenance.py—origin_untracked(), wired intobuild_metrics_payload()/build_footer()_shared/scripts/test_provenance.py— 21 new regression tests_shared/provenance-schema.md— documents the new field/disclaimer (0.1.0→0.2.0, MINOR perAGENTS.md's versioning rules — this is a behavioral schema addition, not a wording-only change). Also adds a "Limitations" bullet noting thatorigin_untrackedreflects the local session log only: sinceprovenance.jsonis gitignored, a lost local log (fresh clone, new worktree, cleaned.artifacts/, CI runner) can make a genuinely-drafted document renderorigin_untracked:true, and the flag doesn't self-heal on a later/draftrun. Recovery and a proposed rehydration fix are tracked separately in provenance: recover origin_untracked false positives when the local session log is lost #97 — out of scope here since it's an orthogonal enhancement, not a regression from this fix (the prior behavior for this same scenario was a silent false negative, i.e. exactly issue Provenance has no signal for a session that starts at /respond or /revise with no /draft (or commit-snapshot) origin — affects prd and design #94).prd/SKILL.md,design/SKILL.md(both0.7.0→0.7.1) — PATCH cascade bumps only (no content changes) perAGENTS.md's shared-file cascade rule, since both workflows transitively consumeprovenance.py/provenance-schema.md. Rebased ontomainafter companion PR Fix /revise and /respond skipping project-level template overrides in prd and design #95 merged (which had already bumped both files to0.7.0); re-bumped past that to0.7.1to preserve the cascade.No changes to
respond.md/revise.mdinstruction files were needed — the issue's own framing holds: closing the gap in the shared script covers every workflow-level path that can reach it, including/respond's PR-number/file-path fallback.Testing
python3 -m unittest discover -s _shared/scripts -p 'test_*.py'), including 21 new regression tests covering:respond/revise/manual-editas the first event (the reported bug),draft-first andcommit-only control cases (unaffected), and thecommit-then-authoring composite case caught during self-review..artifacts/) re-run against the fix: bug case now renders the disclaimer andorigin_untracked:true; both control cases (draft-first,commit_only) render unchanged withorigin_untracked:false.pre-review-checks.py, 229 pass / 1 pre-existing unrelated warning),skillsaw lint(0 errors),markdownlint-cli2(0 errors, 229 files),validate-versions.sh(0 errors),lycheelink check (0 errors). Re-verified after rebasing ontomainpost-Fix /revise and /respond skipping project-level template overrides in prd and design #95 merge.Full test report:
.artifacts/bugfix/94/verification.md.Confidence
HIGH — the bug was proven by direct, deterministic reproduction (not inferred from logs), the fix is small and purely additive, and a same-model self-review round independently caught and closed a real gap in the first-draft fix before this PR was opened.
Rollback
Revert this commit. The change is additive-only (one new JSON field, one new conditionally-rendered footer line) — reverting restores the exact prior behavior with no data migration, since
provenance.json's persistedschema_versionis unchanged.Risk Assessment
LOW — no changes to workflow instruction files (
respond.md/revise.md), only to the shared provenance script, its tests, and its schema doc. Companion PR #95 (issue #93) touched a disjoint file set (respond.md/revise.md/draft.md/controller.md/README.mdinprd/design, plus a newtemplate-override-resolution.mdrecipe) with zero logic overlap — confirmed viagit merge-treesimulation before #95 merged. #95 has since merged intomain(64ad5c1); this branch was rebased on top of it and the one anticipated conflict — the version lines onprd/SKILL.md/design/SKILL.md, which #95 had already bumped to0.7.0— was resolved by re-bumping both to0.7.1. No other conflicts.Fixes #94
Summary
_shared/for PRD and design workflows.origin_untrackeddetection for sessions that start with/respond,/revise,manual-edit, or other non-draftevents.commit_onlyhistories.0.1.0to0.2.0.0.6.1and the PRD skill to0.6.4.