Skip to content

fix(planning): export the restated deferred, planning-owned and decisions sections into the Brief - #9952

Merged
melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-9895-40179285448-1
Oct 25, 2026
Merged

melodic-automation-lanes[bot] merged 1 commit into
mainfrom
work-resolve-issue/issue-9895-40179285448-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Closes #9895

Summary

Opened by the work-resolve-issue lane. The run's own summary:

export-brief dropped three sections of a confirmed restatement. It now writes the decisions recap as a ### Decisions section (only when non-empty, so Briefs without one keep their shape). It also appends the restated deferred and planningOwned bullets to ### Deferred questions, after the register's retired rows. Each bullet stays as written, so a bullet the restatement leads with its source Q<N> keeps that lead. Each is tagged arbiter /planning:plan, or USER-RESERVED when it leads with a user-reserved row's Q<N> or says USER-RESERVED, so a user-reserved question never gains a plan-arbiter entry.

Not verified

  • The new tests and python3 -m unittest discover -s plugins/planning/surface -p 'test_exporters.py' were not run: this lane's Bash allows only the named wrappers, so no Python ran. That the new test passes on the branch and fails on the base exporters.py was checked only by reading the code. Left to
  • ruff and surface-checks.sh were not run on the touched Python, for the same reason; check-affected reported no Python lint failure
  • The repo's fragment tool (new-changelog-fragment) refused to run because HEAD is detached, so the fragment was written by hand in its documented shape and named after this issue rather than the branch slug; check-changelog-fragments validates it

Fix

  • plugins/planning/surface/exporters.py: new LEAD_QN and restated_deferred(); export_brief writes ### Decisions from the confirmed rev's decisions and appends the restated deferred/planningOwned entries to Deferred questions (the - none line now appears only when both lists are empty); the
  • plugins/planning/surface/test_exporters.py: two tests in TestBriefRestatements, one for every deferred, planningOwned and decisions bullet reaching the Brief (the first two under Deferred questions) and one for the USER-RESERVED arbiter carried from a reserved ledger row, a lowercase q<N> lead
  • plugins/planning/skills/interview/context/surface.md: the restate row states which sections export-brief exports and where, the arbiter tagging, and that each deferred/planningOwned bullet leads with its source Q<N> where it has one
  • plugins/planning/surface/README.md: the export-brief row names the Decisions section and the deferred/planningOwned entries
  • .changes/planning/fix-9895-export-restated-sections-6c1e94a7.md: planning changelog fragment, bump: patch, under Fixed

Verification

The runner ran each check from the base copy against b1f6d88:

  • scripts/check-changelog-fragments.sh --check: passed

