@tacuchi/agent-workflow-cli 20.21.0 → 20.23.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.
Files changed (124) hide show
  1. package/README.md +17 -6
  2. package/dist/adapters/git-cli.js +42 -0
  3. package/dist/adapters/git-cli.js.map +1 -1
  4. package/dist/application/artifacts-service.js +5 -5
  5. package/dist/application/artifacts-service.js.map +1 -1
  6. package/dist/application/checkpoint-service.js +60 -55
  7. package/dist/application/checkpoint-service.js.map +1 -1
  8. package/dist/application/checkpoint-write-service.js +61 -66
  9. package/dist/application/checkpoint-write-service.js.map +1 -1
  10. package/dist/application/decisiones-service.js +5 -5
  11. package/dist/application/decisiones-service.js.map +1 -1
  12. package/dist/application/export-service.js +250 -0
  13. package/dist/application/export-service.js.map +1 -0
  14. package/dist/application/fix-git-service.js +244 -0
  15. package/dist/application/fix-git-service.js.map +1 -0
  16. package/dist/application/history-update-service.js +35 -24
  17. package/dist/application/history-update-service.js.map +1 -1
  18. package/dist/application/lifecycle-target.js +39 -0
  19. package/dist/application/lifecycle-target.js.map +1 -0
  20. package/dist/application/markdown.js +61 -16
  21. package/dist/application/markdown.js.map +1 -1
  22. package/dist/application/parsers/phases.js +38 -45
  23. package/dist/application/parsers/phases.js.map +1 -1
  24. package/dist/application/parsers/plan-status.js +75 -0
  25. package/dist/application/parsers/plan-status.js.map +1 -0
  26. package/dist/application/parsers/spec-relation.js +80 -0
  27. package/dist/application/parsers/spec-relation.js.map +1 -0
  28. package/dist/application/paths-service.js +8 -0
  29. package/dist/application/paths-service.js.map +1 -1
  30. package/dist/application/persist-service.js +285 -0
  31. package/dist/application/persist-service.js.map +1 -0
  32. package/dist/application/release-data/artifacts.js +17 -21
  33. package/dist/application/release-data/artifacts.js.map +1 -1
  34. package/dist/application/resume-service.js +184 -0
  35. package/dist/application/resume-service.js.map +1 -0
  36. package/dist/application/semantic-operation/protocol.js +247 -0
  37. package/dist/application/semantic-operation/protocol.js.map +1 -0
  38. package/dist/application/semantic-operation/publish.js +80 -0
  39. package/dist/application/semantic-operation/publish.js.map +1 -0
  40. package/dist/application/session-binding-service.js +125 -0
  41. package/dist/application/session-binding-service.js.map +1 -0
  42. package/dist/application/session-close-service.js +60 -39
  43. package/dist/application/session-close-service.js.map +1 -1
  44. package/dist/application/session-create-service.js +45 -19
  45. package/dist/application/session-create-service.js.map +1 -1
  46. package/dist/application/session-resolver.js +180 -44
  47. package/dist/application/session-resolver.js.map +1 -1
  48. package/dist/application/session-resume-service.js +39 -9
  49. package/dist/application/session-resume-service.js.map +1 -1
  50. package/dist/application/sessions-service.js +0 -2
  51. package/dist/application/sessions-service.js.map +1 -1
  52. package/dist/application/status-service.js +24 -352
  53. package/dist/application/status-service.js.map +1 -1
  54. package/dist/application/tasks-service.js +5 -5
  55. package/dist/application/tasks-service.js.map +1 -1
  56. package/dist/application/workline-index-service.js +510 -0
  57. package/dist/application/workline-index-service.js.map +1 -0
  58. package/dist/cli/commands/checkpoint-read.js +10 -6
  59. package/dist/cli/commands/checkpoint-read.js.map +1 -1
  60. package/dist/cli/commands/checkpoint-write.js +38 -11
  61. package/dist/cli/commands/checkpoint-write.js.map +1 -1
  62. package/dist/cli/commands/export.js +117 -0
  63. package/dist/cli/commands/export.js.map +1 -0
  64. package/dist/cli/commands/fix-git.js +109 -0
  65. package/dist/cli/commands/fix-git.js.map +1 -0
  66. package/dist/cli/commands/generate-launch.js +35 -3
  67. package/dist/cli/commands/generate-launch.js.map +1 -1
  68. package/dist/cli/commands/history-update.js +1 -1
  69. package/dist/cli/commands/history-update.js.map +1 -1
  70. package/dist/cli/commands/index.js +11 -0
  71. package/dist/cli/commands/index.js.map +1 -1
  72. package/dist/cli/commands/persist.js +67 -0
  73. package/dist/cli/commands/persist.js.map +1 -0
  74. package/dist/cli/commands/resume-summary.js +14 -3
  75. package/dist/cli/commands/resume-summary.js.map +1 -1
  76. package/dist/cli/commands/resume.js +73 -0
  77. package/dist/cli/commands/resume.js.map +1 -0
  78. package/dist/cli/commands/session-artifacts.js +12 -11
  79. package/dist/cli/commands/session-artifacts.js.map +1 -1
  80. package/dist/cli/commands/session-close.js +8 -7
  81. package/dist/cli/commands/session-close.js.map +1 -1
  82. package/dist/cli/commands/session-create.js +5 -1
  83. package/dist/cli/commands/session-create.js.map +1 -1
  84. package/dist/cli/commands/session-resume.js +16 -10
  85. package/dist/cli/commands/session-resume.js.map +1 -1
  86. package/dist/cli/commands/status.js +66 -2
  87. package/dist/cli/commands/status.js.map +1 -1
  88. package/dist/cli/commands/workspace-init.js +21 -2
  89. package/dist/cli/commands/workspace-init.js.map +1 -1
  90. package/dist/cli/context-id.js +133 -0
  91. package/dist/cli/context-id.js.map +1 -0
  92. package/dist/cli/help-groups.js +16 -1
  93. package/dist/cli/help-groups.js.map +1 -1
  94. package/dist/cli/main.js +44 -16
  95. package/dist/cli/main.js.map +1 -1
  96. package/dist/cli/output-mode.js +41 -0
  97. package/dist/cli/output-mode.js.map +1 -0
  98. package/dist/cli/parser.js +6 -0
  99. package/dist/cli/parser.js.map +1 -1
  100. package/dist/cli/registry.js.map +1 -1
  101. package/dist/cli/render.js +53 -0
  102. package/dist/cli/render.js.map +1 -1
  103. package/package.json +1 -1
  104. package/skills/w/SKILL.md +3 -1
  105. package/skills/w/commands/export-diagrams.md +19 -10
  106. package/skills/w/commands/export-manuals.md +20 -10
  107. package/skills/w/commands/export-reports.md +20 -11
  108. package/skills/w/commands/export-scripts.md +20 -10
  109. package/skills/w/commands/fix-git.md +31 -12
  110. package/skills/w/commands/generate-launch.md +1 -1
  111. package/skills/w/commands/persist.md +33 -68
  112. package/skills/w/commands/plan-new.md +1 -1
  113. package/skills/w/commands/resume.md +25 -41
  114. package/skills/w/commands/spec-refine.md +12 -0
  115. package/skills/w/commands/status.md +12 -40
  116. package/skills/w/commands/workspace-init.md +3 -3
  117. package/skills/w/hooks/README.md +21 -2
  118. package/skills/w/hooks/hooks.template.json +2 -2
  119. package/skills/w/loops/README.md +5 -3
  120. package/skills/w/loops/plan-exec-loop/LOOP.md +10 -5
  121. package/skills/w/loops/plan-new-loop/LOOP.md +17 -8
  122. package/skills/w/loops/plan-refine-loop/LOOP.md +3 -1
  123. package/skills/w/loops/spec-refine-loop/LOOP.md +20 -7
  124. package/skills/w/roles/git/ROLE.md +7 -8
