From dd643867ecce420a58b697a42e7718a62af5c758 Mon Sep 17 00:00:00 2001 From: William Thorsen Date: Thu, 16 Jul 2026 19:12:01 -0700 Subject: [PATCH 1/4] agents|fix: Sweep ticket and plan for missed decisions before saving Fixes a gap where the ticket and plan produced by `design-and-plan` and `plan` could reach a developer or another agent missing decisions the design conversation had settled. Both skills are now instructed to re-read the artifacts against the conversation before saving them, and to fold in whatever never reached them: rejected alternatives, agreed constraints and scope boundaries, edge cases and success criteria raised in discussion, and context the implementer would otherwise have to rediscover. Amendments are reported without reopening approval, so closing the gap costs no extra round trip. `design-and-plan` is now instructed to offer the remote-issue update after this check rather than before it, with the aim of sending the issue a complete ticket rather than one amended afterward. --- .../_partials/ticket-and-plan-completeness.md | 16 ++++++++++++++++ .../content/skills/design-and-plan/SKILL.md | 18 +++++++++++------- packages/agents/content/skills/plan/SKILL.md | 4 ++++ 3 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 packages/agents/content/skills/_partials/ticket-and-plan-completeness.md diff --git a/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md b/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md new file mode 100644 index 00000000..5378708d --- /dev/null +++ b/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md @@ -0,0 +1,16 @@ +**Sweep the artifacts for anything the conversation settled that never reached them.** After the plan is approved or drafted, before the artifacts are saved, re-read them against the conversation and apply the handoff test: could a competent developer, reading only the ticket and plan with no access to this conversation, achieve the intended result and make the same decisions? Whatever fails that test is a gap. + +This sweep is the completeness twin of the [concision](../_data/concision.md) self-check: that one asks what can be cut, this one asks what was never captured. They are a deliberate pair, not competing pressures. An artifact that drops a settled decision isn't concise, it's incomplete. + +Run the sweep in the main session, never in a subagent. Only the session holds the conversation the artifacts are swept against. + +**Sweep for:** + +- Settled decisions, including the alternatives they rejected. +- Constraints and scope boundaries the conversation agreed on. +- Edge cases and success criteria raised in discussion that never reached the acceptance criteria. +- Tacit context of the form "the implementer might not realize X" — what the conversation established as known and the artifacts leave the reader to rediscover. + +**Route each gap by kind**, per the placement doctrine: the change's subject and outcomes fold into the ticket, mechanism folds into the plan. Where the gap came up in conversation does not decide where it lands. When the invocation produces no ticket artifact, a subject-level gap folds into the plan's context section. + +**Report and proceed.** When the sweep finds gaps, fold them in and report the amendments as a brief list, then save. The report is informational: the amendments carry what the approval already covered, so it opens no new approval gate and asks nothing. When the sweep finds nothing, save silently — a clean sweep is not worth a line. diff --git a/packages/agents/content/skills/design-and-plan/SKILL.md b/packages/agents/content/skills/design-and-plan/SKILL.md index 3ea0e10b..cdd029d2 100644 --- a/packages/agents/content/skills/design-and-plan/SKILL.md +++ b/packages/agents/content/skills/design-and-plan/SKILL.md @@ -28,7 +28,7 @@ Do NOT generate the implementation plan until the design has been agreed upon an ### Phase 1: Resolve task source and assess relevancy -1. **Resolve the task source** using the [ticket source resolution](../_data/ticket-source-resolution.md) table. Request the `updatedAt` field for use in the relevancy check. Store the resolved metadata for use in the relevancy check and Phase 4's optional remote update. When the source resolves to a URL, persist it to the branch manifest per [Stored ticket URL](../_data/ticket-source-resolution.md#stored-ticket-url) so a later session needs no ticket argument. +1. **Resolve the task source** using the [ticket source resolution](../_data/ticket-source-resolution.md) table. Request the `updatedAt` field for use in the relevancy check. Store the resolved metadata for use in the relevancy check and Phase 6's optional remote update. When the source resolves to a URL, persist it to the branch manifest per [Stored ticket URL](../_data/ticket-source-resolution.md#stored-ticket-url) so a later session needs no ticket argument. 2. **Assess relevancy** — determine whether the ticket may be stale and, if so, verify it is still relevant. @@ -108,11 +108,6 @@ Here, _the implementation_ is the plan artifact (Phase 5): mechanism the ticket Present the ticket to the user. Revise until approved. -**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference). This is a shared-state action — do not update without explicit consent. - -- GitHub: Write the refined body to a scratch file using the [gh body file](../_data/gh-body-file.md) pattern, then `gh issue edit {number} --body-file "$body_path"`. -- Other platforms: Note that automated update is not yet supported; suggest manual update - ### Phase 5: Generate implementation plan @@ -129,7 +124,11 @@ Produce a plan that gives a competent coder everything they need — and enough Present the plan to the user. Revise until approved. -### Phase 6: Save artifacts and stop +### Phase 6: Sweep for completeness, save artifacts, and stop + + + +Then save both artifacts: 1. Resolve artifact directory using `save-artifact` conventions: - Invoke `node {harness_home_dir}/skills/derive-session-context/derive-session-context.mjs` via Bash to obtain `ticket_id`, `project_slug`, and `artifact_base_dir` from the manifest JSON emitted on stdout (auto-generate ticket ID as `{YYYYMMDD}-{4 random hex}` if none found) @@ -154,6 +153,11 @@ Design and plan complete: Plan: {plan_path} ``` +**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference). This is a shared-state action — do not update without explicit consent. The offer joins the next-steps block below as an additional ask, keeping that block's identifiers; it never opens a turn of its own. On consent: + +- GitHub: Write the refined body to a scratch file using the [gh body file](../_data/gh-body-file.md) pattern, then `gh issue edit {number} --body-file "$body_path"`. +- Other platforms: Note that automated update is not yet supported; suggest manual update + Follow the options, output format, and recommendation rules in [next-steps options](#next-steps-options) exactly. Do not improvise the options. The plan was developed interactively with user approval at each stage — use this as recommendation context. Include both `{ticket_path}` and `{plan_path}` in each skill-invoking option line. diff --git a/packages/agents/content/skills/plan/SKILL.md b/packages/agents/content/skills/plan/SKILL.md index 9d1dc64b..9791dc7e 100644 --- a/packages/agents/content/skills/plan/SKILL.md +++ b/packages/agents/content/skills/plan/SKILL.md @@ -36,6 +36,10 @@ The body following the frontmatter uses the shared implementation-plan template, - Call out risks and unknowns explicitly - When comparing approaches, rank options per [design priorities](../_data/design-priorities.md) +## Sweep for completeness + + + ## Saving Resolve artifact directory based on context. From 4949e68d200b2abea244d911c2eeb53b729a07d2 Mon Sep 17 00:00:00 2001 From: William Thorsen Date: Thu, 16 Jul 2026 19:33:26 -0700 Subject: [PATCH 2/4] agents|fix: Render the remote-issue offer as a next-steps sub-block Fixes an ambiguity where `design-and-plan`'s offer to update the remote issue had no legal shape in the block it was told to join. The next-steps menu admits exactly four mutually-exclusive options, so a consent item added to it either improvised a fifth option or displaced the menu's own numbering, and a user answering with a number could not say both which next step they wanted and whether to touch the issue. The guidance now specifies the offer as its own labelled sub-block above the menu, under a shared `Next steps:` header, with each sub-block numbered from 1. The consent is stated separately from the single-select next-step choice, and the menu's options keep their identifiers and order. --- .../content/skills/design-and-plan/SKILL.md | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/agents/content/skills/design-and-plan/SKILL.md b/packages/agents/content/skills/design-and-plan/SKILL.md index cdd029d2..9ad4c1c1 100644 --- a/packages/agents/content/skills/design-and-plan/SKILL.md +++ b/packages/agents/content/skills/design-and-plan/SKILL.md @@ -153,13 +153,30 @@ Design and plan complete: Plan: {plan_path} ``` -**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference). This is a shared-state action — do not update without explicit consent. The offer joins the next-steps block below as an additional ask, keeping that block's identifiers; it never opens a turn of its own. On consent: +**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference). This is a shared-state action — do not update without explicit consent, and never open a turn of its own for the ask. + +Render the offer inside the next-steps block as its own labelled sub-block above the options, under the same `Next steps:` header. Each sub-block numbers from 1 and carries its own label; the consent stays orthogonal to the single-select next-step choice, and the four next-steps options keep their own identifiers and order. Recommend the update (■■□) — the refined ticket is newer than the remote body, which is why the offer appears at all. + +``` +Next steps: + +Remote issue: +1. 📝 ■■□ Update {ticket_ref} with the refined ticket +2. ⏭️ ■□□ Leave as-is + +Implementation: +1. 🧠 ■□□ Refine plan: + - Clear context and use the `refine-plan` skill with plan: {plan_path}, ticket: {ticket_path} +... +``` + +On consent: - GitHub: Write the refined body to a scratch file using the [gh body file](../_data/gh-body-file.md) pattern, then `gh issue edit {number} --body-file "$body_path"`. - Other platforms: Note that automated update is not yet supported; suggest manual update -Follow the options, output format, and recommendation rules in [next-steps options](#next-steps-options) exactly. Do not improvise the options. The plan was developed interactively with user approval at each stage — use this as recommendation context. Include both `{ticket_path}` and `{plan_path}` in each skill-invoking option line. +Follow the options, output format, and recommendation rules in [next-steps options](#next-steps-options) exactly. Do not improvise the options. The `Remote issue:` and `Implementation:` sub-block labels above are the sanctioned wrapper when the remote offer is shown; they add no option and reorder none. The plan was developed interactively with user approval at each stage — use this as recommendation context. Include both `{ticket_path}` and `{plan_path}` in each skill-invoking option line. **STOP.** Do not invoke any other skill. Do not begin implementation. From a2bed6deb006b70570bfa989e3821ecde60362df Mon Sep 17 00:00:00 2001 From: William Thorsen Date: Thu, 16 Jul 2026 19:33:39 -0700 Subject: [PATCH 3/4] agents|fix: Ground the sweep's no-gate rule in settled decisions Fixes a rationale in the completeness sweep that justified its no-new-approval-gate rule by appealing to an approval step that only one of the two skills running the sweep performs. A reader of `plan`, which drafts and saves without a present-and-approve step, met a premise that is false there and was handed a reason to doubt the rule. The guidance now grounds the rule in the decisions the conversation settled, which holds wherever the sweep runs. --- .../content/skills/_partials/ticket-and-plan-completeness.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md b/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md index 5378708d..0c80b91e 100644 --- a/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md +++ b/packages/agents/content/skills/_partials/ticket-and-plan-completeness.md @@ -13,4 +13,4 @@ Run the sweep in the main session, never in a subagent. Only the session holds t **Route each gap by kind**, per the placement doctrine: the change's subject and outcomes fold into the ticket, mechanism folds into the plan. Where the gap came up in conversation does not decide where it lands. When the invocation produces no ticket artifact, a subject-level gap folds into the plan's context section. -**Report and proceed.** When the sweep finds gaps, fold them in and report the amendments as a brief list, then save. The report is informational: the amendments carry what the approval already covered, so it opens no new approval gate and asks nothing. When the sweep finds nothing, save silently — a clean sweep is not worth a line. +**Report and proceed.** When the sweep finds gaps, fold them in and report the amendments as a brief list, then save. The report is informational: the amendments carry decisions the conversation already settled, so it opens no new approval gate and asks nothing. When the sweep finds nothing, save silently — a clean sweep is not worth a line. From 0ef35544be980d2a49d0dbb88f9c296f80dfce99 Mon Sep 17 00:00:00 2001 From: William Thorsen Date: Thu, 16 Jul 2026 19:38:56 -0700 Subject: [PATCH 4/4] agents|fix: Offer the remote-issue update only when the body is stale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes an offer that `design-and-plan` recommended even when it would push a body identical to the one already on the issue. Refining a ticket is optional — a good source ticket can be adopted unchanged, and the completeness sweep can find nothing to fold in — but the offer appeared whenever the source was a remote ticket, regardless. It is now made only when the refined ticket actually differs from the remote body, which is also what earns it a recommended marker. Names the sub-block heading over the next-steps options `Next action:` rather than `Implementation:`, which mislabelled a menu whose first option is to refine the plan. --- packages/agents/content/skills/design-and-plan/SKILL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/agents/content/skills/design-and-plan/SKILL.md b/packages/agents/content/skills/design-and-plan/SKILL.md index 9ad4c1c1..3d3256d3 100644 --- a/packages/agents/content/skills/design-and-plan/SKILL.md +++ b/packages/agents/content/skills/design-and-plan/SKILL.md @@ -153,9 +153,9 @@ Design and plan complete: Plan: {plan_path} ``` -**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference). This is a shared-state action — do not update without explicit consent, and never open a turn of its own for the ask. +**Remote issue update** — offer to update the remote issue only when the source was a remote ticket (URL or shorthand reference) and the refined ticket differs from the remote body. Phase 4 may adopt a good source ticket unchanged and the sweep may find nothing to fold in; the remote is then already current, and no offer is made. This is a shared-state action — do not update without explicit consent, and never open a turn of its own for the ask. -Render the offer inside the next-steps block as its own labelled sub-block above the options, under the same `Next steps:` header. Each sub-block numbers from 1 and carries its own label; the consent stays orthogonal to the single-select next-step choice, and the four next-steps options keep their own identifiers and order. Recommend the update (■■□) — the refined ticket is newer than the remote body, which is why the offer appears at all. +Render the offer inside the next-steps block as its own labelled sub-block above the options, under the same `Next steps:` header. Each sub-block numbers from 1 and carries its own label; the consent stays orthogonal to the single-select next-step choice, and the four next-steps options keep their own identifiers and order. Recommend the update (■■□): the offer appears only when the remote body is stale against the refined ticket. ``` Next steps: @@ -164,7 +164,7 @@ Remote issue: 1. 📝 ■■□ Update {ticket_ref} with the refined ticket 2. ⏭️ ■□□ Leave as-is -Implementation: +Next action: 1. 🧠 ■□□ Refine plan: - Clear context and use the `refine-plan` skill with plan: {plan_path}, ticket: {ticket_path} ... @@ -176,7 +176,7 @@ On consent: - Other platforms: Note that automated update is not yet supported; suggest manual update -Follow the options, output format, and recommendation rules in [next-steps options](#next-steps-options) exactly. Do not improvise the options. The `Remote issue:` and `Implementation:` sub-block labels above are the sanctioned wrapper when the remote offer is shown; they add no option and reorder none. The plan was developed interactively with user approval at each stage — use this as recommendation context. Include both `{ticket_path}` and `{plan_path}` in each skill-invoking option line. +Follow the options, output format, and recommendation rules in [next-steps options](#next-steps-options) exactly. Do not improvise the options. The `Remote issue:` and `Next action:` sub-block labels above are the sanctioned wrapper when the remote offer is shown; they add no option and reorder none. The plan was developed interactively with user approval at each stage — use this as recommendation context. Include both `{ticket_path}` and `{plan_path}` in each skill-invoking option line. **STOP.** Do not invoke any other skill. Do not begin implementation.