The run reports:

  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-changelog-fragments: all 6 fragments valid (run after the final edit)
  • /home/runner/work/claude-code-plugins/claude-code-plugins/.lane/checks/bin/check-affected: 10 passed, 6 skipped over 5 changed files (run after the final edit)
  • Grep of plugins/: export-brief / export_brief is called only from plugins/planning/surface/round.py and its tests. The design and prd skills never call it, so their output is unchanged.
  • Read plugins/planning/scripts/check-open-questions.sh: its --brief lookup only needs each retired Q<N> somewhere in Deferred questions, and its --procedure heading check only requires the template headings to be present, so extra entries and a ### Decisions heading pass
  • Fresh-context review subagent over the whole diff: no blocking bugs. It traced both new tests by hand as passing on the branch and failing on the base exporters.py, and found no existing test that breaks. It also raised four low-impact points. Fixed: a lowercase q<N> lead was missed (now match
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40179285448

Left out: the items under Not verified.

Related

#9895

Lane-Activity: work-resolve-issue/resolve-issue
@github-actions

Copy link
Copy Markdown
Contributor

claude-security-review reviewed b1f6d884d39fa7139cb913b2e4dfd42e33cd63cd: 0 finding(s), 0 as inline comments.

No security issues found in PR #9952 at b1f6d88.

critical-findings: 0

  • Scope: The change makes export-brief write a confirmed restatement's decisions, deferred and planningOwned sections into the PLAN.md Brief. It also adds docs, tests and a changelog fragment.
  • Injection: The new bullets go through the existing bullets() and para() sanitizers. Each is a single line, and a leading #, `, ~, -, >, * or + is escaped. A restatement section cannot start a heading, a fence or a register row in the Brief. LEAD_QN has no nested quantifiers, so it can't backtrack badly.
  • Trust gate: The arbiter tag fails toward the more restrictive value only when the bullet leads with a user-reserved row's Q<N> or says USER-RESERVED. A reserved row that a bullet mentions without leading with its Q<N> gets /planning:plan. The register's own rows for that question are still exported with their real arbiter. The restatement is user-confirmed, and the docs tell the author to lead each bullet with its Q<N>. I'm not reporting this as a finding, since I found no concrete exploit path.
  • Manifests and trusted paths: No plugin.json or marketplace.json change. No file matches the trusted-path globs.
  • Instruction surface: surface.md only gains text and removes no rule. The PR context contains no embedded directives.
  • Not run: I had no shell, so I did not run the tests. The PR description also says they were not run.

@github-actions

Copy link
Copy Markdown
Contributor

claude-review reviewed b1f6d884d39fa7139cb913b2e4dfd42e33cd63cd: 0 finding(s), 0 as inline comments.

No blocking or advisory findings. I read the full diff, the PR context and closing issue #9895. I also read the surrounding exporters.py (bullets, para, register, ledger_row, export_brief) and the --brief lookup in plugins/planning/scripts/check-open-questions.sh. I ran no tests and no code, because this lane has no shell. Every claim below comes from reading the code. The PR's own test and lint claims are author-claimed and unverified.

Closing issue #9895 criteria

  • New test for the three sections: test_restated_deferred_planning_owned_and_decisions_reach_the_brief builds a confirmed restatement with non-empty deferred, planningOwned and decisions. It asserts every bullet appears, the first two under ### Deferred questions. Met by reading.
  • Test fails on main and passes on the branch: On the base exporters.py, self.section(text, "Decisions") would raise IndexError, because the heading is never written. By reading, this holds. I did not run it.
  • python3 -m unittest discover -s plugins/planning/surface -p 'test_exporters.py' exits 0: unverified, since I did not run it. Tracing both new tests by hand against the code, I expect them to pass.
  • Planning changelog fragment: .changes/planning/fix-9895-export-restated-sections-6c1e94a7.md is present with bump: patch under Fixed. A patch bump fits a fix to what the export drops.
  • State which restate sections export, in surface.md: the restate row now does this.
  • Design and prd output unchanged: the PR reports a grep showing export_brief is called only from round.py and its tests. I did not re-run that grep.

Downstream check: The check-open-questions.sh --brief lookup only needs each retired Q<N> to appear in the Deferred questions section. Register rows are still emitted first, so extra restated entries and a new ### Decisions heading do not break it.

Manifests: no plugin.json or marketplace.json changes in the diff, so no manifest lines apply.

Spend: nothing in this change touches billing or prepaid usage, so there is no hold.

Minor edge cases, not findings

  • A restated bullet is tagged USER-RESERVED only when it leads with a reserved row's Q<N> or contains the literal USER-RESERVED. The docs say so. A bullet that mentions a reserved question mid-sentence gets the plan arbiter. A bullet like "no longer USER-RESERVED" gets the user arbiter.
  • The ; **arbiter: …** suffix is appended after any trailing punctuation in the bullet, so it can read .; **arbiter…**.

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The unattended merge path armed native auto-merge at head b1f6d884d39fa7139cb913b2e4dfd42e33cd63cd.

@melodic-automation-lanes
melodic-automation-lanes Bot added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit ca25691 Oct 25, 2026
47 checks passed
@melodic-automation-lanes
melodic-automation-lanes Bot deleted the work-resolve-issue/issue-9895-40179285448-1 branch October 25, 2026 09:36
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.

fix(planning): export the restated deferred, planning-owned and decisions sections into the Brief

0 participants