@@ -71,7 +71,9 @@ question that changed nothing, is NOT transcribed.
71
71
 
72
72
  > **No gating contract** (unlike spec↔plan): the presence of `## Refinement decisions` in the plan is **audit trace only** — `plan-exec` neither requires nor checks it (it runs any plan). It serves to (a) distinguish a re-refined plan from a freshly generated one on resume, and (b) record what changed and why. *(Legacy plans may also carry `## Q&A traceability`; new runs never write it.)*
73
73
 
74
- > **Execution updates progress; refinement changes structure.** `plan-exec` updates the plan's operational state in place — task checkboxes, the phase `> Estado:` line with its `> Bloqueo:` line while blocked, declared deferrals and the final plan status line. It does **not** redesign contracts, phase shape or order, participating components, evidence or simulation boundaries: those structural changes are this loop's, and a change of functional behavior belongs to `spec-refine`.
74
+ > **Execution updates progress; refinement changes structure.** `plan-exec` updates the plan's operational state in place — task checkboxes, the phase `> Estado:` line with its `> Bloqueo:` line while blocked, declared deferrals and the plan's own status mark. It does **not** redesign contracts, phase shape or order, participating components, evidence or simulation boundaries: those structural changes are this loop's, and a change of functional behavior belongs to `spec-refine`.
75
+
76
+ > **Normalize on write, never invent.** A save through this loop leaves the document on the current contract. The plan-level `> Estado:` line sits under the title — `open`, unless execution already closed it, and then with the date and session on their own `> Cierre:` line. Each `### Fn` carries its required blocks, and **no conditional block is written empty**: a phase with no temporary behavior gets no `Límite de simulación`, one with nothing excluded gets no `Diferido`. Normalizing is a rewrite of form — it never changes a phase's state, never ticks a box, and never closes a plan.
75
77
 
