Skip to content

Make the implement Phase 4.1 documentation gate record only run-specific workpad facts #2129

Description

@The01Geek

Problem Statement

As the PRFlow maintainer, I want the /prflow:implement Phase 4.1 documentation gate to record only real, run-specific facts on the workpad, so that workpads stop carrying a scripted boilerplate note and never tick a documentation-coupled acceptance criterion on evidence that does not yet exist.

Two things go wrong at the same gate today. First, every implement run writes the same fixed sentence to the workpad, and that sentence is false: it says the gate cannot see a warning that the gate can in fact see. Second, when a deferred acceptance criterion asks for a check to be run, the gate lets the run tick it while pointing at a later step as proof, before that later step has happened. Both fixes live in the same phase file.

Current Behavior

Triggering steps: run /prflow:implement on any issue whose acceptance criteria include a documentation-owned criterion that names a check command, and read the issue workpad after Phase 4.1. Observed on issue #2123 (cloud implement tier, workpad comment https://github.com/The01Geek/prflow/issues/2123#issuecomment-5458815030).

Observed result:

  • At 00:13:14 the workpad gained the fixed note "Phase 4.1: extractor span-suppression breadcrumbs are not durably observable on the cloud tier (stderr not captured); a suppressed command/grant literal in the Documentation Needed block leaves no run-record trace". The same sentence is scripted into the phase file, so every run writes it, including a run in which no span was suppressed.
  • At 00:15:32 the workpad ticked AC8 ("lib/test/lint-internal-docs.py reports no new violation") with a note saying the docs subagent reported 0 new violations and that this was "re-confirmed over the final committed tree by the Phase 4.3 whole-suite pass". The Phase 4.3 pass ran at 00:38:26, 23 minutes later. No command output for the lint appears anywhere on the workpad.

Expected result: a workpad note about a suppressed span appears only in a run where the extractor actually suppressed one, and names that span; a deferred criterion that names a check command is ticked only after that command has run in the same run over the landed docs, with the command's result quoted in the tick note and no reference to a step that has not run yet.

Environment: the cloud implement tier (GitHub Actions). The prose that causes both behaviors is tier-independent, so the local tier behaves the same way.

Desired Behavior

The helper that reads the Documentation Needed block, scripts/read-doc-needed-deliverables.sh, prints one extra self-identifying stdout line, docgate-suppressed: <span>, when the extractor suppressed a span, carrying the first suppressed span's text with the breadcrumb's surrounding backticks removed. Phase 4.1 Stage 1 records a workpad note naming that span only when such a line is present, passing the text through a file rather than a shell argument, and the fixed once-per-run disclosure sentence is gone from the phase file.

A deferred documentation criterion that names a check command is ticked at Phase 4.1 only after the orchestrator has executed, in its own tool call over the landed docs, the command the criterion names — when the tier does not grant that command, the granted covering run that lib/test/modules/coverage-map.json names for it — and the tick note quotes the result line of the command actually run. A subagent's report that it ran the command does not discharge the criterion. A tick note names no result that has not been produced yet. When the tier refuses both forms, the criterion stays unticked and the run takes the paragraph's existing Blocked arm, with the reflection naming prflow_implement.allowed_tools as the remedy.

User Impact

The maintainer reading a workpad sees a suppressed-span note only when it carries a real fact, and sees a doc-criterion tick backed by evidence the run actually holds. The weekly retrospective's gate signals do not move, because they read workpad reflections, not notes.

Technical Context

Scope note: The files and details below are the known starting points, not the full list. Before implementing, trace the change through the codebase to find every affected call site, consumer, and layer — this issue maps the work, it does not bound it.

  • Relevant Classes/Files — skills/implement/phases/phase-4-documentation.md (the disclosure paragraph near line 89 and the deferred doc-AC discharge paragraph near line 177); scripts/read-doc-needed-deliverables.sh (the read boundary whose stdout the gate parses); scripts/extract-doc-needed-paths.sh (the only writer of the breadcrumb); lib/test/run.sh (the extract-doc-needed-paths.sh: command and grant literals inside the Documentation Needed block are tokenized into phantom doc deliverables that Block implement runs #644 and Phase 4.1's Documentation-Needed read produces no observable value and its branch logic is untestable, because it is inline shell written twice #1554 pins); docs/internal/implement-skill.md (the owning page).
  • Verified: skills/implement/phases/phase-4-documentation.md says the extractor emits a "breadcrumb on stderr this gate does not capture" and scripts the fixed --note text quoted above into Stage 1.
  • Verified: scripts/read-doc-needed-deliverables.sh states the opposite in its header — the caller reads a "tool result that merges this command's stdout with the stderr of" the extractor — so the breadcrumb is visible to the agent in every run; it is only never recorded.
  • Verified: scripts/extract-doc-needed-paths.sh prints "suppressed a span (a command/grant/skill literal, or a path mixed with non-path tokens" to stderr at most once per run, from suppress_span(), and exposes the span on no other channel.
  • Verified: skills/implement/phases/phase-4-documentation.md discharges a deferred doc-AC on one piece of evidence — "confirm the docs the criterion required actually landed in this run's diff" — and says nothing about a criterion that names a check command.
  • Verified: skills/implement/phases/phase-3-ac-gate.md defers only a documentation edit, one that "is left unticked at this gate, recorded in a workpad deferral note naming the AC"; on Grant three drift-detecting helpers to the cloud implement tier and mirror them into the matcher-probe EXTRAS list #2123 a check-command criterion was deferred anyway, so the Phase 4.1 paragraph must cope with that shape.
  • Verified: lib/test/run.sh pins that "P4_FILE quotes the extractor's actual breadcrumb phrase" exactly once, and its Phase 4.1's Documentation-Needed read produces no observable value and its branch logic is untestable, because it is inline shell written twice #1554 fixture matrix asserts the exact stdout lines of the helper for an adversarial body.
  • Verified: docs/internal/implement-skill.md repeats the false premise — the breadcrumb is "disclosed by Phase 4.1 as ephemeral on the cloud tier" — and must be corrected with the change.
  • Verified: .prflow/prompt-extensions/implement.md requires a changeset for a "fix, feature, or breaking change to the engine surface", which includes skills/ and scripts/.
  • scripts/workpad.py has no structure that ties an acceptance-criterion tick to a recorded command result: --tick-ac-n flips a row, --note appends text under a 2048-byte budget, and the completion-evidence flags cover the whole-suite gate only. The evidence therefore lives in the tick note's text.
  • Architecture Alignment — the helper already owns the gate's stdout contract (self-identifying prefixes, never positions), so a third prefix is the same pattern; the phase file keeps routing on docgate-outcome: and reads the new line by prefix.
  • Dependencies — none new. The helper and workpad.py are already invoked by Phase 4.1 on both tiers, so no cloud grant changes. The helper and the phase file reach a consumer in the same vendored plugin fetch, so an old helper beside a new phase file cannot occur; a consumer that has not upgraded keeps today's behavior.
  • Data/Schema Considerations — none.
  • Cross-layer Impact — one shipped helper, one shipped phase file, its test pins, one internal doc page, one changeset.

Acceptance Criteria

The helper's stdout lines are observed through the #1554 fixture matrix in lib/test/run.sh: rdnd_lines keeps the docgate- lines, and rdnd_run is the unfiltered capture with stderr merged.

Implementation Notes

Generated via /prflow:create-issue (v2.36.15, medium)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions