@deftai/directive-content 0.103.0 → 0.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Taskfile.yml +1 -0
- package/commands.md +2 -2
- package/docs/writing-ste100.md +38 -4
- package/package.json +1 -1
- package/packs/skills/skills-pack-0.1.json +2 -2
- package/skills/deft-directive-refinement/SKILL.md +7 -5
- package/skills/deft-directive-sync/SKILL.md +8 -10
- package/tasks/verify.yml +10 -0
- package/templates/agent-prompt-preamble.md +10 -0
- package/templates/agents-entry.md +2 -0
package/Taskfile.yml
CHANGED
package/commands.md
CHANGED
|
@@ -132,10 +132,10 @@ Scope xBRIEFs live under `xbrief/{proposed,pending,active,completed,cancelled}/`
|
|
|
132
132
|
|
|
133
133
|
Common commands:
|
|
134
134
|
|
|
135
|
-
- `task scope:promote -- xbrief/proposed/<file>.xbrief.json` -- move proposed work to `pending/` and set status to `pending`.
|
|
135
|
+
- `task scope:promote -- xbrief/proposed/<file>.xbrief.json` -- move proposed work to `pending/` and set status to `pending`. When `plan.acceptance` is absent, empty-with-none_stated, or command-only-without-clauses, runs #3323 clause derivation and stamps `clauses[]` (#3360).
|
|
136
136
|
- `task scope:promote -- --from-issue=<N> [--repo OWNER/NAME] [--strict] [--force-no-cache] [--path <file>]` -- promote the proposed scope for issue N via triage-cache reciprocity (#1136). Latest `candidates.jsonl` decision must be `accept` (non-accept refuses unless `--force-no-cache`; missing decision soft-warns, `--strict` fails). Path/`--batch` without `--from-issue` stay ungated.
|
|
137
137
|
- `task scope:promote -- --batch` -- batch-promote **all** `xbrief/proposed/` scopes to `pending/` in one command (#3011 / epic #3009). Optional: `--batch <path>…` for an explicit list; `--force` overrides WIP cap (logged). Does **not** activate; implement remains one `scope:activate` at a time.
|
|
138
|
-
- `task scope:activate -- xbrief/pending/<file>.xbrief.json` -- move accepted work to `active/` and set status to `running`.
|
|
138
|
+
- `task scope:activate -- xbrief/pending/<file>.xbrief.json` -- move accepted work to `active/` and set status to `running`. Same #3323 derivation hook as promote; #3334 refusal names the derive step (#3360). Headless: records `chosen_reading`, never blocks on a question.
|
|
139
139
|
- `task scope:complete -- xbrief/active/<file>.xbrief.json` -- move running work to `completed/` and set status to `completed`.
|
|
140
140
|
- **Per-criterion acceptance evidence (#3240 / #3305):** each non-terminal `plan.items[]` entry needs either namespaced typed evidence or a human-origin disposition before complete may advance it:
|
|
141
141
|
- `plan.items[].x-directive/evidence` — `{ kind: test|review|merge|deploy|smoke|uat|observed_behavior, pointer, recorded_at, recorded_by }`
|
package/docs/writing-ste100.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Controlled English for docs and issues
|
|
2
2
|
|
|
3
|
-
Directive
|
|
3
|
+
Directive's writing bar is **clarity, simplicity, and brevity**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use that outcome bar for documents and user communications, including sub-agent status and handbacks.
|
|
6
|
+
|
|
7
|
+
**ASD-STE100** is Simplified Technical English (aerospace controlled language). Here it means a practical subset. It is not a certification program. The four rules below are the how.
|
|
6
8
|
|
|
7
9
|
Legend (RFC2119): `!`=MUST, `~`=SHOULD, `≉`=SHOULD NOT, `⊗`=MUST NOT, `?`=MAY.
|
|
8
10
|
|
|
9
|
-
Tracker: [#2927](https://github.com/deftai/directive/issues/2927).
|
|
11
|
+
Tracker: [#3368](https://github.com/deftai/directive/issues/3368). Mechanics from [#2927](https://github.com/deftai/directive/issues/2927).
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
@@ -17,18 +19,45 @@ Tracker: [#2927](https://github.com/deftai/directive/issues/2927).
|
|
|
17
19
|
3. **One term = one meaning.** Keep product terms stable (`xbrief`, host, skill pack, swarm, deposit). Do not reuse one word for two concepts.
|
|
18
20
|
4. **First-use definitions.** Define a tech term the first time it appears when the reader may not know it.
|
|
19
21
|
|
|
20
|
-
! Apply these four rules to
|
|
22
|
+
! Apply these four rules to documents and user communications, including sub-agent status and handbacks — not only new-and-touched files.
|
|
21
23
|
|
|
22
24
|
~ Prefer clarity over ceremony. When a product term already has a glossary or category note, reuse that meaning.
|
|
23
25
|
|
|
24
26
|
---
|
|
25
27
|
|
|
28
|
+
## Ceremony vs required fields
|
|
29
|
+
|
|
30
|
+
! Cut ceremony, not required protocol fields. Keep these complete:
|
|
31
|
+
|
|
32
|
+
- `DONE` / `BLOCKED` / `FAILED` status lines
|
|
33
|
+
- Allocation context
|
|
34
|
+
- SHAs
|
|
35
|
+
- Exit codes
|
|
36
|
+
- Evidence cites
|
|
37
|
+
|
|
38
|
+
⊗ Drop a required field to look brief.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
26
42
|
## Where it applies
|
|
27
43
|
|
|
28
44
|
- Agent and maintainer communications about Directive
|
|
29
45
|
- Product docs (including `content/docs/` and related guides)
|
|
30
46
|
- GitHub issues, PRs, and review comments that maintainers or agents author here
|
|
31
47
|
- Skill and strategy prose where clarity matters for agent load
|
|
48
|
+
- Sub-agent status, handbacks, and sibling reports
|
|
49
|
+
|
|
50
|
+
! The bar governs communication **about** the work, not the work itself.
|
|
51
|
+
|
|
52
|
+
! Product content with its own specified voice (fiction, game dialogue, marketing, brand copy) follows the scope's style requirements. No toggle: this is a scoping sentence, not a config flag.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Reasoning is out of scope
|
|
57
|
+
|
|
58
|
+
! The bar does not govern reasoning itself. Thinking budgets are harness knobs (effort tier, per-role routing #1739), not prose rules.
|
|
59
|
+
|
|
60
|
+
⊗ Extend the bar to thinking. Terse reasoning trades correctness for style.
|
|
32
61
|
|
|
33
62
|
---
|
|
34
63
|
|
|
@@ -37,6 +66,8 @@ Tracker: [#2927](https://github.com/deftai/directive/issues/2927).
|
|
|
37
66
|
- ⊗ Full ASD-STE100 dictionary compliance or formal STE tooling certification
|
|
38
67
|
- ⊗ A big-bang rewrite of the historical issue corpus
|
|
39
68
|
- ⊗ A red CI style gate in v1 that blocks merges on style nitpicks
|
|
69
|
+
- ⊗ A second `[AXIOM]` label
|
|
70
|
+
- ⊗ Prefacing the rule ("per the writing bar…")
|
|
40
71
|
|
|
41
72
|
Process expectation only: follow the bar by default. Do not invent a merge blocker from this page alone.
|
|
42
73
|
|
|
@@ -46,8 +77,11 @@ Process expectation only: follow the bar by default. Do not invent a merge block
|
|
|
46
77
|
|
|
47
78
|
| Issue | Role |
|
|
48
79
|
|-------|------|
|
|
80
|
+
| [#3368](https://github.com/deftai/directive/issues/3368) | Always-on outcome bar (clarity, simplicity, brevity) |
|
|
81
|
+
| [#2927](https://github.com/deftai/directive/issues/2927) | Four STE mechanics (closed) |
|
|
49
82
|
| [#740](https://github.com/deftai/directive/issues/740) | Plain-English UX pass (closed; interview-focused) |
|
|
50
83
|
| [#865](https://github.com/deftai/directive/issues/865) | Every rule is a token tax |
|
|
51
84
|
| [#847](https://github.com/deftai/directive/issues/847) | Lean context first |
|
|
52
85
|
| [#2484](https://github.com/deftai/directive/issues/2484) | Progressive disclosure for large skills |
|
|
53
86
|
| [#2905](https://github.com/deftai/directive/issues/2905) | Category terms (host vs skill pack vs practice layer) |
|
|
87
|
+
| [#1739](https://github.com/deftai/directive/issues/1739) | Per-role routing (thinking budgets; not this bar) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deftai/directive-content",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.104.0",
|
|
4
4
|
"deftConsumerDeposit": true,
|
|
5
5
|
"description": "Shippable Directive framework content in the consumer .deft/core/ layout (C1 flatten), plus the engine surfaces (.githooks/, Taskfile.yml, tasks/) the deposit wires. Python-free per #2022 Phase 3. Refs #11, #1669, #1967.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
],
|
|
223
223
|
"path": "skills/deft-directive-refinement/SKILL.md",
|
|
224
224
|
"version": "0.1",
|
|
225
|
-
"body": "# Deft Directive Refinement\n\nConversational refinement session -- ingest, evaluate, reconcile, and prioritize scope xBRIEFs with the user.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**Upstream pass**: refinement begins with a triage pass -- see [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) for the canonical cache-hygiene + \"what's next?\" queue playbook before continuing into the refinement flow below.\n\n**See also**: [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md) (canonical numbered-menu rule used by every Phase 0 / Phase 2-5 gate below) | `task cache:fetch-all` / `task cache:get` (Tier 1 unified content cache, #883 Story 2) | `task triage:bootstrap` / `task triage:accept` / `task triage:reject` / `task triage:defer` / `task triage:needs-ac` / `task triage:mark-duplicate` / `task triage:bulk-*` / `task triage:refresh-active` (Phase 0 action surface, #845 + #883 Story 3 rebind).\n\n## Platform Requirements\n\n! This skill requires **GitHub** as the SCM platform and the **GitHub CLI (`gh`)** to be installed and authenticated. Issue ingestion, origin freshness checks, and completion lifecycle all depend on `gh`.\n\n## Deterministic Questions Contract\n\n! Every numbered-menu prompt rendered in this skill (Phase 0 Triage action menu, Phase 2 Evaluate per-item accept/reject, Phase 3 Reconcile flagged-item walk, Phase 4 Promote/Demote lifecycle gates, Phase 5 Prioritize reorder gates) MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): render the canonical numbered menu in chat unless the host UI visibly preserves numeric option labels and returns numeric selections or exact displayed option text. The final two numbered options MUST be `Discuss` and `Back`, in that order. The Discuss-pause semantic is documented verbatim there -- on `Discuss` selection the agent MUST halt the in-progress sequence immediately, prompt `What would you like to discuss?`, and resume only on an explicit user signal. Implicit resumption is forbidden, and fallback chat replies MUST map only to the displayed number or exact displayed option text.\n\n## When to Use\n\n- User says \"refinement\", \"reprioritize\", \"refine\", \"roadmap refresh\", or \"refresh roadmap\" (legacy v0.19 terms -- deft-directive-refinement is the current skill name)\n- User says \"triage\", \"action menu\", \"work the cache\", or \"pre-ingest\" -- first-class Phase 0 direct triggers introduced under #845; they route to Phase 0 (Triage), not the general refinement entry\n- New issues have accumulated since the last refinement session\n- Periodic maintenance pass (e.g. weekly or after a batch of user feedback)\n- User wants to review and organize the backlog\n\n! **Entry point (#1141, supersedes #845 / #883 action-menu).** Phase 0 -- Triage-first consultation is the canonical entry point for any refinement session. Phase 0 consults `task triage:summary` (D2 / #1122) and `task triage:queue --state=accept` (D11 / #1128) and pulls the `[RESUME]`-tagged slice (D3 / #1123) FIRST. Refinement does NOT itself triage cached candidates -- that work belongs to [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130). Phase 0 ! MUST chain into Phase 1 -- Ingest on completion (or surface the empty-cache fallback prompt when the cache has not yet been bootstrapped -- see Phase 0a below). Phase 1+ semantics are unchanged.\n\n## Prerequisites\n\n- ! `xbrief/` directory exists with lifecycle folders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`)\n- ! GitHub CLI (`gh`) is authenticated and can access the repo\n- ~ `PROJECT-DEFINITION.xbrief.json` exists (run `task project:render` if missing)\n\n## Session Model\n\nRefinement is a **conversational loop**, not a batch job. The user directs the flow:\n\n- \"Triage\" / \"action menu\" / \"work the cache\" / \"pre-ingest\" -> Phase 0 (Triage-first consultation, #1141) -- refinement consults the cache; the canonical decision-making playbook is `../deft-directive-triage/SKILL.md` (D6 / #1130)\n- \"Pull in issues\" / \"ingest\" -> Phase 0 ALWAYS runs first to consult `task triage:summary` + `task triage:queue --state=accept`; Phase 1 follows on the cohort Phase 0b produces (#1141)\n- \"Show proposed\" / \"evaluate\" -> Phase 2 (Evaluate)\n- \"Check origins\" / \"reconcile\" -> Phase 3 (Reconcile)\n- \"Accept these\" / \"reject that\" / \"promote\" / \"demote\" -> Phase 4 (Promote/Demote)\n- \"Reprioritize\" / \"reorder pending\" -> Phase 5 (Prioritize)\n- \"Close out\" / \"scope is done\" / \"completion\" -> Phase 6 (Completion Lifecycle)\n- \"Done\" / \"exit\" -> Exit\n\nThe agent may suggest the next phase, but the user decides. Phases can be entered in any order and repeated.\n\n## Branch Setup (Preflight)\n\n! Before making any changes, ensure you are working on a feature branch. This preflight runs before Phase 0 and again before Phase 1 if Phase 0 is auto-skipped.\n\n1. ! Check if the working tree has uncommitted changes that would conflict -- stop and ask the user to resolve them first\n2. ! Create or switch to a refinement branch (e.g. `refinement/YYYY-MM-DD`) if not already on one\n3. ! Confirm the branch and working directory to the user before proceeding\n\n## Phase 0 -- Triage-first consultation (cache-first, #1141)\n\n! Phase 0 is a thin consumer of the canonical triage cache: refinement consults `task triage:summary` (D2 / #1122) and `task triage:queue` (D11 / #1128) BEFORE walking any `xbrief/` lifecycle folder. The dedicated triage playbook lives at [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) -- refinement does NOT itself triage cached candidates; it consumes the queue's `accept` and `[RESUME]` slices and turns them into scope xBRIEFs.\n\n! Phase 0 runs three sub-phases in canonical order: **Phase 0a -- Triage gate** -> **Phase 0b -- Cache-first ingestion** -> **Phase 0c -- Resume conditions**. Each sub-phase MUST run before the next, and Phase 0 MUST chain into Phase 1 -- Ingest on completion. Numbered prompts in Phase 0 ! MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md) (`Discuss` / `Back` as the final two numbered options; Discuss-pause semantic applies verbatim).\n\n**See also (#883 Story 2):** the unified cache (`task cache:fetch-all --source=github-issue --repo OWNER/NAME`) is the sole content-mirroring surface in v0.26.0+. Tier 1 reads MUST go through `task cache:get -- github-issue OWNER/NAME/<N>`. The legacy \"Three-Tier Inventory Model\" + action-menu walk that lived here pre-#1141 has moved out of refinement and into `../deft-directive-triage/SKILL.md` (D6 / #1130); refinement now consumes the post-decision queue rather than producing decisions.\n\n### Phase 0a -- Triage gate (`task triage:summary`)\n\n1. ! Invoke `task triage:summary` (D2 / #1122) and capture the one-liner.\n2. ! **Empty-cache backward-compat fallback.** If the one-liner is the documented empty-cache prompt (`[triage] cache empty -- run task triage:bootstrap`), the agent ! MUST emit the verbatim recovery message to stderr BEFORE any folder scan:\n\n ```\n triage cache empty -- run `task triage:welcome` (N3 / #1143) to onboard, or `task triage:bootstrap` to seed the cache directly; refinement Phase 0 cannot consult the queue against an empty cache. Falling back to a legacy `xbrief/proposed/` folder scan only if you opt in.\n ```\n\n Then prompt the user `Fall back to legacy folder-scan against xbrief/proposed/ for this session? [y/N]` (default `N`). On `N`, exit refinement with the canonical `deft-directive-refinement complete -- exiting skill.` confirmation and the chaining instruction `Run task triage:welcome (N3 / #1143) to onboard, then re-enter refinement.`. On `y`, chain into Phase 1 against `xbrief/proposed/` as the legacy fallback. ! MUST NOT silently proceed without surfacing the breadcrumb to `task triage:welcome` -- a fresh post-upgrade install needs that pointer to find the canonical onboarding ritual.\n\n3. ! **Outstanding-work gate.** If the cache is populated AND any of `untriaged`, `stale-defer (resume condition met)`, or `in-flight` is non-zero, surface the one-liner verbatim to the user with the canonical recommendation:\n\n ```\n triage cache has outstanding work -- recommend running `skills/deft-directive-triage/SKILL.md` (D6 / #1130) first. Proceed to refinement anyway? [y/N]\n ```\n\n ~ Default is `N`: deferring to the triage skill is the documented happy path because refinement consumes `accept`-decisioned candidates and an untriaged backlog means there are fewer `accept` rows than there could be. On `N`, exit with the canonical confirmation phrasing and the chaining instruction `Run skills/deft-directive-triage/SKILL.md to clear the backlog, then re-enter refinement.`. On `y`, proceed to Phase 0b.\n\n4. ? When all counts are zero (cache populated, no outstanding work), proceed to Phase 0b without prompting.\n\n⊗ Skip Phase 0a -- refinement on top of an untriaged cache wastes the operator's time on items the triage skill would have rejected, deferred, or marked needs-AC.\n⊗ Bypass the empty-cache fallback prompt -- a silent proceed against an empty cache surfaces a misleading \"no candidates\" state and hides the upgrade-onboarding path from the operator.\n\n### Phase 0b -- Cache-first ingestion (`task triage:queue --state=accept`)\n\n1. ! Pull the ingestion candidate list via `task triage:queue --state=accept` (D11 / #1128). Each row is a cached issue whose latest audit-log decision is `accept` -- the canonical \"ready to become a scope xBRIEF\" cohort. ! MUST NOT enumerate `xbrief/proposed/` independently of the queue; the folder participates only via the join described in step 2.\n2. ! Join the queue against `xbrief/proposed/` (and the rest of the lifecycle folders) by `references[].uri`: queue rows whose issue is already represented by an existing xBRIEF surface as \"already tracked\"; queue rows with no matching xBRIEF are \"new accept candidates\". Items already in `xbrief/proposed/` continue to participate -- they are joined against the cache rather than enumerated separately.\n3. ~ When the join surfaces zero new candidates (every `accept` row already has a xBRIEF), Phase 0b is a clean no-op; chain straight into Phase 0c.\n4. ! For each new candidate, fall through to Phase 1 -- Ingest, which delegates the actual scope-xBRIEF write to `task issue:ingest` (or `task triage:accept`, which already ingests into `proposed/`). After the proposed artifact exists, promote with `task scope:promote -- --from-issue=<N> [--repo OWNER/NAME]` (#1136 / D18), or chain accept+promote via `task triage:accept -- --issue <N> --repo OWNER/NAME --auto-promote` when the operator wants pending/ in one step.\n\n⊗ Walk `xbrief/proposed/` directly as the primary ingestion surface -- the cache is the authoritative \"what is ready to refine?\" surface; the folder is the destination, not the source of truth.\n⊗ Drop items that exist in `xbrief/proposed/` but lack a matching cache row -- those are reconciled later (Phase 3 / origin reconciliation), not silently discarded.\n\n### Phase 0c -- Resume conditions (`[RESUME]`-tagged items first)\n\n1. ! Before walking new untriaged candidates from Phase 0b, process every `[RESUME]`-tagged row in the queue. `[RESUME]` rows surface from D3 (#1123) when a prior `defer` audit entry's `resume-on` condition fires (atomics: `ref:closed:#N`, `ref:merged:#N`, `date:>=YYYY-MM-DD`, `pending-count:>=N|<=N`, composed by a single top-level `AND` or `OR`).\n2. ! Stale-defer (resume-eligible) items take priority over fresh untriaged when both are present in the same Phase 0 pass -- the operator made a forward-dated decision on the deferred item and the framework is honouring it. Treat the `[RESUME]` slice as the FIRST class of candidates surfaced to the user.\n3. ~ The exact precedence in `task triage:queue` is `[ORPHAN]` -> `[RESUME]` -> `[URGENT]` -> untriaged -> other (per D11 + D13 / #1132 grouping). Refinement consumes this order verbatim and surfaces `[RESUME]` candidates first; `[ORPHAN]` rows are out-of-scope for refinement (they are handled by the triage skill's audit phase).\n\n⊗ Treat `[RESUME]` rows as \"leftover\" -- they are the highest-priority class refinement is meant to process, because the operator already decided to revisit them when the condition fired.\n\n### Pre-Phase-1 handoff\n\n1. ! Surface a one-line session summary: `{resume_eligible} resume-eligible, {new_accept} new accept candidate(s), {already_tracked} already tracked in xbrief/`.\n2. ! Chain into Phase 1 -- Ingest, which now operates on the cohort produced by Phase 0b's join (`[RESUME]` rows first, then new accept candidates).\n3. ? If the user opts out of Phase 1 (e.g. \"that's it for today\"), exit via the Phase 0 mid-session exit surface below -- ! MUST NOT route to the `### EXIT` block under `## PR & Review Cycle` because that block is the post-PR-creation exit path and references a `PR #{N}` that does not yet exist at this point in the flow.\n\n#### Phase 0 mid-session exit surface\n\n! When the user opts out of Phase 1 after completing (or partially completing) Phase 0, perform exactly these steps -- ! MUST NOT mention any PR number, since none has been created yet:\n\n1. ! Surface the outstanding-work tally: `{resume_eligible} resume-eligible candidate(s) still pending, {new_accept} accept candidate(s) not yet ingested -- these will resurface on the next Phase 0 entry.`\n2. ! Note the audit-log location verbatim using double-backtick fencing so the inner path renders correctly: ``Audit log preserved at `xbrief/.eval/candidates.jsonl`; queue state is reproducible via `task triage:queue --state=accept`.``\n3. ! Confirm skill exit with the canonical phrasing: `deft-directive-refinement complete -- exiting skill.`\n4. ! Provide the Phase-0-appropriate chaining instruction: ``Resume with `task triage:queue --state=accept` to inspect the queue, or re-enter the refinement skill when ready to continue.`` Do NOT reference a PR, a review cycle, or a monitor agent.\n\n⊗ Skip Phase 1 silently after Phase 0 -- always render the chaining decision so the user knows the entry point shifted.\n⊗ Mutate `xbrief/proposed/` directly during Phase 0 -- only `task issue:ingest` (called from Phase 1) is allowed to write there; Phase 0 is read-only against the cache.\n⊗ Route Phase 0 mid-session opt-out to the post-PR `### EXIT` block under `## PR & Review Cycle` -- that block surfaces a non-existent `PR #{N}` and confuses the user.\n\n## Phase 1 -- Ingest\n\n! Scan external sources for new work items and create proposed scope xBRIEFs.\n\n! **Pre-filing master-diff check (#1102).** When a refinement pass FILES a new GitHub issue that proposes ADDING a file or directory (rather than ingesting an existing issue), first run the pre-filing existence check from [`../deft-directive-gh-slice/SKILL.md`](../deft-directive-gh-slice/SKILL.md) Step 5 -- `git ls-tree origin/master -- <path>` (or `gh api repos/{owner}/{repo}/contents/{path}`) -- so a stale \"add file X\" issue is never opened against state that already exists on master (the #1099 -> #1100 close-and-refile recurrence).\n\n### Step 1: Gather Sources\n\n1. ? Scan non-GitHub sources (Jira, direct user requests, etc.) manually if applicable — those ingest paths are not yet task-wrapped\n2. ! GitHub issues are ingested via the task wrapper documented in Step 3 — the task fetches open issues itself, so no separate `gh issue list` call is needed\n\n### Step 2: Deduplicate via References (Dry-Run Preview)\n\n1. ? Run `task issue:ingest -- --all --dry-run` to preview which issues the ingest task would create scope xBRIEFs for. The task deduplicates candidates against `references` entries in existing xBRIEFs (across all lifecycle folders) so already-tracked issues are skipped automatically.\n2. ! Present the user with the list of new-vs-already-tracked items the dry-run reports: \"{N} new items found, {M} already tracked\"\n3. ! Wait for user approval before proceeding to ingest\n\n### Step 3: Ingest Approved Items\n\n! Delegate ingest to `task issue:ingest` — the task is the canonical implementation of scope-xBRIEF creation. Skills MUST NOT reinvent the slug rules, reference shape, or deduplication logic inline (see #537 for background).\n\n- **Single issue**: `task issue:ingest -- <N>` — creates `xbrief/proposed/YYYY-MM-DD-<slug>.xbrief.json` with origin `references`, canonical slug from `scripts/slug_normalize.py` (see [`../../conventions/vbrief-filenames.md`](../../conventions/vbrief-filenames.md)), and schema-conformant shape.\n- **Batch**: `task issue:ingest -- --all [--label <L>] [--status <S>]` — ingests every open issue matching the filters, skipping duplicates by `references.uri` match.\n- **Preview**: add `--dry-run` to either form to preview without writing files.\n\nThe task emits xBRIEFs conforming to the canonical v0.6 schema (`xbrief/schemas/xbrief-core.schema.json`) with origin references in the form documented in [`../../conventions/references.md`](../../conventions/references.md):\n\n```json\n\"references\": [\n {\n \"uri\": \"https://github.com/{owner}/{repo}/issues/{N}\",\n \"type\": \"x-xbrief/github-issue\",\n \"title\": \"Issue #{N}: {issue title}\"\n }\n]\n```\n\n- ! New scope xBRIEFs MUST target `\"xBRIEFInfo\": { \"version\": \"0.6\" }` (the task handles this automatically)\n- ! `plan.status` starts at `\"proposed\"`; the task sets this\n- ! Conform to `xbrief/schemas/xbrief-core.schema.json` (v0.6) -- the task validates before writing\n- ~ After ingest, review the generated xBRIEFs with the user before promoting any of them to `pending/`\n\n⊗ Hand-author scope xBRIEFs inside the skill when the ingest task exists — duplicating the narrative logic is how #534 (non-conformant references) and #537 (drift between skill and task) arise\n⊗ Write references with `url`/`id`/bare `github-issue` types — use the schema-conformant `{uri, type, title}` shape above\n⊗ Ingest an item that already has a matching xBRIEF reference -- `task issue:ingest` handles deduplication; skills MUST NOT duplicate that logic inline\n\n## Phase 2 -- Evaluate\n\n! List proposed items for interactive user review.\n\n### Step 1: List Proposed Items\n\n1. ! Read all xBRIEFs in `xbrief/proposed/`\n2. ! Present each item with:\n - Title and filename\n - Origin link(s) from `references`\n - Summary from `narratives` (if populated)\n - Labels/category (if available from origin)\n3. ! Sort by creation date (oldest first) or as user prefers\n\n### Step 2: Interactive Review\n\n! For each proposed item (or batch, as user directs):\n\n- ! Present the item and wait for user decision\n- ~ The user may: accept (promote to pending), reject (cancel), defer (keep in proposed), or request more detail\n- ! Do not proceed to the next item until the user responds\n- ? The user may batch-accept or batch-reject multiple items at once\n\n⊗ Auto-accept or auto-reject proposed items without user review\n\n## Phase 3 -- Reconcile (RFC D12)\n\n! Check if linked origins have changed since the xBRIEF was last touched. Delegate the scan to `task reconcile:issues` and walk the user through flagged items for approval (see #537 for why the skill is a thin wrapper over the task).\n\n### Step 1: Run the Reconciler\n\n```\ntask reconcile:issues\n```\n\nThe task scans every xBRIEF with a GitHub-backed reference (whether the reference uses the legacy `github-issue` bare type or the canonical `x-xbrief/github-issue` shape), fetches each linked issue, compares timestamps and state, and reports items in four buckets:\n\n- **Linked & current** — origin has not changed since the xBRIEF was last updated (no action)\n- **Stale** — origin `updatedAt` is newer than the xBRIEF (propose an update)\n- **Externally closed** — origin issue is `CLOSED` (propose cancellation or reconcile if intentional divergence)\n- **Unlinked** — xBRIEF has no GitHub reference (flag for review)\n\n### Step 2: Walk Flagged Items with the User\n\n1. ! For each **stale** item the task surfaces, show the user the diff between the current xBRIEF and the refreshed origin. Propose edits; ! wait for explicit user approval before writing anything.\n2. ! For each **externally closed** item, ask the user whether to `task scope:cancel <file>` it or preserve intentional divergence.\n3. ! For each **unlinked** item, ask whether to attach an origin reference or leave the xBRIEF as-is.\n\n### Step 3: Apply User-Approved Updates\n\n- ! Agent proposes edits; ! user approves each change\n- ! Never auto-update xBRIEFs — intentional divergence (xBRIEF refined beyond original issue scope) must be preserved\n- ! For approved updates, update the xBRIEF content and `xBRIEFInfo.updated` timestamp; prefer the task commands (`task scope:cancel`, `task scope:block`, etc.) over hand-editing where they apply\n\n⊗ Replace the task invocation with a hand-written `gh issue view` loop — the task is the canonical implementation; skills MUST NOT duplicate it (#537)\n⊗ Auto-update xBRIEFs based on origin changes without user approval\n⊗ Overwrite intentional divergence -- if a xBRIEF has been refined beyond the original issue, preserve the refinement\n\n### Origin sync after material xBRIEF edits (#2540)\n\n! When this refinement pass **materially updates** an origin-linked scope xBRIEF (AC, `plan.status`, or `plan.items` statuses/titles), run `task issue:sync-from-xbrief -- <path>` to post a sync comment on the linked GitHub issue so the human-facing tracker stays current. Use `--dry-run` to preview the comment without posting.\n\n! If sync is intentionally skipped (offline, issue frozen, divergence is deliberate), document the skip reason in the session notes or PR body — do not silently leave the origin stale.\n\n⊗ Materially edit an origin-linked xBRIEF without running `issue:sync-from-xbrief` or documenting why it was skipped\n\n## Phase 4 -- Promote/Demote\n\n! Move xBRIEFs between lifecycle folders using deterministic task commands. The status values below align with the canonical v0.6 Status enum (`draft | proposed | approved | pending | running | completed | blocked | failed | cancelled`) — note that `failed` is also a valid terminal transition for active work that could not complete.\n\n### Effort estimate on accept (#1581)\n\n! When accepting an item from `proposed/` to `pending/` (`task scope:promote`), prompt for an optional `PlanItem.effort` estimate when plan items lack one. Time anchors: `S` <2h, `M` half-day (2-4h), `L` 1-2 days, `XL` needs breakdown before start.\n~ Prefer writing `effort` on each executable plan item so swarm sizing and `deft-directive-cost` have a per-item signal without a separate cost pass.\n! If the operator sets `effort: \"XL\"`, keep the scope in proposed/pending and break the item into S/M/L sub-items before any `task scope:activate` — activate fails closed on XL (#1581).\n? Omit `effort` when sizing is unknown; validation still passes (field is optional).\n! Plan-item effort is **post-planning** authority: it confirms or corrects provisional intake size at planning/accept time. It is **not** available at session start and MUST NOT be required for initial ceremony/ritual depth (#3214 two-stage rapid→escalate). Headless: no confirmation prompt required for estimates or stage transitions.\n\n### Available Commands\n\n- `task scope:promote <file>` -- proposed/ -> pending/ (status: pending)\n- `task scope:activate <file>` -- pending/ -> active/ (status: running)\n- `task scope:complete <file>` -- active/ -> completed/ (status: completed)\n- `task scope:cancel <file>` -- any -> cancelled/ (status: cancelled)\n- `task scope:restore <file>` -- cancelled/ -> proposed/ (status: proposed)\n- `task scope:block <file>` -- stays in active/ (status: blocked)\n- `task scope:unblock <file>` -- stays in active/ (status: running)\n- `task scope:fail <file>` (v0.6+) -- active/ -> completed/ (status: failed) — record a failure terminal state when a scope cannot complete but should not be cancelled\n- `task scope:undo <decision_id>` (D15 / #1134) -- reverse a single scope-lifecycle audit entry (`demote` -> re-promote, `cancel` -> restore-from-cancelled-to-prior-folder, `restore` -> re-cancel); terminal actions (`complete` / `fail`) are REFUSED -- use `git revert` or hand-edit\n- `task scope:undo --batch-id=<uuid>` (D15 / #1134) -- reverse every audit entry tagged with the batch_id (e.g. the cohort produced by `task scope:demote --batch`); idempotent on already-undone entries; the undo cohort is itself reversible via the `undo_batch_id` minted on the new entries. Optional `--dry-run` previews without writing.\n- `task scope:undo --latest` (D15 / #1134) -- reverse the most-recent reversible audit entry (`demote` / `cancel` / `restore` / `undo`) not already undone; convenience form used by the N6 / #1146 smoketest contract.\n\n### Workflow\n\n1. ! Execute transitions using the task commands above -- they handle `plan.status` updates, `plan.updated` timestamps, and file moves atomically\n2. ! Derived-artifact renders (`task roadmap:render`, `task project:render`) happen after a **batch** of promotions/demotions, not after each individual item. During high-volume triage (e.g. dozens of accept/reject decisions in one session), defer both renders until the end of the batch -- the source of truth is the lifecycle folder contents under `xbrief/`, so ROADMAP.md and PROJECT-DEFINITION.xbrief.json can be refreshed once per batch without losing correctness.\n3. ! `task roadmap:render` regenerates ROADMAP.md from the updated lifecycle folder contents. Call it once per batch (typically at the end of Phase 4, before handing back to the user or transitioning to Phase 5), not after every single promote/demote.\n4. ! `task project:render` refreshes the PROJECT-DEFINITION items registry. Call it **once per refinement pass** -- usually at the end of the session alongside the final roadmap render -- unless the user explicitly needs an intermediate registry refresh. It is not a per-edit tax.\n5. ! Before the user is shown the final backlog state (end of Phase 4, end of Phase 5, or session exit), both `task roadmap:render` AND `task project:render` MUST have been run at least once so ROADMAP.md and PROJECT-DEFINITION.xbrief.json reflect the current lifecycle folder truth. This preserves correctness while allowing N promotions/demotions to share one render checkpoint.\n6. ! Mark rejected items as `cancelled` via `task scope:cancel` (never delete xBRIEFs)\n\n~ Operationally: a large refinement session can ingest/evaluate/promote multiple issues and close out with **one** final render checkpoint, rather than N repetitive renders after every individual item.\n\n⊗ Rerender derived artifacts (`task roadmap:render`, `task project:render`) after every single accept/reject/promote/demote during high-volume triage -- batch the lifecycle edits and render once at the end of the batch\n⊗ Move xBRIEFs between folders manually (cp/mv) -- always use `task scope:*` commands\n⊗ Delete xBRIEFs -- use `task scope:cancel` to preserve history\n\n## Phase 5 -- Prioritize\n\n! Reorder and organize the pending backlog.\n\n1. ! List all xBRIEFs in `xbrief/pending/` with titles, origins, and any phase/dependency metadata\n2. ~ Help the user set phases and dependencies:\n - Group related items into phases (via xBRIEF `items` hierarchy or `tags`)\n - Identify dependencies between items (via `edges` in xBRIEF schema)\n3. ! `task roadmap:render` is the **checkpoint** before showing the reordered backlog to the user -- not a per-edit tax. Run it ONCE at the end of the reorder pass to regenerate ROADMAP.md from the updated pending/ contents. Do not invoke it after each individual reorder action.\n4. ~ Present the regenerated roadmap summary to the user for confirmation\n\n## Phase 6 -- Completion Lifecycle\n\n! On scope completion, update origins to close the loop.\n\n### When a Scope Completes\n\n1. ! Read the completed xBRIEF's `references` array\n2. ! For each GitHub-issue reference (either the legacy bare `github-issue` type or the canonical `x-xbrief/github-issue` shape):\n - Close the issue with a comment linking to the implementing PR:\n ```\n gh issue close {N} --comment \"Completed via PR #{PR} -- scope xBRIEF: {filename}\"\n ```\n - The issue number is extracted from the reference `uri` (e.g. `https://github.com/o/r/issues/{N}`)\n3. ? For other reference types (`x-xbrief/jira-ticket`, `x-xbrief/user-request`, `x-xbrief/github-pr`, etc.), follow the appropriate update mechanism\n4. ! Update PROJECT-DEFINITION via `task project:render`\n\n⊗ Complete a scope without updating its origins\n~ Completion lifecycle can be triggered during refinement or as a standalone action after a PR merge\n\n! When the refinement session files a new umbrella issue (or surfaces one whose current-shape comment is missing), file the umbrella then file its `## Current shape (as of pass-N)` comment per `## Umbrella current-shape convention` in `AGENTS.md` (#1152) -- the edit-in-place comment is the canonical surface every subsequent design pass updates.\n\n! Before reporting an umbrella or epic's current status to the operator (what is done, what blocks, wave order), fetch `repos/<owner>/<repo>/issues/<N>/comments` via REST, read the `## Current shape (as of pass-N)` comment and any linked context/`LockedDecisions` xBRIEF — never conclude status from the issue body alone (claim-cites-state-surface, #2066).\n\n~ Issue-label hygiene for any umbrella or child issue this skill files: before creating issues, inspect the target repo's existing labels with `gh label list` or the labels API; choose one or more suitable existing labels when practical, or explicitly note that no label was applied. This is a recommendation, not a gate -- do not block issue creation solely because no label fits, and do not invent ad hoc labels outside the repo's existing label set.\n\n! When a refinement pass produces a slicing event (rare but possible -- e.g. a design pass on an existing umbrella files N additional Wave-N child issues), record the cohort in `xbrief/.eval/slices.jsonl` via `scripts/slice_record.py::write_slice(...)` with `actor=\"skill:refinement\"` immediately after the children are filed (#1132 / D13). Same call shape as `skills/deft-directive-gh-slice/SKILL.md` Step 6. The cohort record is what makes `task triage:audit --orphans` able to detect Wave-2+ children whose umbrella closes prematurely; without it the production-side drift this surface guards against re-fires. Skip when the pass produced no new child cohort (e.g. a pure re-prioritization).\n\n\n! When the umbrella + children were filed by hand (legacy `gh issue create` / `issue_write` MCP / prior pass-N runs that pre-date this skill's slicing phase), use the canonical retro verb `task slice:record-existing` (#1147 / N7) -- it wraps the same `slice_record.write_slice` helper with `actor=\"manual:operator\"`, takes `--umbrella=N --children=A,B,C [--wave-N=...]` flags, validates each issue via the N5 / #1145 `scm.call` shim, and is idempotent on a matching umbrella + child set (re-run is a no-op; `--force` writes a second record for legitimate multi-session slicing). Companion `task slice:list` enumerates persisted slices for verification. The backfill verb is the canonical retro path for cohorts D13's writer never saw.\n\n## CHANGELOG Convention\n\n- ! Write ONE batch `CHANGELOG.md` entry at the END of the full refinement session -- not one entry per xBRIEF created or promoted. The batch entry summarizes all changes made during the session.\n- ⊗ Add a CHANGELOG entry after each individual action during refinement -- wait until the full session is complete and write a single summary entry.\n\n## PR & Review Cycle\n\nAfter all refinement work is complete:\n\n1. ! Ask the user: \"Ready to commit and create a PR?\"\n2. ! Wait for explicit user confirmation before proceeding.\n\n### Pre-Flight (before pushing)\n\n! Run all pre-flight checks BEFORE committing and pushing:\n\n1. ! Verify `CHANGELOG.md` has an `[Unreleased]` entry covering the refinement changes\n2. ! Run `task check` -- all checks must pass\n3. ! Verify `.github/PULL_REQUEST_TEMPLATE.md` checklist is satisfiable for this PR. If the file is **missing**, do NOT block — copy the canonical template from `templates/PULL_REQUEST_TEMPLATE.md` (ship-with-deft) to `.github/PULL_REQUEST_TEMPLATE.md` in the consumer project, then proceed with pre-flight (#531). If the file exists but contains unsatisfiable checklist items for this PR, call them out to the user before pushing.\n4. ! **Mandatory file review**: Re-read ALL modified files before committing. Explicitly check for:\n - Encoding errors (em-dashes corrupted to replacement characters, BOM artifacts)\n - Unintended duplication (accidental double xBRIEFs or duplicate entries)\n - Structural issues (malformed xBRIEF JSON, broken references)\n - Semantic accuracy (verify that counts and claims in CHANGELOG entries match the actual data)\n\n### Commit, Push, and Create PR\n\n1. ! Commit with a descriptive message: `docs(xbrief): refinement session -- {summary}`\n2. ! Push the branch to origin\n3. ! Create a PR targeting the appropriate base branch\n\n### Review Cycle Handoff\n\n! After the PR is created, automatically sequence into `skills/deft-directive-review-cycle/SKILL.md`.\n\n- ! Inform the user: \"PR #{N} created -- starting review cycle.\"\n- ! Follow the full review cycle skill from Phase 1 (Deft Process Audit) onward.\n\n### EXIT\n\n! When the review cycle completes (exit condition met) or the PR is ready for human review:\n\n1. ! Explicitly confirm skill exit: \"deft-directive-refinement complete -- exiting skill.\"\n2. ! Provide chaining instructions to the user/agent:\n - If review cycle is complete and PR is approved: \"PR #{N} is ready for human merge review.\"\n - If review cycle is still in progress: \"Review cycle handed off to deft-review-cycle. Monitor PR #{N} for Greptile findings.\"\n - If returning to a monitor agent: \"Returning control to monitor agent -- refinement PR #{N} created and review cycle initiated.\"\n3. ! Do NOT continue into adjacent work after this point -- the skill boundary is an exit condition.\n\n## Anti-Patterns\n\n- ⊗ Bypass Phase 0 by walking `xbrief/proposed/` or `gh issue list` directly -- `task triage:queue --state=accept` (D11 / #1128) is the canonical ingestion-candidate surface (#1141)\n- ⊗ Skip Phase 0a's `task triage:summary` invocation -- the triage-gate decision (run the triage skill first vs proceed) depends on its output (#1141 / D2 / #1122)\n- ⊗ Silently proceed against an empty cache -- emit the canonical `task triage:welcome` (N3 / #1143) breadcrumb to stderr first (#1141)\n- ⊗ Treat `[RESUME]`-tagged items as leftover -- they are the highest-priority class refinement processes (#1141 / D3 / #1123)\n- ⊗ Skip Phase 1 silently after Phase 0 -- always render the chaining decision so the user knows the entry point shifted (#1141, supersedes #845)\n- ⊗ Auto-accept or auto-reject proposed items without user review\n- ⊗ Create xBRIEFs without origin provenance (`references` linking to the source)\n- ⊗ Ingest items without deduplicating against existing xBRIEF references first\n- ⊗ Auto-update xBRIEFs based on origin changes -- user approves all updates\n- ⊗ Overwrite intentional divergence when reconciling stale origins\n- ⊗ Move xBRIEFs between folders manually -- always use `task scope:*` commands\n- ⊗ Delete xBRIEFs -- use `task scope:cancel` to preserve history\n- ⊗ Complete a scope without updating its origins (closing issues, posting comments)\n- ⊗ Skip deduplication during ingest -- always diff against existing references\n- ⊗ Add a CHANGELOG entry per individual action during refinement -- write one batch entry at the end of the full session\n- ⊗ Proceed to the next proposed item without waiting for user decision during evaluate\n- ⊗ Auto-push without explicit user instruction\n- ⊗ Rerender ROADMAP.md or PROJECT-DEFINITION.xbrief.json after every single accept/reject/promote/demote during high-volume triage -- `task roadmap:render` and `task project:render` are batch checkpoints, not per-edit taxes, and calling them N times for N lifecycle edits turns O(1) render work into O(N) without changing correctness (see #638)\n- ⊗ Return a final backlog view to the user without having run `task roadmap:render` and `task project:render` at least once since the last lifecycle edit -- batch the renders, but do not skip them\n\n## See also\n\n- Upstream skill: [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) -- the canonical triage hygiene + queue selection playbook. Refinement Phase 0a consults `task triage:summary` (D2 / #1122) and Phase 0b consumes `task triage:queue --state=accept` (D11 / #1128), both of which are produced by the triage skill's decision flow. `[RESUME]`-tagged items (Phase 0c) originate from D3 (#1123) `--resume-on` conditions documented in the triage skill's Phase 3.\n- Reversibility verb in Phase 4: `task scope:undo <file>` (D15 / #1134).\n- Onboarding (empty-cache fallback target): `task triage:welcome` (N3 / #1143) -- the single chained command a fresh post-upgrade install runs before re-entering refinement.\n- Refs: #1141 (this rewrite), #1119 (umbrella), #1122 (D2), #1128 (D11), #1123 (D3), #1130 (D6), #1134 (D15), #1143 (N3), #1149 (N9 routing).\n",
|
|
225
|
+
"body": "# Deft Directive Refinement\n\nConversational refinement session -- ingest, evaluate, reconcile, and prioritize scope xBRIEFs with the user.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n**Upstream pass**: refinement begins with a triage pass -- see [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) for the canonical cache-hygiene + \"what's next?\" queue playbook before continuing into the refinement flow below.\n\n**See also**: [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md) (canonical numbered-menu rule used by every Phase 0 / Phase 2-5 gate below) | `task cache:fetch-all` / `task cache:get` (Tier 1 unified content cache, #883 Story 2) | `task triage:bootstrap` / `task triage:accept` / `task triage:reject` / `task triage:defer` / `task triage:needs-ac` / `task triage:mark-duplicate` / `task triage:bulk-*` / `task triage:refresh-active` (Phase 0 action surface, #845 + #883 Story 3 rebind).\n\n## Platform Requirements\n\n! This skill requires **GitHub** as the SCM platform and the **GitHub CLI (`gh`)** to be installed and authenticated. Issue ingestion, origin freshness checks, and completion lifecycle all depend on `gh`.\n\n## Deterministic Questions Contract\n\n! Every numbered-menu prompt rendered in this skill (Phase 0 Triage action menu, Phase 2 Evaluate per-item accept/reject, Phase 3 Reconcile flagged-item walk, Phase 4 Promote/Demote lifecycle gates, Phase 5 Prioritize reorder gates) MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md): render the canonical numbered menu in chat unless the host UI visibly preserves numeric option labels and returns numeric selections or exact displayed option text. The final two numbered options MUST be `Discuss` and `Back`, in that order. The Discuss-pause semantic is documented verbatim there -- on `Discuss` selection the agent MUST halt the in-progress sequence immediately, prompt `What would you like to discuss?`, and resume only on an explicit user signal. Implicit resumption is forbidden, and fallback chat replies MUST map only to the displayed number or exact displayed option text.\n\n## When to Use\n\n- User says \"refinement\", \"reprioritize\", \"refine\", \"roadmap refresh\", or \"refresh roadmap\" (legacy v0.19 terms -- deft-directive-refinement is the current skill name)\n- User says \"triage\", \"action menu\", \"work the cache\", or \"pre-ingest\" -- first-class Phase 0 direct triggers introduced under #845; they route to Phase 0 (Triage), not the general refinement entry\n- New issues have accumulated since the last refinement session\n- Periodic maintenance pass (e.g. weekly or after a batch of user feedback)\n- User wants to review and organize the backlog\n\n! **Entry point (#1141, supersedes #845 / #883 action-menu).** Phase 0 -- Triage-first consultation is the canonical entry point for any refinement session. Phase 0 consults `task triage:summary` (D2 / #1122) and `task triage:queue --state=accept` (D11 / #1128) and pulls the `[RESUME]`-tagged slice (D3 / #1123) FIRST. Refinement does NOT itself triage cached candidates -- that work belongs to [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130). Phase 0 ! MUST chain into Phase 1 -- Ingest on completion (or surface the empty-cache fallback prompt when the cache has not yet been bootstrapped -- see Phase 0a below). Phase 1+ semantics are unchanged.\n\n## Prerequisites\n\n- ! `xbrief/` directory exists with lifecycle folders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`)\n- ! GitHub CLI (`gh`) is authenticated and can access the repo\n- ~ `PROJECT-DEFINITION.xbrief.json` exists (run `task project:render` if missing)\n\n## Session Model\n\nRefinement is a **conversational loop**, not a batch job. The user directs the flow:\n\n- \"Triage\" / \"action menu\" / \"work the cache\" / \"pre-ingest\" -> Phase 0 (Triage-first consultation, #1141) -- refinement consults the cache; the canonical decision-making playbook is `../deft-directive-triage/SKILL.md` (D6 / #1130)\n- \"Pull in issues\" / \"ingest\" -> Phase 0 ALWAYS runs first to consult `task triage:summary` + `task triage:queue --state=accept`; Phase 1 follows on the cohort Phase 0b produces (#1141)\n- \"Show proposed\" / \"evaluate\" -> Phase 2 (Evaluate)\n- \"Check origins\" / \"reconcile\" -> Phase 3 (Reconcile)\n- \"Accept these\" / \"reject that\" / \"promote\" / \"demote\" -> Phase 4 (Promote/Demote)\n- \"Reprioritize\" / \"reorder pending\" -> Phase 5 (Prioritize)\n- \"Close out\" / \"scope is done\" / \"completion\" -> Phase 6 (Completion Lifecycle)\n- \"Done\" / \"exit\" -> Exit\n\nThe agent may suggest the next phase, but the user decides. Phases can be entered in any order and repeated.\n\n## Branch Setup (Preflight)\n\n! Before making any changes, ensure you are working on a feature branch. This preflight runs before Phase 0 and again before Phase 1 if Phase 0 is auto-skipped.\n\n1. ! Check if the working tree has uncommitted changes that would conflict -- stop and ask the user to resolve them first\n2. ! Create or switch to a refinement branch (e.g. `refinement/YYYY-MM-DD`) if not already on one\n3. ! Confirm the branch and working directory to the user before proceeding\n\n## Phase 0 -- Triage-first consultation (cache-first, #1141)\n\n! Phase 0 is a thin consumer of the canonical triage cache: refinement consults `task triage:summary` (D2 / #1122) and `task triage:queue` (D11 / #1128) BEFORE walking any `xbrief/` lifecycle folder. The dedicated triage playbook lives at [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) -- refinement does NOT itself triage cached candidates; it consumes the queue's `accept` and `[RESUME]` slices and turns them into scope xBRIEFs.\n\n! Phase 0 runs three sub-phases in canonical order: **Phase 0a -- Triage gate** -> **Phase 0b -- Cache-first ingestion** -> **Phase 0c -- Resume conditions**. Each sub-phase MUST run before the next, and Phase 0 MUST chain into Phase 1 -- Ingest on completion. Numbered prompts in Phase 0 ! MUST follow [`../../contracts/deterministic-questions.md`](../../contracts/deterministic-questions.md) (`Discuss` / `Back` as the final two numbered options; Discuss-pause semantic applies verbatim).\n\n**See also (#883 Story 2):** the unified cache (`task cache:fetch-all --source=github-issue --repo OWNER/NAME`) is the sole content-mirroring surface in v0.26.0+. Tier 1 reads MUST go through `task cache:get -- github-issue OWNER/NAME/<N>`. The legacy \"Three-Tier Inventory Model\" + action-menu walk that lived here pre-#1141 has moved out of refinement and into `../deft-directive-triage/SKILL.md` (D6 / #1130); refinement now consumes the post-decision queue rather than producing decisions.\n\n### Phase 0a -- Triage gate (`task triage:summary`)\n\n1. ! Invoke `task triage:summary` (D2 / #1122) and capture the one-liner.\n2. ! **Empty-cache backward-compat fallback.** If the one-liner is the documented empty-cache prompt (`[triage] cache empty -- run task triage:bootstrap`), the agent ! MUST emit the verbatim recovery message to stderr BEFORE any folder scan:\n\n ```\n triage cache empty -- run `task triage:welcome` (N3 / #1143) to onboard, or `task triage:bootstrap` to seed the cache directly; refinement Phase 0 cannot consult the queue against an empty cache. Falling back to a legacy `xbrief/proposed/` folder scan only if you opt in.\n ```\n\n Then prompt the user `Fall back to legacy folder-scan against xbrief/proposed/ for this session? [y/N]` (default `N`). On `N`, exit refinement with the canonical `deft-directive-refinement complete -- exiting skill.` confirmation and the chaining instruction `Run task triage:welcome (N3 / #1143) to onboard, then re-enter refinement.`. On `y`, chain into Phase 1 against `xbrief/proposed/` as the legacy fallback. ! MUST NOT silently proceed without surfacing the breadcrumb to `task triage:welcome` -- a fresh post-upgrade install needs that pointer to find the canonical onboarding ritual.\n\n3. ! **Outstanding-work gate.** If the cache is populated AND any of `untriaged`, `stale-defer (resume condition met)`, or `in-flight` is non-zero, surface the one-liner verbatim to the user with the canonical recommendation:\n\n ```\n triage cache has outstanding work -- recommend running `skills/deft-directive-triage/SKILL.md` (D6 / #1130) first. Proceed to refinement anyway? [y/N]\n ```\n\n ~ Default is `N`: deferring to the triage skill is the documented happy path because refinement consumes `accept`-decisioned candidates and an untriaged backlog means there are fewer `accept` rows than there could be. On `N`, exit with the canonical confirmation phrasing and the chaining instruction `Run skills/deft-directive-triage/SKILL.md to clear the backlog, then re-enter refinement.`. On `y`, proceed to Phase 0b.\n\n4. ? When all counts are zero (cache populated, no outstanding work), proceed to Phase 0b without prompting.\n\n⊗ Skip Phase 0a -- refinement on top of an untriaged cache wastes the operator's time on items the triage skill would have rejected, deferred, or marked needs-AC.\n⊗ Bypass the empty-cache fallback prompt -- a silent proceed against an empty cache surfaces a misleading \"no candidates\" state and hides the upgrade-onboarding path from the operator.\n\n### Phase 0b -- Cache-first ingestion (`task triage:queue --state=accept`)\n\n1. ! Pull the ingestion candidate list via `task triage:queue --state=accept` (D11 / #1128). Each row is a cached issue whose latest audit-log decision is `accept` -- the canonical \"ready to become a scope xBRIEF\" cohort. ! MUST NOT enumerate `xbrief/proposed/` independently of the queue; the folder participates only via the join described in step 2.\n2. ! Join the queue against `xbrief/proposed/` (and the rest of the lifecycle folders) by `references[].uri`: queue rows whose issue is already represented by an existing xBRIEF surface as \"already tracked\"; queue rows with no matching xBRIEF are \"new accept candidates\". Items already in `xbrief/proposed/` continue to participate -- they are joined against the cache rather than enumerated separately.\n3. ~ When the join surfaces zero new candidates (every `accept` row already has a xBRIEF), Phase 0b is a clean no-op; chain straight into Phase 0c.\n4. ! For each new candidate, fall through to Phase 1 -- Ingest, which delegates the actual scope-xBRIEF write to `task issue:ingest` (or `task triage:accept`, which already ingests into `proposed/`). After the proposed artifact exists, promote with `task scope:promote -- --from-issue=<N> [--repo OWNER/NAME]` (#1136 / D18), or chain accept+promote via `task triage:accept -- --issue <N> --repo OWNER/NAME --auto-promote` when the operator wants pending/ in one step.\n\n⊗ Walk `xbrief/proposed/` directly as the primary ingestion surface -- the cache is the authoritative \"what is ready to refine?\" surface; the folder is the destination, not the source of truth.\n⊗ Drop items that exist in `xbrief/proposed/` but lack a matching cache row -- those are reconciled later (Phase 3 / origin reconciliation), not silently discarded.\n\n### Phase 0c -- Resume conditions (`[RESUME]`-tagged items first)\n\n1. ! Before walking new untriaged candidates from Phase 0b, process every `[RESUME]`-tagged row in the queue. `[RESUME]` rows surface from D3 (#1123) when a prior `defer` audit entry's `resume-on` condition fires (atomics: `ref:closed:#N`, `ref:merged:#N`, `date:>=YYYY-MM-DD`, `pending-count:>=N|<=N`, composed by a single top-level `AND` or `OR`).\n2. ! Stale-defer (resume-eligible) items take priority over fresh untriaged when both are present in the same Phase 0 pass -- the operator made a forward-dated decision on the deferred item and the framework is honouring it. Treat the `[RESUME]` slice as the FIRST class of candidates surfaced to the user.\n3. ~ The exact precedence in `task triage:queue` is `[ORPHAN]` -> `[RESUME]` -> `[URGENT]` -> untriaged -> other (per D11 + D13 / #1132 grouping). Refinement consumes this order verbatim and surfaces `[RESUME]` candidates first; `[ORPHAN]` rows are out-of-scope for refinement (they are handled by the triage skill's audit phase).\n\n⊗ Treat `[RESUME]` rows as \"leftover\" -- they are the highest-priority class refinement is meant to process, because the operator already decided to revisit them when the condition fired.\n\n### Pre-Phase-1 handoff\n\n1. ! Surface a one-line session summary: `{resume_eligible} resume-eligible, {new_accept} new accept candidate(s), {already_tracked} already tracked in xbrief/`.\n2. ! Chain into Phase 1 -- Ingest, which now operates on the cohort produced by Phase 0b's join (`[RESUME]` rows first, then new accept candidates).\n3. ? If the user opts out of Phase 1 (e.g. \"that's it for today\"), exit via the Phase 0 mid-session exit surface below -- ! MUST NOT route to the `### EXIT` block under `## PR & Review Cycle` because that block is the post-PR-creation exit path and references a `PR #{N}` that does not yet exist at this point in the flow.\n\n#### Phase 0 mid-session exit surface\n\n! When the user opts out of Phase 1 after completing (or partially completing) Phase 0, perform exactly these steps -- ! MUST NOT mention any PR number, since none has been created yet:\n\n1. ! Surface the outstanding-work tally: `{resume_eligible} resume-eligible candidate(s) still pending, {new_accept} accept candidate(s) not yet ingested -- these will resurface on the next Phase 0 entry.`\n2. ! Note the audit-log location verbatim using double-backtick fencing so the inner path renders correctly: ``Audit log preserved at `xbrief/.eval/candidates.jsonl`; queue state is reproducible via `task triage:queue --state=accept`.``\n3. ! Confirm skill exit with the canonical phrasing: `deft-directive-refinement complete -- exiting skill.`\n4. ! Provide the Phase-0-appropriate chaining instruction: ``Resume with `task triage:queue --state=accept` to inspect the queue, or re-enter the refinement skill when ready to continue.`` Do NOT reference a PR, a review cycle, or a monitor agent.\n\n⊗ Skip Phase 1 silently after Phase 0 -- always render the chaining decision so the user knows the entry point shifted.\n⊗ Mutate `xbrief/proposed/` directly during Phase 0 -- only `task issue:ingest` (called from Phase 1) is allowed to write there; Phase 0 is read-only against the cache.\n⊗ Route Phase 0 mid-session opt-out to the post-PR `### EXIT` block under `## PR & Review Cycle` -- that block surfaces a non-existent `PR #{N}` and confuses the user.\n\n## Phase 1 -- Ingest\n\n! Scan external sources for new work items and create proposed scope xBRIEFs.\n\n! **Pre-filing master-diff check (#1102).** When a refinement pass FILES a new GitHub issue that proposes ADDING a file or directory (rather than ingesting an existing issue), first run the pre-filing existence check from [`../deft-directive-gh-slice/SKILL.md`](../deft-directive-gh-slice/SKILL.md) Step 5 -- `git ls-tree origin/master -- <path>` (or `gh api repos/{owner}/{repo}/contents/{path}`) -- so a stale \"add file X\" issue is never opened against state that already exists on master (the #1099 -> #1100 close-and-refile recurrence).\n\n### Step 1: Gather Sources\n\n1. ? Scan non-GitHub sources (Jira, direct user requests, etc.) manually if applicable — those ingest paths are not yet task-wrapped\n2. ! GitHub issues are ingested via the task wrapper documented in Step 3 — the task fetches open issues itself, so no separate `gh issue list` call is needed\n\n### Step 2: Deduplicate via References (Dry-Run Preview)\n\n1. ? Run `task issue:ingest -- --all --dry-run` to preview which issues the ingest task would create scope xBRIEFs for. The task deduplicates candidates against `references` entries in existing xBRIEFs (across all lifecycle folders) so already-tracked issues are skipped automatically.\n2. ! Present the user with the list of new-vs-already-tracked items the dry-run reports: \"{N} new items found, {M} already tracked\"\n3. ! Wait for user approval before proceeding to ingest\n\n### Step 3: Ingest Approved Items\n\n! Delegate ingest to `task issue:ingest` — the task is the canonical implementation of scope-xBRIEF creation. Skills MUST NOT reinvent the slug rules, reference shape, or deduplication logic inline (see #537 for background).\n\n- **Single issue**: `task issue:ingest -- <N>` — creates `xbrief/proposed/YYYY-MM-DD-<slug>.xbrief.json` with origin `references`, canonical slug from `scripts/slug_normalize.py` (see [`../../conventions/vbrief-filenames.md`](../../conventions/vbrief-filenames.md)), and schema-conformant shape.\n- **Batch**: `task issue:ingest -- --all [--label <L>] [--status <S>]` — ingests every open issue matching the filters, skipping duplicates by `references.uri` match.\n- **Preview**: add `--dry-run` to either form to preview without writing files.\n\nThe task emits xBRIEFs conforming to the canonical v0.6 schema (`xbrief/schemas/xbrief-core.schema.json`) with origin references in the form documented in [`../../conventions/references.md`](../../conventions/references.md):\n\n```json\n\"references\": [\n {\n \"uri\": \"https://github.com/{owner}/{repo}/issues/{N}\",\n \"type\": \"x-xbrief/github-issue\",\n \"title\": \"Issue #{N}: {issue title}\"\n }\n]\n```\n\n- ! New scope xBRIEFs MUST target `\"xBRIEFInfo\": { \"version\": \"0.6\" }` (the task handles this automatically)\n- ! `plan.status` starts at `\"proposed\"`; the task sets this\n- ! Conform to `xbrief/schemas/xbrief-core.schema.json` (v0.6) -- the task validates before writing\n- ~ After ingest, review the generated xBRIEFs with the user before promoting any of them to `pending/`\n\n⊗ Hand-author scope xBRIEFs inside the skill when the ingest task exists — duplicating the narrative logic is how #534 (non-conformant references) and #537 (drift between skill and task) arise\n⊗ Write references with `url`/`id`/bare `github-issue` types — use the schema-conformant `{uri, type, title}` shape above\n⊗ Ingest an item that already has a matching xBRIEF reference -- `task issue:ingest` handles deduplication; skills MUST NOT duplicate that logic inline\n\n## Phase 2 -- Evaluate\n\n! List proposed items for interactive user review.\n\n### Step 1: List Proposed Items\n\n1. ! Read all xBRIEFs in `xbrief/proposed/`\n2. ! Present each item with:\n - Title and filename\n - Origin link(s) from `references`\n - Summary from `narratives` (if populated)\n - Labels/category (if available from origin)\n3. ! Sort by creation date (oldest first) or as user prefers\n\n### Step 2: Interactive Review\n\n! For each proposed item (or batch, as user directs):\n\n- ! Present the item and wait for user decision\n- ~ The user may: accept (promote to pending), reject (cancel), defer (keep in proposed), or request more detail\n- ! Do not proceed to the next item until the user responds\n- ? The user may batch-accept or batch-reject multiple items at once\n\n⊗ Auto-accept or auto-reject proposed items without user review\n\n## Phase 3 -- Reconcile (RFC D12)\n\n! Check if linked origins have changed since the xBRIEF was last touched. Delegate the scan to `task reconcile:issues` and walk the user through flagged items for approval (see #537 for why the skill is a thin wrapper over the task).\n\n### Step 1: Run the Reconciler\n\n```\ntask reconcile:issues\n```\n\nThe task scans every xBRIEF with a GitHub-backed reference (whether the reference uses the legacy `github-issue` bare type or the canonical `x-xbrief/github-issue` shape), fetches each linked issue, and reports items in these buckets:\n\n- **Linked & current** — an open origin issue has a matching xBRIEF (no action)\n- **Externally closed** — origin issue is `CLOSED` (propose cancellation or reconcile if intentional divergence)\n- **Unlinked** — open GitHub issue with no xBRIEF (flag for review)\n- **Completed-status drift** — a `completed/` brief whose `plan.status` is not terminal\n\n`task reconcile:issues` does **not** compare origin `updated_at` to the brief `updated` timestamp. Origin **content** staleness is fail-closed at implementation intent: `task xbrief:preflight` exits 1 when the live issue is newer than `xBRIEFInfo.updated` (#3363).\n\n### Step 2: Walk Flagged Items with the User\n\n1. ! When `task xbrief:preflight` (or a manual origin re-read) shows the live issue is newer than the brief, show the user the current xBRIEF against the origin body + comments (#2143). Propose a refresh **or** record intentional divergence and bump `xBRIEFInfo.updated`; ! wait for explicit user approval before writing anything. ⊗ Auto-write origin text onto the brief (#309 D12).\n2. ! For each **externally closed** item, ask the user whether to `task scope:cancel <file>` it or preserve intentional divergence.\n3. ! For each **unlinked** item, ask whether to attach an origin reference or leave the xBRIEF as-is.\n\n### Step 3: Apply User-Approved Updates\n\n- ! Agent proposes edits; ! user approves each change\n- ! Never auto-update xBRIEFs — intentional divergence (xBRIEF refined beyond original issue scope) must be preserved\n- ! For approved updates, update the xBRIEF content and `xBRIEFInfo.updated` timestamp; prefer the task commands (`task scope:cancel`, `task scope:block`, etc.) over hand-editing where they apply\n\n⊗ Replace the task invocation with a hand-written `gh issue view` loop — the task is the canonical implementation; skills MUST NOT duplicate it (#537)\n⊗ Auto-update xBRIEFs based on origin changes without user approval\n⊗ Overwrite intentional divergence -- if a xBRIEF has been refined beyond the original issue, preserve the refinement\n\n### Origin sync after material xBRIEF edits (#2540)\n\n! When this refinement pass **materially updates** an origin-linked scope xBRIEF (AC, `plan.status`, or `plan.items` statuses/titles), run `task issue:sync-from-xbrief -- <path>` to post a sync comment on the linked GitHub issue so the human-facing tracker stays current. Use `--dry-run` to preview the comment without posting.\n\n! If sync is intentionally skipped (offline, issue frozen, divergence is deliberate), document the skip reason in the session notes or PR body — do not silently leave the origin stale.\n\n⊗ Materially edit an origin-linked xBRIEF without running `issue:sync-from-xbrief` or documenting why it was skipped\n\n## Phase 4 -- Promote/Demote\n\n! Move xBRIEFs between lifecycle folders using deterministic task commands. The status values below align with the canonical v0.6 Status enum (`draft | proposed | approved | pending | running | completed | blocked | failed | cancelled`) — note that `failed` is also a valid terminal transition for active work that could not complete.\n\n### Effort estimate on accept (#1581)\n\n! When accepting an item from `proposed/` to `pending/` (`task scope:promote`), prompt for an optional `PlanItem.effort` estimate when plan items lack one. Time anchors: `S` <2h, `M` half-day (2-4h), `L` 1-2 days, `XL` needs breakdown before start.\n~ Prefer writing `effort` on each executable plan item so swarm sizing and `deft-directive-cost` have a per-item signal without a separate cost pass.\n! If the operator sets `effort: \"XL\"`, keep the scope in proposed/pending and break the item into S/M/L sub-items before any `task scope:activate` — activate fails closed on XL (#1581).\n? Omit `effort` when sizing is unknown; validation still passes (field is optional).\n! Plan-item effort is **post-planning** authority: it confirms or corrects provisional intake size at planning/accept time. It is **not** available at session start and MUST NOT be required for initial ceremony/ritual depth (#3214 two-stage rapid→escalate). Headless: no confirmation prompt required for estimates or stage transitions.\n\n### Available Commands\n\n- `task scope:promote <file>` -- proposed/ -> pending/ (status: pending)\n- `task scope:activate <file>` -- pending/ -> active/ (status: running)\n- `task scope:complete <file>` -- active/ -> completed/ (status: completed)\n- `task scope:cancel <file>` -- any -> cancelled/ (status: cancelled)\n- `task scope:restore <file>` -- cancelled/ -> proposed/ (status: proposed)\n- `task scope:block <file>` -- stays in active/ (status: blocked)\n- `task scope:unblock <file>` -- stays in active/ (status: running)\n- `task scope:fail <file>` (v0.6+) -- active/ -> completed/ (status: failed) — record a failure terminal state when a scope cannot complete but should not be cancelled\n- `task scope:undo <decision_id>` (D15 / #1134) -- reverse a single scope-lifecycle audit entry (`demote` -> re-promote, `cancel` -> restore-from-cancelled-to-prior-folder, `restore` -> re-cancel); terminal actions (`complete` / `fail`) are REFUSED -- use `git revert` or hand-edit\n- `task scope:undo --batch-id=<uuid>` (D15 / #1134) -- reverse every audit entry tagged with the batch_id (e.g. the cohort produced by `task scope:demote --batch`); idempotent on already-undone entries; the undo cohort is itself reversible via the `undo_batch_id` minted on the new entries. Optional `--dry-run` previews without writing.\n- `task scope:undo --latest` (D15 / #1134) -- reverse the most-recent reversible audit entry (`demote` / `cancel` / `restore` / `undo`) not already undone; convenience form used by the N6 / #1146 smoketest contract.\n\n### Workflow\n\n1. ! Execute transitions using the task commands above -- they handle `plan.status` updates, `plan.updated` timestamps, and file moves atomically\n2. ! Derived-artifact renders (`task roadmap:render`, `task project:render`) happen after a **batch** of promotions/demotions, not after each individual item. During high-volume triage (e.g. dozens of accept/reject decisions in one session), defer both renders until the end of the batch -- the source of truth is the lifecycle folder contents under `xbrief/`, so ROADMAP.md and PROJECT-DEFINITION.xbrief.json can be refreshed once per batch without losing correctness.\n3. ! `task roadmap:render` regenerates ROADMAP.md from the updated lifecycle folder contents. Call it once per batch (typically at the end of Phase 4, before handing back to the user or transitioning to Phase 5), not after every single promote/demote.\n4. ! `task project:render` refreshes the PROJECT-DEFINITION items registry. Call it **once per refinement pass** -- usually at the end of the session alongside the final roadmap render -- unless the user explicitly needs an intermediate registry refresh. It is not a per-edit tax.\n5. ! Before the user is shown the final backlog state (end of Phase 4, end of Phase 5, or session exit), both `task roadmap:render` AND `task project:render` MUST have been run at least once so ROADMAP.md and PROJECT-DEFINITION.xbrief.json reflect the current lifecycle folder truth. This preserves correctness while allowing N promotions/demotions to share one render checkpoint.\n6. ! Mark rejected items as `cancelled` via `task scope:cancel` (never delete xBRIEFs)\n\n~ Operationally: a large refinement session can ingest/evaluate/promote multiple issues and close out with **one** final render checkpoint, rather than N repetitive renders after every individual item.\n\n⊗ Rerender derived artifacts (`task roadmap:render`, `task project:render`) after every single accept/reject/promote/demote during high-volume triage -- batch the lifecycle edits and render once at the end of the batch\n⊗ Move xBRIEFs between folders manually (cp/mv) -- always use `task scope:*` commands\n⊗ Delete xBRIEFs -- use `task scope:cancel` to preserve history\n\n## Phase 5 -- Prioritize\n\n! Reorder and organize the pending backlog.\n\n1. ! List all xBRIEFs in `xbrief/pending/` with titles, origins, and any phase/dependency metadata\n2. ~ Help the user set phases and dependencies:\n - Group related items into phases (via xBRIEF `items` hierarchy or `tags`)\n - Identify dependencies between items (via `edges` in xBRIEF schema)\n3. ! `task roadmap:render` is the **checkpoint** before showing the reordered backlog to the user -- not a per-edit tax. Run it ONCE at the end of the reorder pass to regenerate ROADMAP.md from the updated pending/ contents. Do not invoke it after each individual reorder action.\n4. ~ Present the regenerated roadmap summary to the user for confirmation\n\n## Phase 6 -- Completion Lifecycle\n\n! On scope completion, update origins to close the loop.\n\n### When a Scope Completes\n\n1. ! Read the completed xBRIEF's `references` array\n2. ! For each GitHub-issue reference (either the legacy bare `github-issue` type or the canonical `x-xbrief/github-issue` shape):\n - Close the issue with a comment linking to the implementing PR:\n ```\n gh issue close {N} --comment \"Completed via PR #{PR} -- scope xBRIEF: {filename}\"\n ```\n - The issue number is extracted from the reference `uri` (e.g. `https://github.com/o/r/issues/{N}`)\n3. ? For other reference types (`x-xbrief/jira-ticket`, `x-xbrief/user-request`, `x-xbrief/github-pr`, etc.), follow the appropriate update mechanism\n4. ! Update PROJECT-DEFINITION via `task project:render`\n\n⊗ Complete a scope without updating its origins\n~ Completion lifecycle can be triggered during refinement or as a standalone action after a PR merge\n\n! When the refinement session files a new umbrella issue (or surfaces one whose current-shape comment is missing), file the umbrella then file its `## Current shape (as of pass-N)` comment per `## Umbrella current-shape convention` in `AGENTS.md` (#1152) -- the edit-in-place comment is the canonical surface every subsequent design pass updates.\n\n! Before reporting an umbrella or epic's current status to the operator (what is done, what blocks, wave order), fetch `repos/<owner>/<repo>/issues/<N>/comments` via REST, read the `## Current shape (as of pass-N)` comment and any linked context/`LockedDecisions` xBRIEF — never conclude status from the issue body alone (claim-cites-state-surface, #2066).\n\n~ Issue-label hygiene for any umbrella or child issue this skill files: before creating issues, inspect the target repo's existing labels with `gh label list` or the labels API; choose one or more suitable existing labels when practical, or explicitly note that no label was applied. This is a recommendation, not a gate -- do not block issue creation solely because no label fits, and do not invent ad hoc labels outside the repo's existing label set.\n\n! When a refinement pass produces a slicing event (rare but possible -- e.g. a design pass on an existing umbrella files N additional Wave-N child issues), record the cohort in `xbrief/.eval/slices.jsonl` via `scripts/slice_record.py::write_slice(...)` with `actor=\"skill:refinement\"` immediately after the children are filed (#1132 / D13). Same call shape as `skills/deft-directive-gh-slice/SKILL.md` Step 6. The cohort record is what makes `task triage:audit --orphans` able to detect Wave-2+ children whose umbrella closes prematurely; without it the production-side drift this surface guards against re-fires. Skip when the pass produced no new child cohort (e.g. a pure re-prioritization).\n\n\n! When the umbrella + children were filed by hand (legacy `gh issue create` / `issue_write` MCP / prior pass-N runs that pre-date this skill's slicing phase), use the canonical retro verb `task slice:record-existing` (#1147 / N7) -- it wraps the same `slice_record.write_slice` helper with `actor=\"manual:operator\"`, takes `--umbrella=N --children=A,B,C [--wave-N=...]` flags, validates each issue via the N5 / #1145 `scm.call` shim, and is idempotent on a matching umbrella + child set (re-run is a no-op; `--force` writes a second record for legitimate multi-session slicing). Companion `task slice:list` enumerates persisted slices for verification. The backfill verb is the canonical retro path for cohorts D13's writer never saw.\n\n## CHANGELOG Convention\n\n- ! Write ONE batch `CHANGELOG.md` entry at the END of the full refinement session -- not one entry per xBRIEF created or promoted. The batch entry summarizes all changes made during the session.\n- ⊗ Add a CHANGELOG entry after each individual action during refinement -- wait until the full session is complete and write a single summary entry.\n\n## PR & Review Cycle\n\nAfter all refinement work is complete:\n\n1. ! Ask the user: \"Ready to commit and create a PR?\"\n2. ! Wait for explicit user confirmation before proceeding.\n\n### Pre-Flight (before pushing)\n\n! Run all pre-flight checks BEFORE committing and pushing:\n\n1. ! Verify `CHANGELOG.md` has an `[Unreleased]` entry covering the refinement changes\n2. ! Run `task check` -- all checks must pass\n3. ! Verify `.github/PULL_REQUEST_TEMPLATE.md` checklist is satisfiable for this PR. If the file is **missing**, do NOT block — copy the canonical template from `templates/PULL_REQUEST_TEMPLATE.md` (ship-with-deft) to `.github/PULL_REQUEST_TEMPLATE.md` in the consumer project, then proceed with pre-flight (#531). If the file exists but contains unsatisfiable checklist items for this PR, call them out to the user before pushing.\n4. ! **Mandatory file review**: Re-read ALL modified files before committing. Explicitly check for:\n - Encoding errors (em-dashes corrupted to replacement characters, BOM artifacts)\n - Unintended duplication (accidental double xBRIEFs or duplicate entries)\n - Structural issues (malformed xBRIEF JSON, broken references)\n - Semantic accuracy (verify that counts and claims in CHANGELOG entries match the actual data)\n\n### Commit, Push, and Create PR\n\n1. ! Commit with a descriptive message: `docs(xbrief): refinement session -- {summary}`\n2. ! Push the branch to origin\n3. ! Create a PR targeting the appropriate base branch\n\n### Review Cycle Handoff\n\n! After the PR is created, automatically sequence into `skills/deft-directive-review-cycle/SKILL.md`.\n\n- ! Inform the user: \"PR #{N} created -- starting review cycle.\"\n- ! Follow the full review cycle skill from Phase 1 (Deft Process Audit) onward.\n\n### EXIT\n\n! When the review cycle completes (exit condition met) or the PR is ready for human review:\n\n1. ! Explicitly confirm skill exit: \"deft-directive-refinement complete -- exiting skill.\"\n2. ! Provide chaining instructions to the user/agent:\n - If review cycle is complete and PR is approved: \"PR #{N} is ready for human merge review.\"\n - If review cycle is still in progress: \"Review cycle handed off to deft-review-cycle. Monitor PR #{N} for Greptile findings.\"\n - If returning to a monitor agent: \"Returning control to monitor agent -- refinement PR #{N} created and review cycle initiated.\"\n3. ! Do NOT continue into adjacent work after this point -- the skill boundary is an exit condition.\n\n## Anti-Patterns\n\n- ⊗ Bypass Phase 0 by walking `xbrief/proposed/` or `gh issue list` directly -- `task triage:queue --state=accept` (D11 / #1128) is the canonical ingestion-candidate surface (#1141)\n- ⊗ Skip Phase 0a's `task triage:summary` invocation -- the triage-gate decision (run the triage skill first vs proceed) depends on its output (#1141 / D2 / #1122)\n- ⊗ Silently proceed against an empty cache -- emit the canonical `task triage:welcome` (N3 / #1143) breadcrumb to stderr first (#1141)\n- ⊗ Treat `[RESUME]`-tagged items as leftover -- they are the highest-priority class refinement processes (#1141 / D3 / #1123)\n- ⊗ Skip Phase 1 silently after Phase 0 -- always render the chaining decision so the user knows the entry point shifted (#1141, supersedes #845)\n- ⊗ Auto-accept or auto-reject proposed items without user review\n- ⊗ Create xBRIEFs without origin provenance (`references` linking to the source)\n- ⊗ Ingest items without deduplicating against existing xBRIEF references first\n- ⊗ Auto-update xBRIEFs based on origin changes -- user approves all updates\n- ⊗ Overwrite intentional divergence when reconciling stale origins\n- ⊗ Move xBRIEFs between folders manually -- always use `task scope:*` commands\n- ⊗ Delete xBRIEFs -- use `task scope:cancel` to preserve history\n- ⊗ Complete a scope without updating its origins (closing issues, posting comments)\n- ⊗ Skip deduplication during ingest -- always diff against existing references\n- ⊗ Add a CHANGELOG entry per individual action during refinement -- write one batch entry at the end of the full session\n- ⊗ Proceed to the next proposed item without waiting for user decision during evaluate\n- ⊗ Auto-push without explicit user instruction\n- ⊗ Rerender ROADMAP.md or PROJECT-DEFINITION.xbrief.json after every single accept/reject/promote/demote during high-volume triage -- `task roadmap:render` and `task project:render` are batch checkpoints, not per-edit taxes, and calling them N times for N lifecycle edits turns O(1) render work into O(N) without changing correctness (see #638)\n- ⊗ Return a final backlog view to the user without having run `task roadmap:render` and `task project:render` at least once since the last lifecycle edit -- batch the renders, but do not skip them\n\n## See also\n\n- Upstream skill: [`../deft-directive-triage/SKILL.md`](../deft-directive-triage/SKILL.md) (D6 / #1130) -- the canonical triage hygiene + queue selection playbook. Refinement Phase 0a consults `task triage:summary` (D2 / #1122) and Phase 0b consumes `task triage:queue --state=accept` (D11 / #1128), both of which are produced by the triage skill's decision flow. `[RESUME]`-tagged items (Phase 0c) originate from D3 (#1123) `--resume-on` conditions documented in the triage skill's Phase 3.\n- Reversibility verb in Phase 4: `task scope:undo <file>` (D15 / #1134).\n- Onboarding (empty-cache fallback target): `task triage:welcome` (N3 / #1143) -- the single chained command a fresh post-upgrade install runs before re-entering refinement.\n- Refs: #1141 (this rewrite), #1119 (umbrella), #1122 (D2), #1128 (D11), #1123 (D3), #1130 (D6), #1134 (D15), #1143 (N3), #1149 (N9 routing).\n",
|
|
226
226
|
"frontmatter_extra": "triggers:\n - refinement\n - reprioritize\n - refine\n - roadmap refresh\n - refresh roadmap\n - triage\n - action menu\n - work the cache\n - pre-ingest"
|
|
227
227
|
},
|
|
228
228
|
{
|
|
@@ -316,7 +316,7 @@
|
|
|
316
316
|
],
|
|
317
317
|
"path": "skills/deft-directive-sync/SKILL.md",
|
|
318
318
|
"version": "0.1",
|
|
319
|
-
"body": "# Deft Directive Sync\n\nSession-start framework sync and upgrade handoff -- refresh the framework deposit via npm + `directive update` / `deft update`, validate xBRIEF lifecycle structure, detect stale origins (RFC D12), then finish SCM release handoff in a named terminal state (#1604).\n\n> **Canonical bootstrap / update path (#761 / #1604):** Install and upgrade via npm: `npm i -g @deftai/directive` (install) or `npm i -g @deftai/directive@latest` (upgrade); Node >= 20 is required. Then from the project root run `directive update` (or `deft update`) to refresh `.deft/core/`, optionally `deft migrate` for npm provenance, and `directive doctor` / `deft doctor` / `task doctor` to confirm deposit health. For machines without Node, the frozen legacy Go installer (`deft-install` / platform-specific `install-*` from GitHub Releases) is a no-Node bootstrap bridge (#1912) -- migrate to npm once Node is available. Legacy `run upgrade` / `task upgrade` are metadata-only acknowledgment (they do NOT replace the payload). **Git-submodule / `task framework:doctor` paths are back-compat only** -- Phases 1-2 below are the legacy update flow, de-emphasized in UPGRADING.md / README. Deposit success is not upgrade released; Phase 8 records one terminal state: `released` | `pr-open` | `blocked:<reason>`. See UPGRADING.md and #761 / #1912 / #1604.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n## Platform Requirements\n\n! This skill requires **GitHub** as the SCM platform and the **GitHub CLI (`gh`)** to be installed and authenticated for origin freshness (Phase 5) and for the PR path of Phase 8 SCM release handoff. Origin freshness checks fetch issue data via REST-equivalent `gh` surfaces (prefer `gh api repos/<owner>/<repo>/issues/<N>` over GraphQL-heavy forms when under rate pressure; #954).\n\n## When to Use\n\n- User says \"good morning\", \"update deft\", \"update directive\", \"upgrade framework\", \"update xbrief\", or \"sync frameworks\"\n- Beginning of a new session where framework updates may be available\n- After a known upstream deft / `@deftai/directive` release\n- After a successful local deposit when the default branch still lacks the framework update\n\n## Missing CLI / PATH remediation\n\n! When `directive`, `deft`, or the global npm bin is missing from PATH (or `npm i -g @deftai/directive@latest` has not been run), surface actionable install remediation first:\n\n```bash\nnpm i -g @deftai/directive@latest\n```\n\n(or the pnpm equivalent: `pnpm add -g @deftai/directive@latest`). Then re-run `directive update` / `deft update` and `directive doctor`.\n\n⊗ Send the operator to manual GitHub release-asset archaeology or Go installer discovery as the happy path when Node is available -- npm is the primary remediation (#761 / #1604).\n\n## Session orientation — unmanaged header (#2065)\n\n! The region of AGENTS.md **above** the `<!-- deft:managed-section ... -->` marker is project-owned, preserved verbatim on refresh, and **not** freshness-checked by `deft doctor`.\n\n- ! Do NOT treat that unmanaged header as the work queue — consult `deft triage:queue`, `xbrief/` lifecycle, GitHub issues, and `PROJECT-DEFINITION.xbrief.json` instead (#1149, #2065 Option A).\n- ⊗ Do NOT add or revive `Status`, `Next:`, or `Known Issues` blocks in AGENTS.md — they duplicate authoritative sources and rot silently while the managed section stays current.\n\n## Framework Events Emitted Here\n\n! When this skill responds to a context-window shift or an explicit \"are you using Deft?\" probe (per AGENTS.md Deft Alignment Confirmation), emit the paired `session:interrupted` -> `session:resumed` framework events via `scripts/_events.py` so observability of agent-runtime state transitions is structural, not prose-only:\n\n- ! Before re-confirming alignment: `python -m scripts._events emit session:interrupted --session-id <id> --reason context-window-shift`\n- ! Immediately after the alignment confirmation line: `python -m scripts._events emit session:resumed --session-id <id> --interrupted-id <id-from-prior-emit>`\n- ⊗ Emit a `session:resumed` whose `interrupted_id` does not reference a prior `session:interrupted` -- such records are orphan and rejected by `scripts._events.validate_pairing` (#635 events behavioral wiring)\n\n## Pre-Cutover Detection Guard\n\n! Before proceeding with sync, detect whether the project uses the pre-v0.20 document model and report model state.\n\n### Detection Criteria\n\nA project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `scripts/_precutover.py`; when in doubt, the helper is canonical.\n\n1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `xbrief/specification.xbrief.json` plus all five lifecycle folders exist.\n2. `PROJECT.md` exists and contains neither the legacy `<!-- deft:deprecated-redirect -->` sentinel NOR the current `Purpose: deprecation redirect` canonical-banner marker (real content, not a deprecation redirect)\n3. `xbrief/specification.xbrief.json` exists but the lifecycle folders (`xbrief/proposed/`, `xbrief/pending/`, `xbrief/active/`, `xbrief/completed/`, `xbrief/cancelled/`) do NOT exist\n\n### Action on Detection\n\n! If pre-cutover state is detected, display the actionable migration message, then **skip Phases 0-6** and proceed directly to Phase 7 with the Document Model line set to \"pre-v0.20 (legacy)\". Phase 8 still applies if a local migration/framework change must land on the default branch after the frozen migrator path:\n\n> \"This project uses the pre-v0.20 document model. Current npm releases no longer ship in-product `task migrate:vbrief` (#2068). Follow UPGRADING.md § Frozen pre-v0.20 document-model migration: pin framework v0.59.0, install Python 3.11+ and uv, run `task migrate:vbrief` once from that payload, then upgrade to current npm.\"\n\n! Include specific details about what was detected:\n\n- Missing lifecycle folders: \"Create lifecycle folders via the frozen v0.59.0 migrator (#2068), or manually add `xbrief/{proposed,pending,active,completed,cancelled}/` after migrating narratives\"\n- `SPECIFICATION.md` with real content: \"SPECIFICATION.md contains non-redirect content -- this file is deprecated; use scope xBRIEFs in `xbrief/` instead\"\n- `PROJECT.md` with real content: \"PROJECT.md contains non-redirect content -- this file is deprecated; use `PROJECT-DEFINITION.xbrief.json` instead\"\n- Missing `PROJECT-DEFINITION.xbrief.json`: \"Run `task project:render` to generate the project definition\"\n- Scope xBRIEF in wrong folder: \"Status is '{status}' but file is in {folder}/ -- run `task scope:activate <file>` to fix\"\n\n### Model State in Sync Output\n\n! Include a **Document Model** line in the Phase 7 summary:\n\n- Pre-cutover detected: \"**Document Model**: pre-v0.20 (legacy) -- follow UPGRADING.md § Frozen pre-v0.20 document-model migration (#2068)\"\n- Post-cutover (lifecycle folders present, no stale artifacts): \"**Document Model**: v0.20+ (xBRIEF-centric) -- OK\"\n- Post-cutover with tampered placeholders: \"**Document Model**: v0.20+ with warnings -- SPECIFICATION.md or PROJECT.md contains non-redirect content\"\n\n⊗ Skip model state detection during sync -- always report the document model state.\n⊗ Silently ignore pre-cutover artifacts -- the user must be informed with an actionable command to fix the state.\n\n## Phase 0 -- Primary upgrade (npm deposit) (#761 / #1604)\n\n! Treat npm + `directive update` / `deft update` as the **primary** consumer upgrade path when an upgrade is authorized. Do not lead with submodule update when Node is available.\n\n### 0a: When mutation is authorized\n\n! **Mutating** engine install / deposit refresh is authorized only when at least one of:\n\n1. The operator used an **explicit upgrade** trigger: `update deft`, `update directive`, `upgrade framework`, or equivalent (\"upgrade Directive\", \"run update\").\n2. Doctor / payload-staleness already reports the deposit is **behind** and the operator confirmed the upgrade (or autonomous upgrade was pre-approved).\n3. CLI is **missing** from PATH -- then Missing CLI remediation may install the global package so doctor/update can run.\n\n! For routine session orientation triggers (`good morning`, `sync frameworks`, plain `update xbrief` without upgrade language):\n\n1. ! Run **read-only** checks: CLI present?, `directive doctor` / `deft doctor` / `task doctor` when available, structure validation (Phases 3+).\n2. ! If doctor reports a stale deposit or available upgrade, **report** the recommended command and ask for consent before mutating.\n3. ⊗ Run `npm i -g @deftai/directive@latest` or `directive update` / `deft update` on a routine \"good morning\" without staleness evidence **and** operator consent (or pre-approved autonomous upgrade).\n\n### 0b: Consumer worktree isolation before deposit\n\n! Before any mutating deposit that will be handed off in Phase 8:\n\n1. ! Run `git status --porcelain` at the **project root** (not only the legacy submodule).\n2. ! If the worktree or index has non-framework product changes (or any unexpected staged paths), **stop** and either:\n - ask the operator to stash / commit product work first, or\n - record `blocked:dirty-worktree` and skip deposit mutation,\n - or, with explicit consent, isolate product changes (stash including index) so the deposit cannot mix with them.\n3. ! After deposit, stage **only** framework-managed paths for the upgrade commit (e.g. `.deft/core/`, managed AGENTS section, hooks, VERSION / marker files). Reconstruct a clean index if needed rather than `git add -A`.\n4. ⊗ Create a framework-only commit or PR from a mixed worktree/index that still carries product feature paths.\n\n### 0c: Engine + deposit (when authorized)\n\n1. ! Confirm the global CLI is available (`directive --version` or `deft --version`). If missing, run Missing CLI / PATH remediation above, then continue.\n2. ! Upgrade the global engine only when mutation is authorized (0a):\n\n```bash\nnpm i -g @deftai/directive@latest\n```\n\n3. ! From the **project root**, after worktree isolation (0b), refresh the deposit:\n\n```bash\ndirective update\n# or: deft update\n```\n\n4. ~ Optionally stamp npm provenance (idempotent): `directive migrate` / `deft migrate`.\n5. ! Verify deposit health:\n\n```bash\ndirective doctor\n# or: deft doctor / task doctor\n```\n\n6. ! Record whether the working tree now has **framework-only** changes under `.deft/core/`, managed AGENTS section, hooks, or related managed files that need SCM release.\n\n### 0d: Framework-only change-set discipline\n\n! Keep upgrade commits/PRs **framework-only** -- do not mix product feature work into the same commit or PR as the deposit refresh.\n\n⊗ Treat a successful deposit alone as `released` -- the default branch must carry the update (or a PR must be open) before the operator goal is complete (#1604).\n⊗ Force a global CLI upgrade or deposit mutation on routine session sync without consent or staleness evidence.\n\n## Phase 1 -- Pre-flight (legacy submodule path)\n\n! **Legacy / back-compat only.** Run Phases 1-2 only when the consumer still uses a `deft/` git submodule layout and cannot use the npm deposit path. Prefer Phase 0 for all npm-managed installs.\n\n! Check that the deft/ submodule working tree is clean before attempting any update.\n\n1. ! Run `git -C deft status --porcelain`\n2. ! If output is non-empty (dirty working tree): **stop** and ask user whether to stash (`git -C deft stash`) or abort the sync entirely. Do NOT proceed with a dirty submodule. Record terminal state `blocked:dirty-submodule` if the operator aborts.\n3. ! Record the current DEFT commit for later comparison:\n ```\n git -C deft log --oneline -1\n ```\n4. ! Present the current state to the user:\n - Current DEFT commit (hash + subject)\n - Clean/dirty status\n - Confirmation that pre-flight passed (or the blocker if dirty)\n\n## Phase 2 -- Update DEFT Submodule (legacy / back-compat)\n\n! **Legacy / back-compat only** -- not the primary consumer upgrade path (#1604). Submodule update does not replace Phase 0 for npm installs.\n\n1. ! Run the submodule update:\n ```\n git submodule update --remote --merge deft\n ```\n2. ! Show what changed by comparing before/after:\n ```\n git -C deft log --oneline <old-hash>..HEAD\n ```\n3. ~ If no new commits, report \"deft submodule already up to date\" and proceed to Phase 3.\n\n## Phase 3 -- Structure Validation\n\n! Validate the xBRIEF lifecycle folder structure and project files.\n\n### 3a: Lifecycle Folder Structure\n\n! Verify all required lifecycle folders exist:\n\n1. ! Check that the following directories exist under `./xbrief/`:\n - `proposed/`\n - `pending/`\n - `active/`\n - `completed/`\n - `cancelled/`\n2. ! Report any missing folders with a clear warning:\n - \"WARNING: xbrief/{folder}/ does not exist -- lifecycle structure is incomplete\"\n3. ~ If folders are missing, suggest `task migrate:preflight` and the frozen v0.59.0 migrator path (#2068), or creating them manually after migration\n\n### 3b: PROJECT-DEFINITION.xbrief.json Validation\n\n! Validate the project identity gestalt file:\n\n1. ! Check that `./xbrief/PROJECT-DEFINITION.xbrief.json` exists\n - If missing: \"WARNING: PROJECT-DEFINITION.xbrief.json not found -- run `task project:render` to create\"\n2. ! If the file exists, validate it is well-formed:\n - Valid JSON (`python3 -m json.tool` or equivalent)\n - Top-level `xBRIEFInfo` envelope with `version` field equal to `\"0.6\"`\n - `plan` object with `title`, `status`, and `items` fields present\n - `plan.narratives` values are plain strings (not objects or arrays)\n3. ! **Freshness check**: Compare `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated`) against recent scope completions:\n - Scan `xbrief/completed/` for xBRIEFs with `xBRIEFInfo.updated` timestamps newer than the PROJECT-DEFINITION timestamp\n - If stale: \"WARNING: PROJECT-DEFINITION.xbrief.json may be stale -- {N} scopes completed since last update. Run `task project:render` to refresh.\"\n\n### 3c: Validate Root-Level xBRIEF Files\n\n! Validate all `./xbrief/*.xbrief.json` files at the xbrief root:\n\n1. ! Check each file is valid JSON\n2. ! Verify structural conformance:\n - Top-level `xBRIEFInfo` envelope with `version` field present\n - `plan` object with `title`, `status`, and `items` fields present\n - `plan.status` values from valid enum: draft, proposed, approved, pending, running, completed, blocked, cancelled\n3. ~ Use `task xbrief:validate` if available for deeper validation\n4. ! Report any validation failures with file name and specific violation\n\n⊗ Overwrite or modify project-level `./xbrief/*.xbrief.json` files -- those are project data, not framework files. Report issues and let the user decide how to fix them.\n\n## Phase 4 -- Lifecycle Consistency Check\n\n! Verify that each scope xBRIEF's `plan.status` matches its folder location.\n\n1. ! Scan all scope xBRIEFs in lifecycle folders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`)\n2. ! For each xBRIEF, check `plan.status` against the expected statuses for its folder:\n - `proposed/`: status should be `draft` or `proposed`\n - `pending/`: status should be `approved` or `pending`\n - `active/`: status should be `running` or `blocked`\n - `completed/`: status should be `completed`\n - `cancelled/`: status should be `cancelled`\n3. ! Report any mismatches:\n - \"MISMATCH: {filename} in {folder}/ has status '{status}' -- expected one of [{expected_statuses}]\"\n4. ~ Per `vbrief/vbrief.md` convention, trust the status field and suggest correcting the folder location:\n - \"Suggested fix: move {filename} to {correct_folder}/ (status '{status}' is authoritative)\"\n\n⊗ Auto-move xBRIEFs to fix folder/status mismatches -- report only; user decides during refinement or ad-hoc\n\n## Phase 5 -- Origin Freshness (RFC D12)\n\n! For xBRIEFs with external origin references, detect staleness and externally-closed origins.\n\n### Step 1: Scan Origins\n\n1. ! For each xBRIEF in `proposed/` and `pending/` with a `github-issue` reference in `plan.references` or top-level `references`:\n - Extract the issue number from the reference URL or `id` field\n - Fetch the issue: `gh issue view {N} --repo {owner/repo} --json updatedAt,state`\n2. ! Compare the issue's `updatedAt` against the xBRIEF's `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated` field)\n\n### Step 2: Categorize and Report\n\n1. ! **Stale origins** -- issue `updatedAt` is newer than xBRIEF `updated` timestamp:\n - \"{N} xBRIEFs have origins updated since last sync\"\n - List each: \"{filename}: Issue #{N} updated {time_delta} ago\"\n2. ! **Externally closed origins** -- issue state is `CLOSED`:\n - \"{N} xBRIEFs have origins that were closed externally\"\n - List each: \"{filename}: Issue #{N} is closed ({close_reason})\"\n3. ~ **Current origins** -- no changes detected (report count only)\n\n### Step 3: Recommendation\n\n- ! Report only -- never auto-update xBRIEFs based on origin changes\n- ~ If stale or externally-closed xBRIEFs are found, suggest: \"Run a refinement session (`skills/deft-directive-refinement/SKILL.md`) to reconcile stale origins with user approval.\"\n\n⊗ Auto-update xBRIEFs based on origin freshness checks -- report only; user decides during refinement\n\n## Phase 6 -- Framework Sync\n\nAfter structure validation, sync framework-level assets.\n\n### 6a: Check AGENTS.md freshness\n\n~ Compare the project's `AGENTS.md` against the deft template (if a template exists in the updated deposit / `.deft/core/` or legacy `deft/` submodule):\n\n1. ~ Diff the structure (section headings, key rules) rather than expecting byte-identical content\n2. ~ Report any new sections or rules added upstream that are missing locally\n3. ~ Do NOT auto-overwrite -- present differences and let the user decide\n4. ~ If the unmanaged header still carries `Status`, `Next:`, or `Known Issues`, recommend replacing them with the **Session orientation** pointer at `xbrief/` + triage + issues (#2065 Option A) -- do NOT treat that header prose as the work queue\n\n### 6b: Check codebase MAP freshness\n\n~ If `./.planning/codebase/MAP.md` exists, or `PROJECT-DEFINITION.xbrief.json` declares a `projectionManifest[]` entry with `kind: \"codebase-map\"`, run `task verify:codebase-map-fresh` when the command resolves. If it reports drift, recommend `task codebase:map` and note that the generated MAP is advisory unless the operator asked to refresh projections.\n\n- ! Keep `plan.architecture.codeStructure` and configured provider artifacts authoritative; the MAP is a generated projection.\n- ⊗ Auto-edit canonical xBRIEF metadata to make the MAP fresh during sync -- report drift and let the operator choose a follow-up.\n\n### 6c: List new skills\n\n! Compare the `skills/` directory (or deposited `.deft/core/` skills) before and after the update:\n\n1. ! List any new skill directories added in the update\n2. ~ For each new skill, read its frontmatter `description` field and present a one-liner\n3. ~ Mention if any existing skills were updated (changed files)\n\n## Phase 6d -- Legacy Artifact Review (post-migration, one-time)\n\n! If `xbrief/migration/LEGACY-REPORT.md` exists (and has NOT been renamed to `LEGACY-REPORT.reviewed.md`), walk the operator through each captured legacy section and record their disposition inline in the same file. This phase surfaces the non-canonical content that `task migrate:xbrief` preserved via the `LegacyArtifacts` narrative mechanism (#505).\n\n### Detection\n\n1. ! Check for `xbrief/migration/LEGACY-REPORT.md` in the project root.\n2. ! If the file is absent or `LEGACY-REPORT.reviewed.md` exists (reviewed form), skip Phase 6d silently and proceed to Phase 7.\n3. ! If `LEGACY-REPORT.md` is present and has NOT been renamed, begin the review loop below.\n\n### Review loop\n\n1. ! Present the report summary (sources + per-bucket section counts) to the user.\n2. ! For each captured section listed under `## specification.xbrief.json -> LegacyArtifacts`, `## PROJECT-DEFINITION.xbrief.json -> LegacyArtifacts`, and `## PRD.md content (flagged: hand-edited)`:\n - Restate the section title, source file + line range, and size.\n - Offer exactly three disposition options: **Keep** (leave inside `LegacyArtifacts`), **Fold into {suggested narrative}** (move into a canonical narrative key), or **Drop** (remove from `LegacyArtifacts`, with explicit user confirmation).\n - ~ If a sidecar pointer is present (`xbrief/legacy/{stem}-{slug}.md`), open the sidecar for the user before offering options so the full content is visible.\n3. ! Record each disposition inline in the same `LEGACY-REPORT.md` file under a new `## Reviewed` section with one entry per legacy item: original section, user's decision, target location (if folded) or confirmation note (if kept/dropped), and the reviewer's timestamp.\n4. ! For a **Fold** decision, the agent updates the target xBRIEF's narrative key AND deletes only the corresponding section from the `LegacyArtifacts` narrative -- never the file.\n5. ! For a **Drop** decision, the agent removes only the corresponding section from the `LegacyArtifacts` narrative.\n6. ! Once all sections carry a recorded disposition, rename the file to `LEGACY-REPORT.reviewed.md`. The file is kept so the audit trail remains -- ⊗ MUST NOT delete either form.\n\n### Anti-patterns\n\n- ⊗ Delete `LEGACY-REPORT.md` or `LEGACY-REPORT.reviewed.md` -- these are the migration audit trail and MUST persist.\n- ⊗ Auto-dispose of legacy artifacts without user input -- every section requires an explicit decision.\n- ⊗ Rename to `.reviewed.md` before every captured section has a recorded disposition in the `## Reviewed` section.\n- ⊗ Drop a legacy section without explicit user confirmation (even if the section looks obviously stale).\n- ⊗ Silently delete sidecar files under `xbrief/legacy/` -- they are referenced from `LegacyArtifacts` and are part of the audit trail.\n\n## Phase 6e -- Doc-sprawl awareness (advisory, #647)\n\nDoc sprawl is a project-health concern, not just a human-experience one: a lean, well-written AGENTS.md sitting on top of a large reachable doc corpus does **not** stop agents from discovering and loading those docs (Augment Code study, `content/docs/good-agents-md.md`). It degrades agent quality silently until measured. This step **surfaces** the risk; it is ADVISORY and MUST NOT block or fail the sync.\n\n1. ~ Scan the project's reachable documentation footprint: the top-level `docs/` / `_docs/` directories, nested `README.md` files, and any `architecture` / `design` docs.\n2. ~ Flag, as a non-blocking nudge, when any of these appear:\n - A large `docs/` (or `_docs/`) directory that is **not referenced** from the AGENTS.md reference chain (orphan docs are discovered <10% of the time yet still cost context when found -- the reference-chain contract, #644).\n - Deeply nested READMEs that duplicate guidance the reference chain already carries.\n - Architecture / design docs that restate what the codebase already shows (a measured overexploration trigger).\n3. ~ Point the operator at `content/docs/agent-docs.md` (the empirically-grounded structure pattern) and the `REFERENCES.md` reference-chain contract for remediation. For directive's own always-loaded file, the `verify:agents-md-budget` ratchet (#645) and the consumer advisory (`agentsMdAdvisory`, #2155) are the size guards.\n4. ⊗ Do NOT convert this into a hard gate or auto-delete any doc -- the value is the nudge at the right moment; thresholds are a judgment call the operator owns.\n\n## Phase 7 -- Summary\n\n! Present a consolidated summary to the user covering:\n\n1. **Upgrade path used**: npm deposit (Phase 0) / legacy submodule (Phases 1-2) / already up to date\n2. **DEFT / deposit version change**: old version or commit -> new (or \"already up to date\")\n3. **Structure validation**: lifecycle folders status (all present / missing folders listed)\n4. **PROJECT-DEFINITION status**: valid / missing / stale (with freshness details)\n5. **xBRIEF validation results**: pass/fail per file, with details on any failures\n6. **Lifecycle consistency**: all consistent / N mismatches found (with details)\n7. **Origin freshness**: N stale / N externally-closed / N current (with details)\n8. **Document Model**: pre-v0.20 (legacy) / v0.20+ (xBRIEF-centric) OK / v0.20+ with warnings (see Pre-Cutover Detection Guard)\n9. **AGENTS.md status**: current / has upstream changes / needs review\n10. **Codebase MAP status**: current / stale / absent / not configured (advisory)\n11. **New skills**: list any newly added skills with descriptions\n12. **Pending SCM release**: whether framework-only changes still need commit/push/PR/merge (Phase 8)\n\n! After a successful deposit (or submodule bump), **do not stop at the local change set**. Proceed to Phase 8 SCM release handoff. If there is nothing to release (already on default branch / no local framework delta), record terminal state `released` when the default branch already carries the current framework update; otherwise name the next release step.\n\n? For the legacy submodule path only, if a bump is ready and the operator has not yet approved a commit, ask: \"Shall I commit the submodule update and continue SCM release handoff?\" -- do NOT auto-commit without approval. Prefer message:\n\n```\nchore(deft): update deft submodule to <short-hash>\n```\n\nFor npm deposit changes, prefer a framework-only commit message such as:\n\n```\nchore(deft): refresh framework deposit to <version>\n```\n\n## Phase 8 -- SCM release handoff (#1604)\n\n! After a successful framework deposit (Phase 0) or legacy submodule bump (Phases 1-2), carry the update through consumer SCM release. Installer/update success is not upgrade released.\n\n! Record **exactly one** terminal state when this skill exits after a deposit-related run:\n\n| Terminal state | Meaning |\n| --- | --- |\n| `released` | Default branch carries the framework update (merged or committed directly under policy). |\n| `pr-open` | Framework-only branch pushed and PR opened; awaiting review/merge per policy. |\n| `blocked:<reason>` | Explicit blocker (examples: `blocked:dirty-worktree`, `blocked:auth`, `blocked:branch-protection`, `blocked:human-merge-gate`, `blocked:ci`, `blocked:operator-declined`). |\n\n### 8a: Policy detection\n\n1. ! Read consumer branch policy: `plan.policy.allowDirectCommitsToMaster`, `plan.policy.requireHumanMerge`, and any known branch-protection / default-branch rules (`deft policy:show` when available).\n2. ! Classify the path:\n - **PR path (default when protected or human-merge):** branch protection enabled, or `requireHumanMerge` is true, or direct commits to default branch are disallowed.\n - **Direct-commit path:** `allowDirectCommitsToMaster` (or equivalent) is true **and** human-merge is not required **and** branch protection does not forbid the commit.\n\n### 8b: PR-oriented path (branch-protected / human-merge)\n\n1. ! With operator consent (or autonomous consent when the operator already approved upgrade handoff), create a **framework-only** branch (e.g. `chore/deft-update-<version>`), commit framework deposit files only, push, and open a PR targeting the default branch.\n2. ! Stop at terminal state **`pr-open`** once the PR URL is available -- unless policy explicitly allows bot merge **and** the operator directed merge.\n3. ⊗ Auto-merge past `requireHumanMerge` / the human merge gate (#1193). Agents may open PRs; they do not merge when policy forbids it.\n4. ⊗ Claim `released` when the PR is only open or only locally committed.\n\n### 8c: Direct-commit-enabled path\n\n1. ! Present an **explicit** default-branch path with confirmation (do not silently commit to master/main).\n2. ! On confirmation, commit framework-only changes on the default branch (or merge the framework branch) and push so the default branch carries the update.\n3. ! Record terminal state **`released`** only after the default branch ref includes the framework update.\n\n### 8d: Stop-after-commit is a failure mode\n\n! A local framework-only commit without push/PR/merge **and** without naming the next release step is a **failure mode** of this skill (#1604 historical class).\n\n- ! If the workflow must pause after a local commit, name the next step explicitly (push + open PR, or confirm direct-commit + push) and record `blocked:<reason>` or continue until `pr-open` / `released`.\n- ⊗ End the skill at \"local framework-only commit done\" without a terminal state line.\n- ⊗ Report `released` when only a local commit exists and the default branch does not yet carry the update.\n\n### 8e: Terminal state line\n\n! End the skill output with a single machine-readable line operators and agents can grep:\n\n```text\nupgrade-handoff: released\nupgrade-handoff: pr-open\nupgrade-handoff: blocked:<reason>\n```\n\nInclude the PR URL when state is `pr-open`, and the merge/default-branch SHA when state is `released`.\n\n### 8f: Framework-only path allowlist\n\n! When committing for handoff, include only framework deposit artifacts (managed `.deft/core/`, AGENTS managed section, hooks, VERSION/marker files, and other paths the deposit itself refreshed). Exclude product source, tests, and unrelated staged files. If isolation was used in 0b, restore the operator's product stash only **after** the framework commit is complete (or on a separate branch).\n\n## Anti-Patterns\n\n- ⊗ Auto-commit submodule changes without user approval\n- ⊗ Auto-commit or auto-push framework deposit changes without the Phase 8 policy path and consent rules\n- ⊗ Stop after a local framework-only commit without naming the next release step or recording a terminal state (#1604)\n- ⊗ Claim terminal state `released` when the update is only local or only on an open PR\n- ⊗ Auto-merge when `requireHumanMerge` is true or branch protection forbids bot merge (#1193)\n- ⊗ Treat git submodule update as the primary consumer upgrade path when npm + `directive update` / `deft update` is available\n- ⊗ Send operators to manual GitHub release-asset archaeology when `npm i -g @deftai/directive@latest` is the correct remediation\n- ⊗ Overwrite project-level `./xbrief/*.xbrief.json` files -- those are project data\n- ⊗ Skip the pre-flight dirty check -- a dirty submodule can cause merge conflicts or data loss\n- ⊗ Include a separate fetch of the xBRIEF schema from upstream deftai/xBRIEF -- that is a CI concern (see #128), not a user sync task\n- ⊗ Auto-move xBRIEFs to fix folder/status mismatches -- report only; never auto-fix\n- ⊗ Auto-update xBRIEFs based on origin freshness -- report only; user decides during refinement\n- ⊗ Mix product feature work into a framework-only upgrade commit or PR\n- ⊗ Force `npm i -g @deftai/directive@latest` or deposit mutation on routine session sync without staleness evidence and operator consent\n- ⊗ Run Phase 8 framework-only commit from a mixed product+framework worktree/index without isolation\n",
|
|
319
|
+
"body": "# Deft Directive Sync\n\nSession-start framework sync and upgrade handoff -- refresh the framework deposit via npm + `directive update` / `deft update`, validate xBRIEF lifecycle structure, detect stale origins (RFC D12), then finish SCM release handoff in a named terminal state (#1604).\n\n> **Canonical bootstrap / update path (#761 / #1604):** Install and upgrade via npm: `npm i -g @deftai/directive` (install) or `npm i -g @deftai/directive@latest` (upgrade); Node >= 20 is required. Then from the project root run `directive update` (or `deft update`) to refresh `.deft/core/`, optionally `deft migrate` for npm provenance, and `directive doctor` / `deft doctor` / `task doctor` to confirm deposit health. For machines without Node, the frozen legacy Go installer (`deft-install` / platform-specific `install-*` from GitHub Releases) is a no-Node bootstrap bridge (#1912) -- migrate to npm once Node is available. Legacy `run upgrade` / `task upgrade` are metadata-only acknowledgment (they do NOT replace the payload). **Git-submodule / `task framework:doctor` paths are back-compat only** -- Phases 1-2 below are the legacy update flow, de-emphasized in UPGRADING.md / README. Deposit success is not upgrade released; Phase 8 records one terminal state: `released` | `pr-open` | `blocked:<reason>`. See UPGRADING.md and #761 / #1912 / #1604.\n\nLegend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.\n\n## Platform Requirements\n\n! This skill requires **GitHub** as the SCM platform and the **GitHub CLI (`gh`)** to be installed and authenticated for origin freshness (Phase 5) and for the PR path of Phase 8 SCM release handoff. Origin freshness checks fetch issue data via REST-equivalent `gh` surfaces (prefer `gh api repos/<owner>/<repo>/issues/<N>` over GraphQL-heavy forms when under rate pressure; #954).\n\n## When to Use\n\n- User says \"good morning\", \"update deft\", \"update directive\", \"upgrade framework\", \"update xbrief\", or \"sync frameworks\"\n- Beginning of a new session where framework updates may be available\n- After a known upstream deft / `@deftai/directive` release\n- After a successful local deposit when the default branch still lacks the framework update\n\n## Missing CLI / PATH remediation\n\n! When `directive`, `deft`, or the global npm bin is missing from PATH (or `npm i -g @deftai/directive@latest` has not been run), surface actionable install remediation first:\n\n```bash\nnpm i -g @deftai/directive@latest\n```\n\n(or the pnpm equivalent: `pnpm add -g @deftai/directive@latest`). Then re-run `directive update` / `deft update` and `directive doctor`.\n\n⊗ Send the operator to manual GitHub release-asset archaeology or Go installer discovery as the happy path when Node is available -- npm is the primary remediation (#761 / #1604).\n\n## Session orientation — unmanaged header (#2065)\n\n! The region of AGENTS.md **above** the `<!-- deft:managed-section ... -->` marker is project-owned, preserved verbatim on refresh, and **not** freshness-checked by `deft doctor`.\n\n- ! Do NOT treat that unmanaged header as the work queue — consult `deft triage:queue`, `xbrief/` lifecycle, GitHub issues, and `PROJECT-DEFINITION.xbrief.json` instead (#1149, #2065 Option A).\n- ⊗ Do NOT add or revive `Status`, `Next:`, or `Known Issues` blocks in AGENTS.md — they duplicate authoritative sources and rot silently while the managed section stays current.\n\n## Framework Events Emitted Here\n\n! When this skill responds to a context-window shift or an explicit \"are you using Deft?\" probe (per AGENTS.md Deft Alignment Confirmation), emit the paired `session:interrupted` -> `session:resumed` framework events via `scripts/_events.py` so observability of agent-runtime state transitions is structural, not prose-only:\n\n- ! Before re-confirming alignment: `python -m scripts._events emit session:interrupted --session-id <id> --reason context-window-shift`\n- ! Immediately after the alignment confirmation line: `python -m scripts._events emit session:resumed --session-id <id> --interrupted-id <id-from-prior-emit>`\n- ⊗ Emit a `session:resumed` whose `interrupted_id` does not reference a prior `session:interrupted` -- such records are orphan and rejected by `scripts._events.validate_pairing` (#635 events behavioral wiring)\n\n## Pre-Cutover Detection Guard\n\n! Before proceeding with sync, detect whether the project uses the pre-v0.20 document model and report model state.\n\n### Detection Criteria\n\nA project is **pre-cutover** if ANY of the following are true. This prose mirrors the executable helper in `scripts/_precutover.py`; when in doubt, the helper is canonical.\n\n1. `SPECIFICATION.md` exists and is neither a deprecation redirect nor a current generated spec export. A current generated spec export contains `<!-- Purpose: rendered specification -->` and `<!-- Source of truth: xbrief/specification.xbrief.json -->`, and `xbrief/specification.xbrief.json` plus all five lifecycle folders exist.\n2. `PROJECT.md` exists and contains neither the legacy `<!-- deft:deprecated-redirect -->` sentinel NOR the current `Purpose: deprecation redirect` canonical-banner marker (real content, not a deprecation redirect)\n3. `xbrief/specification.xbrief.json` exists but the lifecycle folders (`xbrief/proposed/`, `xbrief/pending/`, `xbrief/active/`, `xbrief/completed/`, `xbrief/cancelled/`) do NOT exist\n\n### Action on Detection\n\n! If pre-cutover state is detected, display the actionable migration message, then **skip Phases 0-6** and proceed directly to Phase 7 with the Document Model line set to \"pre-v0.20 (legacy)\". Phase 8 still applies if a local migration/framework change must land on the default branch after the frozen migrator path:\n\n> \"This project uses the pre-v0.20 document model. Current npm releases no longer ship in-product `task migrate:vbrief` (#2068). Follow UPGRADING.md § Frozen pre-v0.20 document-model migration: pin framework v0.59.0, install Python 3.11+ and uv, run `task migrate:vbrief` once from that payload, then upgrade to current npm.\"\n\n! Include specific details about what was detected:\n\n- Missing lifecycle folders: \"Create lifecycle folders via the frozen v0.59.0 migrator (#2068), or manually add `xbrief/{proposed,pending,active,completed,cancelled}/` after migrating narratives\"\n- `SPECIFICATION.md` with real content: \"SPECIFICATION.md contains non-redirect content -- this file is deprecated; use scope xBRIEFs in `xbrief/` instead\"\n- `PROJECT.md` with real content: \"PROJECT.md contains non-redirect content -- this file is deprecated; use `PROJECT-DEFINITION.xbrief.json` instead\"\n- Missing `PROJECT-DEFINITION.xbrief.json`: \"Run `task project:render` to generate the project definition\"\n- Scope xBRIEF in wrong folder: \"Status is '{status}' but file is in {folder}/ -- run `task scope:activate <file>` to fix\"\n\n### Model State in Sync Output\n\n! Include a **Document Model** line in the Phase 7 summary:\n\n- Pre-cutover detected: \"**Document Model**: pre-v0.20 (legacy) -- follow UPGRADING.md § Frozen pre-v0.20 document-model migration (#2068)\"\n- Post-cutover (lifecycle folders present, no stale artifacts): \"**Document Model**: v0.20+ (xBRIEF-centric) -- OK\"\n- Post-cutover with tampered placeholders: \"**Document Model**: v0.20+ with warnings -- SPECIFICATION.md or PROJECT.md contains non-redirect content\"\n\n⊗ Skip model state detection during sync -- always report the document model state.\n⊗ Silently ignore pre-cutover artifacts -- the user must be informed with an actionable command to fix the state.\n\n## Phase 0 -- Primary upgrade (npm deposit) (#761 / #1604)\n\n! Treat npm + `directive update` / `deft update` as the **primary** consumer upgrade path when an upgrade is authorized. Do not lead with submodule update when Node is available.\n\n### 0a: When mutation is authorized\n\n! **Mutating** engine install / deposit refresh is authorized only when at least one of:\n\n1. The operator used an **explicit upgrade** trigger: `update deft`, `update directive`, `upgrade framework`, or equivalent (\"upgrade Directive\", \"run update\").\n2. Doctor / payload-staleness already reports the deposit is **behind** and the operator confirmed the upgrade (or autonomous upgrade was pre-approved).\n3. CLI is **missing** from PATH -- then Missing CLI remediation may install the global package so doctor/update can run.\n\n! For routine session orientation triggers (`good morning`, `sync frameworks`, plain `update xbrief` without upgrade language):\n\n1. ! Run **read-only** checks: CLI present?, `directive doctor` / `deft doctor` / `task doctor` when available, structure validation (Phases 3+).\n2. ! If doctor reports a stale deposit or available upgrade, **report** the recommended command and ask for consent before mutating.\n3. ⊗ Run `npm i -g @deftai/directive@latest` or `directive update` / `deft update` on a routine \"good morning\" without staleness evidence **and** operator consent (or pre-approved autonomous upgrade).\n\n### 0b: Consumer worktree isolation before deposit\n\n! Before any mutating deposit that will be handed off in Phase 8:\n\n1. ! Run `git status --porcelain` at the **project root** (not only the legacy submodule).\n2. ! If the worktree or index has non-framework product changes (or any unexpected staged paths), **stop** and either:\n - ask the operator to stash / commit product work first, or\n - record `blocked:dirty-worktree` and skip deposit mutation,\n - or, with explicit consent, isolate product changes (stash including index) so the deposit cannot mix with them.\n3. ! After deposit, stage **only** framework-managed paths for the upgrade commit (e.g. `.deft/core/`, managed AGENTS section, hooks, VERSION / marker files). Reconstruct a clean index if needed rather than `git add -A`.\n4. ⊗ Create a framework-only commit or PR from a mixed worktree/index that still carries product feature paths.\n\n### 0c: Engine + deposit (when authorized)\n\n1. ! Confirm the global CLI is available (`directive --version` or `deft --version`). If missing, run Missing CLI / PATH remediation above, then continue.\n2. ! Upgrade the global engine only when mutation is authorized (0a):\n\n```bash\nnpm i -g @deftai/directive@latest\n```\n\n3. ! From the **project root**, after worktree isolation (0b), refresh the deposit:\n\n```bash\ndirective update\n# or: deft update\n```\n\n4. ~ Optionally stamp npm provenance (idempotent): `directive migrate` / `deft migrate`.\n5. ! Verify deposit health:\n\n```bash\ndirective doctor\n# or: deft doctor / task doctor\n```\n\n6. ! Record whether the working tree now has **framework-only** changes under `.deft/core/`, managed AGENTS section, hooks, or related managed files that need SCM release.\n\n### 0d: Framework-only change-set discipline\n\n! Keep upgrade commits/PRs **framework-only** -- do not mix product feature work into the same commit or PR as the deposit refresh.\n\n⊗ Treat a successful deposit alone as `released` -- the default branch must carry the update (or a PR must be open) before the operator goal is complete (#1604).\n⊗ Force a global CLI upgrade or deposit mutation on routine session sync without consent or staleness evidence.\n\n## Phase 1 -- Pre-flight (legacy submodule path)\n\n! **Legacy / back-compat only.** Run Phases 1-2 only when the consumer still uses a `deft/` git submodule layout and cannot use the npm deposit path. Prefer Phase 0 for all npm-managed installs.\n\n! Check that the deft/ submodule working tree is clean before attempting any update.\n\n1. ! Run `git -C deft status --porcelain`\n2. ! If output is non-empty (dirty working tree): **stop** and ask user whether to stash (`git -C deft stash`) or abort the sync entirely. Do NOT proceed with a dirty submodule. Record terminal state `blocked:dirty-submodule` if the operator aborts.\n3. ! Record the current DEFT commit for later comparison:\n ```\n git -C deft log --oneline -1\n ```\n4. ! Present the current state to the user:\n - Current DEFT commit (hash + subject)\n - Clean/dirty status\n - Confirmation that pre-flight passed (or the blocker if dirty)\n\n## Phase 2 -- Update DEFT Submodule (legacy / back-compat)\n\n! **Legacy / back-compat only** -- not the primary consumer upgrade path (#1604). Submodule update does not replace Phase 0 for npm installs.\n\n1. ! Run the submodule update:\n ```\n git submodule update --remote --merge deft\n ```\n2. ! Show what changed by comparing before/after:\n ```\n git -C deft log --oneline <old-hash>..HEAD\n ```\n3. ~ If no new commits, report \"deft submodule already up to date\" and proceed to Phase 3.\n\n## Phase 3 -- Structure Validation\n\n! Validate the xBRIEF lifecycle folder structure and project files.\n\n### 3a: Lifecycle Folder Structure\n\n! Verify all required lifecycle folders exist:\n\n1. ! Check that the following directories exist under `./xbrief/`:\n - `proposed/`\n - `pending/`\n - `active/`\n - `completed/`\n - `cancelled/`\n2. ! Report any missing folders with a clear warning:\n - \"WARNING: xbrief/{folder}/ does not exist -- lifecycle structure is incomplete\"\n3. ~ If folders are missing, suggest `task migrate:preflight` and the frozen v0.59.0 migrator path (#2068), or creating them manually after migration\n\n### 3b: PROJECT-DEFINITION.xbrief.json Validation\n\n! Validate the project identity gestalt file:\n\n1. ! Check that `./xbrief/PROJECT-DEFINITION.xbrief.json` exists\n - If missing: \"WARNING: PROJECT-DEFINITION.xbrief.json not found -- run `task project:render` to create\"\n2. ! If the file exists, validate it is well-formed:\n - Valid JSON (`python3 -m json.tool` or equivalent)\n - Top-level `xBRIEFInfo` envelope with `version` field equal to `\"0.6\"`\n - `plan` object with `title`, `status`, and `items` fields present\n - `plan.narratives` values are plain strings (not objects or arrays)\n3. ! **Freshness check**: Compare `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated`) against recent scope completions:\n - Scan `xbrief/completed/` for xBRIEFs with `xBRIEFInfo.updated` timestamps newer than the PROJECT-DEFINITION timestamp\n - If stale: \"WARNING: PROJECT-DEFINITION.xbrief.json may be stale -- {N} scopes completed since last update. Run `task project:render` to refresh.\"\n\n### 3c: Validate Root-Level xBRIEF Files\n\n! Validate all `./xbrief/*.xbrief.json` files at the xbrief root:\n\n1. ! Check each file is valid JSON\n2. ! Verify structural conformance:\n - Top-level `xBRIEFInfo` envelope with `version` field present\n - `plan` object with `title`, `status`, and `items` fields present\n - `plan.status` values from valid enum: draft, proposed, approved, pending, running, completed, blocked, cancelled\n3. ~ Use `task xbrief:validate` if available for deeper validation\n4. ! Report any validation failures with file name and specific violation\n\n⊗ Overwrite or modify project-level `./xbrief/*.xbrief.json` files -- those are project data, not framework files. Report issues and let the user decide how to fix them.\n\n## Phase 4 -- Lifecycle Consistency Check\n\n! Verify that each scope xBRIEF's `plan.status` matches its folder location.\n\n1. ! Scan all scope xBRIEFs in lifecycle folders (`proposed/`, `pending/`, `active/`, `completed/`, `cancelled/`)\n2. ! For each xBRIEF, check `plan.status` against the expected statuses for its folder:\n - `proposed/`: status should be `draft` or `proposed`\n - `pending/`: status should be `approved` or `pending`\n - `active/`: status should be `running` or `blocked`\n - `completed/`: status should be `completed`\n - `cancelled/`: status should be `cancelled`\n3. ! Report any mismatches:\n - \"MISMATCH: {filename} in {folder}/ has status '{status}' -- expected one of [{expected_statuses}]\"\n4. ~ Per `vbrief/vbrief.md` convention, trust the status field and suggest correcting the folder location:\n - \"Suggested fix: move {filename} to {correct_folder}/ (status '{status}' is authoritative)\"\n\n⊗ Auto-move xBRIEFs to fix folder/status mismatches -- report only; user decides during refinement or ad-hoc\n\n## Phase 5 -- Origin Freshness (RFC D12)\n\n! For xBRIEFs with external origin references, detect externally-closed origins. `task reconcile:issues` reports linked / unlinked / closed / completed-status drift -- it does **not** have a stale-content (`updatedAt`) bucket. Implementation-intent fail-closed for a newer origin is `task xbrief:preflight` (#3363).\n\n### Step 1: Scan Origins\n\n1. ! Run `task reconcile:issues` for linked / unlinked / externally-closed / completed-status drift.\n2. ! For each xBRIEF in `proposed/` and `pending/` with a `github-issue` reference in `plan.references` or top-level `references`, an advisory scan MAY fetch the issue (`gh api repos/{owner}/{repo}/issues/{N}`) and compare `updatedAt` / `updated_at` against `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated` field). This is report-only; it is not the engine verb.\n\n### Step 2: Categorize and Report\n\n1. ! **Externally closed origins** -- issue state is `CLOSED` (from `task reconcile:issues`):\n - \"{N} xBRIEFs have origins that were closed externally\"\n - List each: \"{filename}: Issue #{N} is closed ({close_reason})\"\n2. ! **Advisory newer origin** -- issue `updatedAt` is newer than xBRIEF `updated` timestamp (manual scan or later `task xbrief:preflight`):\n - \"{N} xBRIEFs have origins updated since last sync\"\n - List each: \"{filename}: Issue #{N} updated {time_delta} ago\"\n3. ~ **Current origins** -- no changes detected (report count only)\n\n### Step 3: Recommendation\n\n- ! Report only -- never auto-update xBRIEFs based on origin changes\n- ~ If newer or externally-closed origins are found, suggest: \"Run a refinement session (`skills/deft-directive-refinement/SKILL.md`) to walk origin changes with user approval. Implementation will fail closed at `task xbrief:preflight` until the brief is refreshed or intentional divergence is recorded.\"\n\n⊗ Auto-update xBRIEFs based on origin freshness checks -- report only; user decides during refinement\n\n## Phase 6 -- Framework Sync\n\nAfter structure validation, sync framework-level assets.\n\n### 6a: Check AGENTS.md freshness\n\n~ Compare the project's `AGENTS.md` against the deft template (if a template exists in the updated deposit / `.deft/core/` or legacy `deft/` submodule):\n\n1. ~ Diff the structure (section headings, key rules) rather than expecting byte-identical content\n2. ~ Report any new sections or rules added upstream that are missing locally\n3. ~ Do NOT auto-overwrite -- present differences and let the user decide\n4. ~ If the unmanaged header still carries `Status`, `Next:`, or `Known Issues`, recommend replacing them with the **Session orientation** pointer at `xbrief/` + triage + issues (#2065 Option A) -- do NOT treat that header prose as the work queue\n\n### 6b: Check codebase MAP freshness\n\n~ If `./.planning/codebase/MAP.md` exists, or `PROJECT-DEFINITION.xbrief.json` declares a `projectionManifest[]` entry with `kind: \"codebase-map\"`, run `task verify:codebase-map-fresh` when the command resolves. If it reports drift, recommend `task codebase:map` and note that the generated MAP is advisory unless the operator asked to refresh projections.\n\n- ! Keep `plan.architecture.codeStructure` and configured provider artifacts authoritative; the MAP is a generated projection.\n- ⊗ Auto-edit canonical xBRIEF metadata to make the MAP fresh during sync -- report drift and let the operator choose a follow-up.\n\n### 6c: List new skills\n\n! Compare the `skills/` directory (or deposited `.deft/core/` skills) before and after the update:\n\n1. ! List any new skill directories added in the update\n2. ~ For each new skill, read its frontmatter `description` field and present a one-liner\n3. ~ Mention if any existing skills were updated (changed files)\n\n## Phase 6d -- Legacy Artifact Review (post-migration, one-time)\n\n! If `xbrief/migration/LEGACY-REPORT.md` exists (and has NOT been renamed to `LEGACY-REPORT.reviewed.md`), walk the operator through each captured legacy section and record their disposition inline in the same file. This phase surfaces the non-canonical content that `task migrate:xbrief` preserved via the `LegacyArtifacts` narrative mechanism (#505).\n\n### Detection\n\n1. ! Check for `xbrief/migration/LEGACY-REPORT.md` in the project root.\n2. ! If the file is absent or `LEGACY-REPORT.reviewed.md` exists (reviewed form), skip Phase 6d silently and proceed to Phase 7.\n3. ! If `LEGACY-REPORT.md` is present and has NOT been renamed, begin the review loop below.\n\n### Review loop\n\n1. ! Present the report summary (sources + per-bucket section counts) to the user.\n2. ! For each captured section listed under `## specification.xbrief.json -> LegacyArtifacts`, `## PROJECT-DEFINITION.xbrief.json -> LegacyArtifacts`, and `## PRD.md content (flagged: hand-edited)`:\n - Restate the section title, source file + line range, and size.\n - Offer exactly three disposition options: **Keep** (leave inside `LegacyArtifacts`), **Fold into {suggested narrative}** (move into a canonical narrative key), or **Drop** (remove from `LegacyArtifacts`, with explicit user confirmation).\n - ~ If a sidecar pointer is present (`xbrief/legacy/{stem}-{slug}.md`), open the sidecar for the user before offering options so the full content is visible.\n3. ! Record each disposition inline in the same `LEGACY-REPORT.md` file under a new `## Reviewed` section with one entry per legacy item: original section, user's decision, target location (if folded) or confirmation note (if kept/dropped), and the reviewer's timestamp.\n4. ! For a **Fold** decision, the agent updates the target xBRIEF's narrative key AND deletes only the corresponding section from the `LegacyArtifacts` narrative -- never the file.\n5. ! For a **Drop** decision, the agent removes only the corresponding section from the `LegacyArtifacts` narrative.\n6. ! Once all sections carry a recorded disposition, rename the file to `LEGACY-REPORT.reviewed.md`. The file is kept so the audit trail remains -- ⊗ MUST NOT delete either form.\n\n### Anti-patterns\n\n- ⊗ Delete `LEGACY-REPORT.md` or `LEGACY-REPORT.reviewed.md` -- these are the migration audit trail and MUST persist.\n- ⊗ Auto-dispose of legacy artifacts without user input -- every section requires an explicit decision.\n- ⊗ Rename to `.reviewed.md` before every captured section has a recorded disposition in the `## Reviewed` section.\n- ⊗ Drop a legacy section without explicit user confirmation (even if the section looks obviously stale).\n- ⊗ Silently delete sidecar files under `xbrief/legacy/` -- they are referenced from `LegacyArtifacts` and are part of the audit trail.\n\n## Phase 6e -- Doc-sprawl awareness (advisory, #647)\n\nDoc sprawl is a project-health concern, not just a human-experience one: a lean, well-written AGENTS.md sitting on top of a large reachable doc corpus does **not** stop agents from discovering and loading those docs (Augment Code study, `content/docs/good-agents-md.md`). It degrades agent quality silently until measured. This step **surfaces** the risk; it is ADVISORY and MUST NOT block or fail the sync.\n\n1. ~ Scan the project's reachable documentation footprint: the top-level `docs/` / `_docs/` directories, nested `README.md` files, and any `architecture` / `design` docs.\n2. ~ Flag, as a non-blocking nudge, when any of these appear:\n - A large `docs/` (or `_docs/`) directory that is **not referenced** from the AGENTS.md reference chain (orphan docs are discovered <10% of the time yet still cost context when found -- the reference-chain contract, #644).\n - Deeply nested READMEs that duplicate guidance the reference chain already carries.\n - Architecture / design docs that restate what the codebase already shows (a measured overexploration trigger).\n3. ~ Point the operator at `content/docs/agent-docs.md` (the empirically-grounded structure pattern) and the `REFERENCES.md` reference-chain contract for remediation. For directive's own always-loaded file, the `verify:agents-md-budget` ratchet (#645) and the consumer advisory (`agentsMdAdvisory`, #2155) are the size guards.\n4. ⊗ Do NOT convert this into a hard gate or auto-delete any doc -- the value is the nudge at the right moment; thresholds are a judgment call the operator owns.\n\n## Phase 7 -- Summary\n\n! Present a consolidated summary to the user covering:\n\n1. **Upgrade path used**: npm deposit (Phase 0) / legacy submodule (Phases 1-2) / already up to date\n2. **DEFT / deposit version change**: old version or commit -> new (or \"already up to date\")\n3. **Structure validation**: lifecycle folders status (all present / missing folders listed)\n4. **PROJECT-DEFINITION status**: valid / missing / stale (with freshness details)\n5. **xBRIEF validation results**: pass/fail per file, with details on any failures\n6. **Lifecycle consistency**: all consistent / N mismatches found (with details)\n7. **Origin freshness**: N stale / N externally-closed / N current (with details)\n8. **Document Model**: pre-v0.20 (legacy) / v0.20+ (xBRIEF-centric) OK / v0.20+ with warnings (see Pre-Cutover Detection Guard)\n9. **AGENTS.md status**: current / has upstream changes / needs review\n10. **Codebase MAP status**: current / stale / absent / not configured (advisory)\n11. **New skills**: list any newly added skills with descriptions\n12. **Pending SCM release**: whether framework-only changes still need commit/push/PR/merge (Phase 8)\n\n! After a successful deposit (or submodule bump), **do not stop at the local change set**. Proceed to Phase 8 SCM release handoff. If there is nothing to release (already on default branch / no local framework delta), record terminal state `released` when the default branch already carries the current framework update; otherwise name the next release step.\n\n? For the legacy submodule path only, if a bump is ready and the operator has not yet approved a commit, ask: \"Shall I commit the submodule update and continue SCM release handoff?\" -- do NOT auto-commit without approval. Prefer message:\n\n```\nchore(deft): update deft submodule to <short-hash>\n```\n\nFor npm deposit changes, prefer a framework-only commit message such as:\n\n```\nchore(deft): refresh framework deposit to <version>\n```\n\n## Phase 8 -- SCM release handoff (#1604)\n\n! After a successful framework deposit (Phase 0) or legacy submodule bump (Phases 1-2), carry the update through consumer SCM release. Installer/update success is not upgrade released.\n\n! Record **exactly one** terminal state when this skill exits after a deposit-related run:\n\n| Terminal state | Meaning |\n| --- | --- |\n| `released` | Default branch carries the framework update (merged or committed directly under policy). |\n| `pr-open` | Framework-only branch pushed and PR opened; awaiting review/merge per policy. |\n| `blocked:<reason>` | Explicit blocker (examples: `blocked:dirty-worktree`, `blocked:auth`, `blocked:branch-protection`, `blocked:human-merge-gate`, `blocked:ci`, `blocked:operator-declined`). |\n\n### 8a: Policy detection\n\n1. ! Read consumer branch policy: `plan.policy.allowDirectCommitsToMaster`, `plan.policy.requireHumanMerge`, and any known branch-protection / default-branch rules (`deft policy:show` when available).\n2. ! Classify the path:\n - **PR path (default when protected or human-merge):** branch protection enabled, or `requireHumanMerge` is true, or direct commits to default branch are disallowed.\n - **Direct-commit path:** `allowDirectCommitsToMaster` (or equivalent) is true **and** human-merge is not required **and** branch protection does not forbid the commit.\n\n### 8b: PR-oriented path (branch-protected / human-merge)\n\n1. ! With operator consent (or autonomous consent when the operator already approved upgrade handoff), create a **framework-only** branch (e.g. `chore/deft-update-<version>`), commit framework deposit files only, push, and open a PR targeting the default branch.\n2. ! Stop at terminal state **`pr-open`** once the PR URL is available -- unless policy explicitly allows bot merge **and** the operator directed merge.\n3. ⊗ Auto-merge past `requireHumanMerge` / the human merge gate (#1193). Agents may open PRs; they do not merge when policy forbids it.\n4. ⊗ Claim `released` when the PR is only open or only locally committed.\n\n### 8c: Direct-commit-enabled path\n\n1. ! Present an **explicit** default-branch path with confirmation (do not silently commit to master/main).\n2. ! On confirmation, commit framework-only changes on the default branch (or merge the framework branch) and push so the default branch carries the update.\n3. ! Record terminal state **`released`** only after the default branch ref includes the framework update.\n\n### 8d: Stop-after-commit is a failure mode\n\n! A local framework-only commit without push/PR/merge **and** without naming the next release step is a **failure mode** of this skill (#1604 historical class).\n\n- ! If the workflow must pause after a local commit, name the next step explicitly (push + open PR, or confirm direct-commit + push) and record `blocked:<reason>` or continue until `pr-open` / `released`.\n- ⊗ End the skill at \"local framework-only commit done\" without a terminal state line.\n- ⊗ Report `released` when only a local commit exists and the default branch does not yet carry the update.\n\n### 8e: Terminal state line\n\n! End the skill output with a single machine-readable line operators and agents can grep:\n\n```text\nupgrade-handoff: released\nupgrade-handoff: pr-open\nupgrade-handoff: blocked:<reason>\n```\n\nInclude the PR URL when state is `pr-open`, and the merge/default-branch SHA when state is `released`.\n\n### 8f: Framework-only path allowlist\n\n! When committing for handoff, include only framework deposit artifacts (managed `.deft/core/`, AGENTS managed section, hooks, VERSION/marker files, and other paths the deposit itself refreshed). Exclude product source, tests, and unrelated staged files. If isolation was used in 0b, restore the operator's product stash only **after** the framework commit is complete (or on a separate branch).\n\n## Anti-Patterns\n\n- ⊗ Auto-commit submodule changes without user approval\n- ⊗ Auto-commit or auto-push framework deposit changes without the Phase 8 policy path and consent rules\n- ⊗ Stop after a local framework-only commit without naming the next release step or recording a terminal state (#1604)\n- ⊗ Claim terminal state `released` when the update is only local or only on an open PR\n- ⊗ Auto-merge when `requireHumanMerge` is true or branch protection forbids bot merge (#1193)\n- ⊗ Treat git submodule update as the primary consumer upgrade path when npm + `directive update` / `deft update` is available\n- ⊗ Send operators to manual GitHub release-asset archaeology when `npm i -g @deftai/directive@latest` is the correct remediation\n- ⊗ Overwrite project-level `./xbrief/*.xbrief.json` files -- those are project data\n- ⊗ Skip the pre-flight dirty check -- a dirty submodule can cause merge conflicts or data loss\n- ⊗ Include a separate fetch of the xBRIEF schema from upstream deftai/xBRIEF -- that is a CI concern (see #128), not a user sync task\n- ⊗ Auto-move xBRIEFs to fix folder/status mismatches -- report only; never auto-fix\n- ⊗ Auto-update xBRIEFs based on origin freshness -- report only; user decides during refinement\n- ⊗ Mix product feature work into a framework-only upgrade commit or PR\n- ⊗ Force `npm i -g @deftai/directive@latest` or deposit mutation on routine session sync without staleness evidence and operator consent\n- ⊗ Run Phase 8 framework-only commit from a mixed product+framework worktree/index without isolation\n",
|
|
320
320
|
"frontmatter_extra": "triggers:\n - good morning\n - update deft\n - update directive\n - upgrade framework\n - update xbrief\n - sync frameworks"
|
|
321
321
|
},
|
|
322
322
|
{
|
|
@@ -229,16 +229,18 @@ The task emits xBRIEFs conforming to the canonical v0.6 schema (`xbrief/schemas/
|
|
|
229
229
|
task reconcile:issues
|
|
230
230
|
```
|
|
231
231
|
|
|
232
|
-
The task scans every xBRIEF with a GitHub-backed reference (whether the reference uses the legacy `github-issue` bare type or the canonical `x-xbrief/github-issue` shape), fetches each linked issue,
|
|
232
|
+
The task scans every xBRIEF with a GitHub-backed reference (whether the reference uses the legacy `github-issue` bare type or the canonical `x-xbrief/github-issue` shape), fetches each linked issue, and reports items in these buckets:
|
|
233
233
|
|
|
234
|
-
- **Linked & current** — origin has
|
|
235
|
-
- **Stale** — origin `updatedAt` is newer than the xBRIEF (propose an update)
|
|
234
|
+
- **Linked & current** — an open origin issue has a matching xBRIEF (no action)
|
|
236
235
|
- **Externally closed** — origin issue is `CLOSED` (propose cancellation or reconcile if intentional divergence)
|
|
237
|
-
- **Unlinked** —
|
|
236
|
+
- **Unlinked** — open GitHub issue with no xBRIEF (flag for review)
|
|
237
|
+
- **Completed-status drift** — a `completed/` brief whose `plan.status` is not terminal
|
|
238
|
+
|
|
239
|
+
`task reconcile:issues` does **not** compare origin `updated_at` to the brief `updated` timestamp. Origin **content** staleness is fail-closed at implementation intent: `task xbrief:preflight` exits 1 when the live issue is newer than `xBRIEFInfo.updated` (#3363).
|
|
238
240
|
|
|
239
241
|
### Step 2: Walk Flagged Items with the User
|
|
240
242
|
|
|
241
|
-
1. !
|
|
243
|
+
1. ! When `task xbrief:preflight` (or a manual origin re-read) shows the live issue is newer than the brief, show the user the current xBRIEF against the origin body + comments (#2143). Propose a refresh **or** record intentional divergence and bump `xBRIEFInfo.updated`; ! wait for explicit user approval before writing anything. ⊗ Auto-write origin text onto the brief (#309 D12).
|
|
242
244
|
2. ! For each **externally closed** item, ask the user whether to `task scope:cancel <file>` it or preserve intentional divergence.
|
|
243
245
|
3. ! For each **unlinked** item, ask whether to attach an origin reference or leave the xBRIEF as-is.
|
|
244
246
|
|
|
@@ -263,29 +263,27 @@ directive doctor
|
|
|
263
263
|
|
|
264
264
|
## Phase 5 -- Origin Freshness (RFC D12)
|
|
265
265
|
|
|
266
|
-
! For xBRIEFs with external origin references, detect
|
|
266
|
+
! For xBRIEFs with external origin references, detect externally-closed origins. `task reconcile:issues` reports linked / unlinked / closed / completed-status drift -- it does **not** have a stale-content (`updatedAt`) bucket. Implementation-intent fail-closed for a newer origin is `task xbrief:preflight` (#3363).
|
|
267
267
|
|
|
268
268
|
### Step 1: Scan Origins
|
|
269
269
|
|
|
270
|
-
1. !
|
|
271
|
-
|
|
272
|
-
- Fetch the issue: `gh issue view {N} --repo {owner/repo} --json updatedAt,state`
|
|
273
|
-
2. ! Compare the issue's `updatedAt` against the xBRIEF's `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated` field)
|
|
270
|
+
1. ! Run `task reconcile:issues` for linked / unlinked / externally-closed / completed-status drift.
|
|
271
|
+
2. ! For each xBRIEF in `proposed/` and `pending/` with a `github-issue` reference in `plan.references` or top-level `references`, an advisory scan MAY fetch the issue (`gh api repos/{owner}/{repo}/issues/{N}`) and compare `updatedAt` / `updated_at` against `xBRIEFInfo.updated` (or `xBRIEFInfo.created` if no `updated` field). This is report-only; it is not the engine verb.
|
|
274
272
|
|
|
275
273
|
### Step 2: Categorize and Report
|
|
276
274
|
|
|
277
|
-
1. ! **
|
|
278
|
-
- "{N} xBRIEFs have origins updated since last sync"
|
|
279
|
-
- List each: "{filename}: Issue #{N} updated {time_delta} ago"
|
|
280
|
-
2. ! **Externally closed origins** -- issue state is `CLOSED`:
|
|
275
|
+
1. ! **Externally closed origins** -- issue state is `CLOSED` (from `task reconcile:issues`):
|
|
281
276
|
- "{N} xBRIEFs have origins that were closed externally"
|
|
282
277
|
- List each: "{filename}: Issue #{N} is closed ({close_reason})"
|
|
278
|
+
2. ! **Advisory newer origin** -- issue `updatedAt` is newer than xBRIEF `updated` timestamp (manual scan or later `task xbrief:preflight`):
|
|
279
|
+
- "{N} xBRIEFs have origins updated since last sync"
|
|
280
|
+
- List each: "{filename}: Issue #{N} updated {time_delta} ago"
|
|
283
281
|
3. ~ **Current origins** -- no changes detected (report count only)
|
|
284
282
|
|
|
285
283
|
### Step 3: Recommendation
|
|
286
284
|
|
|
287
285
|
- ! Report only -- never auto-update xBRIEFs based on origin changes
|
|
288
|
-
- ~ If
|
|
286
|
+
- ~ If newer or externally-closed origins are found, suggest: "Run a refinement session (`skills/deft-directive-refinement/SKILL.md`) to walk origin changes with user approval. Implementation will fail closed at `task xbrief:preflight` until the brief is refreshed or intentional divergence is recorded."
|
|
289
287
|
|
|
290
288
|
⊗ Auto-update xBRIEFs based on origin freshness checks -- report only; user decides during refinement
|
|
291
289
|
|
package/tasks/verify.yml
CHANGED
|
@@ -47,6 +47,16 @@ tasks:
|
|
|
47
47
|
vars:
|
|
48
48
|
ENGINE_CMD: 'verify-biome-config --project-root "{{.DEFT_ROOT}}"'
|
|
49
49
|
|
|
50
|
+
telemetry-coverage:
|
|
51
|
+
desc: "Dead-surface detector for run-summary event kinds (#3362). Every RUN_SUMMARY_EVENT_KINDS member needs a production caller and a field-shaped fixture. Default is warn-only; pass --enforce to fail closed. -- task verify:telemetry-coverage [-- --enforce]"
|
|
52
|
+
deps:
|
|
53
|
+
- task: :engine:_ts-build
|
|
54
|
+
# Framework-source-only gate: scans THIS repo's packages/core/src emitters.
|
|
55
|
+
cmds:
|
|
56
|
+
- task: :engine:invoke
|
|
57
|
+
vars:
|
|
58
|
+
ENGINE_CMD: 'verify-telemetry-coverage --project-root "{{.DEFT_ROOT}}" {{.CLI_ARGS}}'
|
|
59
|
+
|
|
50
60
|
contained-writes:
|
|
51
61
|
desc: "Inventory raw product write sinks outside the contained-write allowlist (#2951 / #2980). Default CLI remains fail-open; task check wires --enforce fail-closed. -- task verify:contained-writes [-- --enforce]"
|
|
52
62
|
deps:
|
|
@@ -535,6 +535,16 @@ The parent monitor watches the heartbeat file directly (three-state exit 0 ok /
|
|
|
535
535
|
Principle: `main.md` `## Rule Authority [AXIOM]`.
|
|
536
536
|
Principle: `main.md` `## Thin Fail-Closed Design (#3265)`.
|
|
537
537
|
|
|
538
|
+
## 10.56 Writing bar — clarity, simplicity, brevity (#3368)
|
|
539
|
+
|
|
540
|
+
! Clarity, simplicity, brevity in documents and user communications, including sub-agent status and handbacks. Cut ceremony, not required fields. Depth: `.deft/core/docs/writing-ste100.md` (#2927 / #3368). ⊗ Full STE; ⊗ historical rewrite; ⊗ red CI style gate; ⊗ prefacing the rule.
|
|
541
|
+
|
|
542
|
+
## 10.57 Telemetry deliverable fixture (#3362)
|
|
543
|
+
|
|
544
|
+
! A telemetry deliverable is not done until a field-shaped fixture reads its events from the shared fake trial (`task verify:telemetry-coverage`). Silence is the failure mode this gate exists for.
|
|
545
|
+
|
|
546
|
+
⊗ Ship a new `RUN_SUMMARY_EVENT_KINDS` member or exported emitter method without a production caller and a fixture that asserts the kind in `DEFT_RUN_SUMMARY_PATH` JSONL.
|
|
547
|
+
|
|
538
548
|
## 10.6 Dual stop for multi-iteration worker loops (#2442)
|
|
539
549
|
|
|
540
550
|
Multi-iteration implement, pre-PR, repair, and monitor loops require **two** stops: **success** (goal / AC / checker met) and **failure or budget** (max iterations, no-progress, or time/token budget). Single-turn tasks are exempt. Principle and defaults: `main.md` `## Dual Stop Rule (#2442)`; build skill dual-stop table; swarm Phase 4 / core-ops.
|
|
@@ -70,6 +70,8 @@ Legacy `vbrief/` read-accepted; `deft migrate:xbrief` for `xbrief/` (v0.6→v0.8
|
|
|
70
70
|
! Prefer `task deft:*` over AGENTS.md prose. See main.md.
|
|
71
71
|
## Thin Fail-Closed Design (#3265)
|
|
72
72
|
! One fail-closed `task deft:*` check + one remediation. See main.md.
|
|
73
|
+
## Writing bar (#3368)
|
|
74
|
+
! Clarity, simplicity, brevity in documents and user communications, including sub-agent status and handbacks. Cut ceremony, not required fields. STE how: `.deft/core/docs/writing-ste100.md` (#2927). ⊗ Full STE; ⊗ historical rewrite; ⊗ red CI style gate; ⊗ prefacing the rule.
|
|
73
75
|
|
|
74
76
|
## Continuous Improvement Learning (#607 / #3164)
|
|
75
77
|
|