76
78
  ## Delta 2 — Gap taxonomy (of "plan")
77
79
 
@@ -46,7 +46,9 @@ Closing *every* gap turns the spec into a premature plan. Close what changes **w
46
46
  **Adopt, do not repeat.** `spec-new`'s **facts** are reused; its **assumptions** are re-validated **only when one blocks a gap**; its `Open questions` are re-classified by destination; its one-vs-many hypothesis is re-judged at the *Change-shape gate*. The shallow sweep is never re-run wholesale. Keep the labels distinct — a spec that blurs them cannot be gated: **fact** (backed by repo, data or docs) · **inference** (unproven) · **user decision** · **deferred decision** (owner declared) · **open question** (can still move the contract).
47
47
 
48
48
  ## Writes
49
- Updates `docs/specs/NNN-spec-<slug>.md` **in place** (when the user picks `Guardar especificación refinada`): completes sections, **adds** `## Decisions`, closes `Open questions` as they get resolved, and stamps the frontmatter `status: ready-for-plan`. Since it overwrites an existing doc, it asks the user's **confirmation**. An accepted split — or an accepted replacement — also **creates** new spec files (§ *Change-shape gate*).
49
+ Updates `docs/specs/NNN-spec-<slug>.md` **in place** (when the user picks `Guardar especificación refinada`): completes sections, **adds** `## Decisions`, closes `Open questions` as they get resolved, and stamps the frontmatter `status: ready-for-plan`. Since it overwrites an existing doc, it asks the user's **confirmation**.
50
+
51
+ > **Not every shape decision creates a file** (§ *Change-shape gate*). An accepted **split** writes the reduced original **and** the extracted sibling specs; a replacement by **`Crear una nueva spec`** writes one new file and leaves this one untouched; **`Reformular esta spec`** creates nothing — it edits this same file, same number, same path. Every write, new or overwriting, is confirmed first.
50
52
 
51
53
  > **Boundary invariant:** this loop writes **only** into `docs/specs`. It never graduates/exports other artifacts to `docs/` — that is separate `export-*` work (chassis § *docs/ boundary*).
52
54
 
@@ -82,6 +84,8 @@ When the project already exists, establish the current behavior the change rests
82
84
 
83
85
  Runs once the baseline exists and **before** closing details: the investigation can reveal the draft's shape was wrong. Does the spec still carry **one** functional outcome, did its purpose survive, can the delivery be accepted as a unit? The verdict is **one of three shapes** — `same` | `split` | `replace` — each with its own branch; only the last two ask anything.
84
86
 
87
+ > **Resolved before the gap loop starts, never carried into it (hard rule).** A `split` or a `replace` is asked, answered and applied **immediately** — its own structured-choice, in its own step, between the baseline and the first gap batch. It never travels in `pending_human`: that collection is rebuilt on every iteration and is reserved for questions about functional, technical or scope **gaps**, so a shape decision parked there is erased by the next batch — or never asked at all, because a spec with no blocking gap breaks out of the loop before the batch is built. The resolution lands in `CHECKPOINT` **before** anything else runs, so a resume re-enters with the shape already decided and never re-asks it.
88
+
85
89
  - same outcome — more clarity, or more technical components → **`same`**: no shape question, keep refining this spec;
86
90
  - independent functional outcomes discovered → **`split`** (below);
87
91
  - purpose fundamentally changed → **`replace`** (below);
@@ -97,6 +101,8 @@ Runs once the baseline exists and **before** closing details: the investigation
97
101
  - **New spec:** this one is **preserved**, its purpose never silently rewritten; the new one is minted with `aw next-number docs/specs`, born **`status: draft`**, its `## Origin` recording the origin spec, the replaced purpose and the user's decision. Its path goes to the `CHECKPOINT`; the run closes reporting `/w:spec-refine <new path>` as the next step.
98
102
  - **Reformulate:** same number/path, the work treated as `refining` while rewritten; baseline, gap classification and the *ready-for-plan gate* run again over the new purpose; `status` is stamped only on the save that follows the passing gate, and the material decision lands in `## Decisions`.
99
103
 
104
+ **Every branch has a way out that changes nothing.** The `flow` control present on every structured-choice (chassis) is that exit here: `Cerrar` closes the run **without applying the shape change** — no sibling minted, no spec reformulated, the document untouched and the decision recorded in `CHECKPOINT` as declined. And no branch writes a file without the user's confirmation: minting siblings and minting a replacement both go through the same confirm-before-write rule as an in-place save.
105
+
100
106
  Neither branch adds a `superseded` status or archives the replaced spec: a historical close needs its own runtime contract, out of scope here.
101
107
 
102
108
  ## Deliverable schema (the spec, edited in place)
@@ -193,15 +199,23 @@ spec-refine-loop(spec):
193
199
  adopt(spec-new facts + assumptions + open questions + conversation) # never re-derive (§ Reads)
194
200
  baseline = resolve_current_behavior(work) # inline research, ONLY what the change rests on
195
201
  shape = change_shape_gate(work, baseline) # BEFORE closing details → same | split | replace
196
- if shape == split: pending_human.push(split offer) # `Dividir en varias specs` | `Una sola spec`
197
- if shape == replace: pending_human.push(replace offer) # `Crear una nueva spec` | `Reformular esta spec`
202
+ if shape != same: # RESOLVED HERE never queued into pending_human
203
+ ans = structured_choice(content: [the offer of THIS branch], # split and replace never share labels
204
+ flow: [Compactar, Cerrar])
205
+ write CHECKPOINT (the decision + its consequence) # BEFORE acting: a resume re-enters already decided
206
+ flow Cerrar → goto finalize # closed without applying the change; the spec stays untouched
207
+ `Una sola spec` → shape resolved as same; keep refining this spec
208
+ `Dividir en varias specs` → the accepted cut is fixed now; its writes wait for `Guardar specs`
209
+ `Crear una nueva spec` → mint draft with confirmation (## Origin) ; THIS spec untouched ;
210
+ CHECKPOINT.Next = refine it ; goto finalize
211
+ `Reformular esta spec` → same number/path ; re-run baseline + this gate before any stamp
198
212
  attempts = {} # anti re-fire per gap
199
213
  repeat:
200
214
  gaps = classify_by_destination(detect_gaps(work)) minus the "exhausted" gaps
201
215
  record(gaps.plan_owned + gaps.deferrable) → ## Open questions with destination # never closed here
202
216
  blocking = gaps.spec_blocking
203
217
  if blocking == ∅: break
204
- batch = top ≤3 blocking ; pending_human = []
218
+ batch = top ≤3 blocking ; pending_human = [] # gap questions ONLY — the shape was resolved above
205
219
  seed CHECKPOINT.Pending/Next = batch (refine_session) # BEFORE: seed the intent (artifact-first)
206
220
  for each gap in batch:
207
221
  if gap = UI (requirement involves UI, ## UI spec missing):
@@ -222,9 +236,7 @@ spec-refine-loop(spec):
222
236
  switch(flow):
223
237
  Compactar → write CHECKPOINT (refine_session) ; compact(harness) ; continue
224
238
  Cerrar → goto finalize
225
- work = integrate(work, ans) # → Decisions / Open questions / the accepted shape
226
- accepted `Crear una nueva spec` → mint draft (## Origin) ; this one untouched ; CHECKPOINT.Next = refine it ; goto finalize
227
- accepted `Reformular esta spec` → same number/path ; re-run baseline + gaps + ready-for-plan gate before any stamp
239
+ work = integrate(work, ans) # → Decisions / Open questions
228
240
  ideation offer accepted → run the round NOW, then its verdicts as a NEW ≤3+flow batch (§ Ideation gate)
229
241
  ideation offer declined → mark that gap exhausted # anti re-fire; on-demand entry stays open
230
242
  # no BLOCKING gaps → ready-for-plan gate = Success criteria green (read-only) before offering Guardar:
@@ -247,6 +259,7 @@ finalize:
247
259
  Full mechanism (3 cases, `Compactar`, re-run on demand with `--reopen`) in the chassis (§ *Compact / resume*). SPEC keys:
248
260
 
249
261
  - The **prior-work mark** is the frontmatter `status: ready-for-plan` (legacy specs: `## Refinement decisions`, older ones also `## Q&A traceability`).
262
+ - The **shape decision survives a resume.** It is written to `CHECKPOINT` the moment it is taken, before anything acts on it, so a compact, a `Cerrar` or a crash between the gate and the save re-enters with the shape settled — the gate is not re-run and the question is not re-asked. Only a *new* run over a spec whose baseline changed re-opens it.
250
263
  - Re-refining on demand is a **first-class operation** while the flow stays in SPEC (new requirements, scope changes, after re-reading the spec): it always reads the **spec itself**, incremental re-refinement; on `Guardar`, edits in place with confirmation.
251
264
  - **Legacy migration happens only here.** A re-refined legacy spec runs the gate like any other; on `Guardar`, its `## Refinement decisions` is renamed `## Decisions` and pruned to the material decisions — **in the same write that stamps `status`**, so the spec is never left with no mark. Specs nobody re-refines are not migrated.
252
265
  - **`Cerrar` before converging leaves the spec untouched**: the progress lives in the `CHECKPOINT`, and `status` is neither invented nor downgraded. `refining` is understood **on read** (a hand-written spec may declare it) — this loop never writes a partial spec.
@@ -97,14 +97,13 @@ Outside an active session: relax to "1 line + no co-author"; the `session<NNN>`
97
97
 
98
98
  Autonomous `git merge` is forbidden (above), **but** resolving an **in-progress** merge (MERGE_HEAD), or one invoked by the user via `/w:fix-git`, **is** sanctioned work. **Workspace-agnostic**: it operates on any repo (no `.workflow/`, flows or sessions required).
99
99
 
100
- 1. **Detect + identify** with `aw merge-state [<path>|--source <alias>|--all]` (read-only): `is_merging`, `current_branch` (**destination / ours**), `merge_origin` (**origin / theirs**), `conflicted_files`. If `merge_origin` comes empty, check `.git/MERGE_MSG` or `git log --oneline -1 MERGE_HEAD`.
101
- 2. **Analyze each conflict's intent** **before** resolving — never pick a side blindly:
102
- - The three versions: `git show :1:<file>` (base) · `:2:<file>` (ours/destination) · `:3:<file>` (theirs/origin).
103
- - Each side's why: `git log --merge -p -- <file>`; the hunk's history on each branch.
104
- - The code around the marker (coherence with the rest of the file).
105
- 3. **Resolve** by editing the file (remove `<<<<<<<` / `=======` / `>>>>>>>`): pick **ours**, **theirs**, **combine** both intents, or **rewrite** to satisfy both. `git add <file>` what is resolved.
106
- 4. **Ask** (*structured-choice*) when the intent is **ambiguous** or both sides are **incoherent** with each other (not combinable without losing something): one content question per doubtful file/hunk (≤3 + `flow` control), options "Ours (`<destination>`)" / "Theirs (`<origin>`)" / "Combine" / "Edit manually". **Never invent** a resolution under real doubt.
107
- 5. **Proposed commit**: completing the merge is a `git commit` (the merge commit) → **propose-then-execute** like any commit (canonical format above; outside a session → 1 line without the `session<NNN>` tag; never `--no-verify`/`--amend`/`push`). The `git-commit-advisor` hook gates it.
100
+ **The mechanics live in the CLI** (`aw fix-git prepare | apply | commit`); what follows is the reasoning it expects from you. Never edit a conflicted file, `git add` or `git commit` by hand here — see [`../../commands/fix-git.md`](../../commands/fix-git.md) for the exact invocations.
101
+
102
+ 1. **Detect + identify**: `aw fix-git prepare` (read-only) returns the merge direction (**theirs → ours**), the conflicted paths and, per path, its three index stages with their blob hashes. `aw merge-state` remains the lighter inspector when you only need the state.
103
+ 2. **Analyze each conflict's intent** **before** resolving — never pick a side blindly. The request already carries the three versions: `base` (common ancestor), `ours` (destination) and `theirs` (origin). Add `git log --merge -p -- <file>` when the *why* of a hunk is not evident, and read the surrounding code for coherence.
104
+ 3. **Resolve** by composing the complete resolved file: pick **ours**, **theirs**, **combine** both intents, or **rewrite** to satisfy both — with no `<<<<<<<` / `=======` / `>>>>>>>` left. The CLI writes and stages it; a leftover marker is rejected, and so is a path that is no longer in conflict.
105
+ 4. **Ask** (*structured-choice*) when the intent is **ambiguous** or both sides are **incoherent** with each other (not combinable without losing something): answer `state: "ambiguous"` so nothing is written, then ask one content question per doubtful file/hunk (≤3 + `flow` control), options "Ours (`<destination>`)" / "Theirs (`<origin>`)" / "Combine" / "Edit manually". **Never invent** a resolution under real doubt. A **binary** conflict is never resolved automatically: propose `git checkout --ours|--theirs`.
106
+ 5. **Proposed commit**: completing the merge is a `git commit` (the merge commit) → **propose-then-execute** like any commit (canonical format above; outside a session 1 line without the `session<NNN>` tag; never `--no-verify`/`--amend`/`push`). It is a **separate, confirmed** invocation `aw fix-git commit --message "<msg>" --confirm` which refuses while any file stays unmerged. The `git-commit-advisor` hook gates it.
108
107
  6. **Escape hatch**: if the merge must not complete, `git merge --abort` **after user confirmation** (*structured-choice*) — leaves the repo as before the merge.
109
108
 
110
109
  > **Resume via git**: the merge state in `.git` (MERGE_HEAD + index) **is** the checkpoint; re-running `/w:fix-git` resumes from the remaining conflicts. No session, no artifact.