@tacuchi/agent-workflow-cli 21.0.0 → 21.3.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 (170) hide show
  1. package/README.md +3 -2
  2. package/dist/adapters/git-cli.js +12 -7
  3. package/dist/adapters/git-cli.js.map +1 -1
  4. package/dist/application/capability/compose.js +161 -0
  5. package/dist/application/capability/compose.js.map +1 -0
  6. package/dist/application/capability/descriptor-loader.js +109 -0
  7. package/dist/application/capability/descriptor-loader.js.map +1 -0
  8. package/dist/application/capability/design-handler.js +299 -0
  9. package/dist/application/capability/design-handler.js.map +1 -0
  10. package/dist/application/capability/dispatcher.js +312 -0
  11. package/dist/application/capability/dispatcher.js.map +1 -0
  12. package/dist/application/capability/durable-effect.js +220 -0
  13. package/dist/application/capability/durable-effect.js.map +1 -0
  14. package/dist/application/capability/installed-inventory.js +168 -0
  15. package/dist/application/capability/installed-inventory.js.map +1 -0
  16. package/dist/application/capability/readiness.js +204 -0
  17. package/dist/application/capability/readiness.js.map +1 -0
  18. package/dist/application/capability/resolution.js +264 -0
  19. package/dist/application/capability/resolution.js.map +1 -0
  20. package/dist/application/capability/wrapper.js +195 -0
  21. package/dist/application/capability/wrapper.js.map +1 -0
  22. package/dist/application/context/manifest.js +11 -5
  23. package/dist/application/context/manifest.js.map +1 -1
  24. package/dist/application/context/measure.js +5 -2
  25. package/dist/application/context/measure.js.map +1 -1
  26. package/dist/application/context/plan-service.js +6 -6
  27. package/dist/application/context/plan-service.js.map +1 -1
  28. package/dist/application/design/design-bundle-service.js +148 -0
  29. package/dist/application/design/design-bundle-service.js.map +1 -0
  30. package/dist/application/design/design-proposal-service.js +69 -0
  31. package/dist/application/design/design-proposal-service.js.map +1 -0
  32. package/dist/application/design/design-publish-service.js +275 -7
  33. package/dist/application/design/design-publish-service.js.map +1 -1
  34. package/dist/application/design/design-record-service.js +100 -0
  35. package/dist/application/design/design-record-service.js.map +1 -0
  36. package/dist/application/flow/advance.js +533 -0
  37. package/dist/application/flow/advance.js.map +1 -0
  38. package/dist/application/flow/flow-service.js +65 -0
  39. package/dist/application/flow/flow-service.js.map +1 -0
  40. package/dist/application/flow/run-projection.js +80 -0
  41. package/dist/application/flow/run-projection.js.map +1 -0
  42. package/dist/application/flow/run-state-service.js +107 -0
  43. package/dist/application/flow/run-state-service.js.map +1 -0
  44. package/dist/application/flow/submit.js +423 -0
  45. package/dist/application/flow/submit.js.map +1 -0
  46. package/dist/application/markdown.js +16 -2
  47. package/dist/application/markdown.js.map +1 -1
  48. package/dist/application/resume-service.js +23 -10
  49. package/dist/application/resume-service.js.map +1 -1
  50. package/dist/application/self/hooks-toml.js +137 -17
  51. package/dist/application/self/hooks-toml.js.map +1 -1
  52. package/dist/application/self/host-states.js +87 -1
  53. package/dist/application/self/host-states.js.map +1 -1
  54. package/dist/application/self/install-hooks.js +62 -6
  55. package/dist/application/self/install-hooks.js.map +1 -1
  56. package/dist/application/self/install-skill.js +37 -6
  57. package/dist/application/self/install-skill.js.map +1 -1
  58. package/dist/application/self/uninstall.js +21 -0
  59. package/dist/application/self/uninstall.js.map +1 -1
  60. package/dist/application/skills-resolver-service.js +8 -2
  61. package/dist/application/skills-resolver-service.js.map +1 -1
  62. package/dist/application/status-service.js +4 -1
  63. package/dist/application/status-service.js.map +1 -1
  64. package/dist/application/workline-index-service.js +15 -2
  65. package/dist/application/workline-index-service.js.map +1 -1
  66. package/dist/application/workspace-init-service.js +13 -1
  67. package/dist/application/workspace-init-service.js.map +1 -1
  68. package/dist/cli/commands/capability.js +182 -0
  69. package/dist/cli/commands/capability.js.map +1 -0
  70. package/dist/cli/commands/flow.js +71 -0
  71. package/dist/cli/commands/flow.js.map +1 -0
  72. package/dist/cli/commands/index.js +4 -0
  73. package/dist/cli/commands/index.js.map +1 -1
  74. package/dist/cli/commands/skills.js +55 -2
  75. package/dist/cli/commands/skills.js.map +1 -1
  76. package/dist/cli/commands/status.js +5 -0
  77. package/dist/cli/commands/status.js.map +1 -1
  78. package/dist/cli/help-groups.js +6 -0
  79. package/dist/cli/help-groups.js.map +1 -1
  80. package/dist/cli/parser.js +6 -0
  81. package/dist/cli/parser.js.map +1 -1
  82. package/dist/cli/tui/components/host-admin-section.js +14 -2
  83. package/dist/cli/tui/components/host-admin-section.js.map +1 -1
  84. package/dist/cli/tui/data/workflow-content.js +13 -1
  85. package/dist/cli/tui/data/workflow-content.js.map +1 -1
  86. package/dist/cli/tui/tabs/workflow-tab.js +8 -1
  87. package/dist/cli/tui/tabs/workflow-tab.js.map +1 -1
  88. package/dist/domain/capability/descriptor.js +553 -0
  89. package/dist/domain/capability/descriptor.js.map +1 -0
  90. package/dist/domain/capability/effects.js +90 -0
  91. package/dist/domain/capability/effects.js.map +1 -0
  92. package/dist/domain/capability/protocol.js +494 -0
  93. package/dist/domain/capability/protocol.js.map +1 -0
  94. package/dist/domain/contract-reader.js +84 -0
  95. package/dist/domain/contract-reader.js.map +1 -0
  96. package/dist/domain/design/adapter.js +161 -0
  97. package/dist/domain/design/adapter.js.map +1 -0
  98. package/dist/domain/design/artifact.js +148 -4
  99. package/dist/domain/design/artifact.js.map +1 -1
  100. package/dist/domain/design/capability.js +263 -4
  101. package/dist/domain/design/capability.js.map +1 -1
  102. package/dist/domain/design/direct.js +108 -0
  103. package/dist/domain/design/direct.js.map +1 -0
  104. package/dist/domain/design/external-send.js +65 -0
  105. package/dist/domain/design/external-send.js.map +1 -0
  106. package/dist/domain/design/maturity.js +71 -0
  107. package/dist/domain/design/maturity.js.map +1 -1
  108. package/dist/domain/design/offline.js +92 -0
  109. package/dist/domain/design/offline.js.map +1 -0
  110. package/dist/domain/design/profiles.js +212 -0
  111. package/dist/domain/design/profiles.js.map +1 -0
  112. package/dist/domain/design/proposal.js +234 -0
  113. package/dist/domain/design/proposal.js.map +1 -0
  114. package/dist/domain/design/render-bundle.js +0 -0
  115. package/dist/domain/design/render-bundle.js.map +1 -0
  116. package/dist/domain/design/rendition.js +472 -0
  117. package/dist/domain/design/rendition.js.map +1 -0
  118. package/dist/domain/design/sources.js +180 -0
  119. package/dist/domain/design/sources.js.map +1 -0
  120. package/dist/domain/design/validation.js +12 -68
  121. package/dist/domain/design/validation.js.map +1 -1
  122. package/dist/domain/design/visual-evidence.js +155 -0
  123. package/dist/domain/design/visual-evidence.js.map +1 -0
  124. package/dist/domain/flow/answer.js +459 -0
  125. package/dist/domain/flow/answer.js.map +1 -0
  126. package/dist/domain/flow/authority.js +2338 -0
  127. package/dist/domain/flow/authority.js.map +1 -0
  128. package/dist/domain/flow/authorization.js +62 -0
  129. package/dist/domain/flow/authorization.js.map +1 -0
  130. package/dist/domain/flow/directive.js +421 -0
  131. package/dist/domain/flow/directive.js.map +1 -0
  132. package/dist/domain/flow/rules.js +140 -0
  133. package/dist/domain/flow/rules.js.map +1 -0
  134. package/dist/domain/flow/run-state.js +317 -0
  135. package/dist/domain/flow/run-state.js.map +1 -0
  136. package/dist/domain/harnesses.js +124 -4
  137. package/dist/domain/harnesses.js.map +1 -1
  138. package/dist/domain/host-verification.js +8 -8
  139. package/dist/domain/skills.js +13 -14
  140. package/dist/domain/skills.js.map +1 -1
  141. package/dist/domain/structured-choice-stamp.js +106 -0
  142. package/dist/domain/structured-choice-stamp.js.map +1 -0
  143. package/package.json +1 -1
  144. package/skills/w/SKILL.md +5 -5
  145. package/skills/w/context/MANIFEST.json +42 -1
  146. package/skills/w/harness/HARNESS.md +30 -4
  147. package/skills/w/loops/CHASSIS.md +11 -20
  148. package/skills/w/loops/CODE-POLICIES.md +9 -15
  149. package/skills/w/loops/plan-exec-loop/LOOP.md +11 -13
  150. package/skills/w/loops/plan-new-loop/LOOP.md +6 -4
  151. package/skills/w/loops/plan-refine-loop/LOOP.md +5 -3
  152. package/skills/w/loops/quick-loop/LOOP.md +18 -26
  153. package/skills/w/loops/spec-refine-loop/LOOP.md +14 -18
  154. package/skills/w/modules/COMPACTION.md +2 -6
  155. package/skills/w/modules/DB-SCRIPTS-ONLY.md +2 -0
  156. package/skills/w/modules/DESIGN-REFERENCES.md +15 -11
  157. package/skills/w/modules/IDEATION-GATE.md +3 -3
  158. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +17 -36
  159. package/skills/w/modules/PLAN-INPUT.md +5 -3
  160. package/skills/w/modules/PLAN-REFINE-SPLIT.md +3 -1
  161. package/skills/w/modules/PLAN-SPLIT-GATE.md +7 -5
  162. package/skills/w/modules/PROMPT-CONTINUITY.md +3 -1
  163. package/skills/w/modules/SPEC-CHANGE-SHAPE.md +4 -4
  164. package/skills/w/roles/README.md +2 -0
  165. package/skills/w/roles/design/CONTRACT.md +80 -0
  166. package/skills/w/roles/design/ROLE.md +7 -0
  167. package/skills/w/schemas/capability-descriptor.schema.json +260 -0
  168. package/skills/w/schemas/design/design-render-bundle.v1.schema.json +191 -0
  169. package/skills/w/schemas/design/design-rendition.v1.schema.json +232 -0
  170. package/skills/w/schemas/design/ui-screen.v1.schema.json +29 -1
@@ -26,27 +26,19 @@ The phase contracts, dependencies, risks and open questions are the reproducible
26
26
 
27
27
  ## Inference
28
28
 
29
- Choose the maximal consecutive `continuous` ranges. A range is eligible only when all of these
30
- are true:
29
+ Choose the maximal consecutive `continuous` ranges: a range stays eligible while nothing observable
30
+ breaks it. Anything else is `isolated`; if every phase is eligible, the whole plan is one batch.
31
31
 
32
- 1. Every dependency is already satisfied or is an earlier phase in the same range.
33
- 2. No phase result, proof, probe or human decision determines how a later phase must be built.
34
- 3. There is no unresolved question, live blocker, operative handoff or irreversible external
35
- action between its phases.
36
- 4. No intermediate commit, release, review or deployment is a required recovery boundary.
37
- 5. The combined change is coherent, recoverable and reviewable as one unit.
32
+ > **Which facts break eligibility, and what one of them costs, is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document. It emits the closed vocabulary of those facts at the boundary that asks for them.
38
33
 
39
- Anything else is `isolated`. If every phase is eligible, the whole plan is one batch. This is an
40
- AI inference from observable facts, not a preference question; planning writes it without asking.
41
- The PLAN gate fails when a phase is missing, duplicated, reordered or grouped across an
42
- ineligible boundary.
34
+ This is an inference from observable facts, not a preference question. The PLAN gate fails when a
35
+ phase is missing, duplicated, reordered or grouped across an ineligible boundary.
43
36
 
44
37
  ## Runtime authority
45
38
 
46
39
  Before editing, `plan-exec` repeats the inference over pending phases using the plan plus live
47
- dependencies, branches, working trees, blockers and risks.
48
- It may merge or split the declared batches without asking: current evidence wins.
49
- The declared section remains planning structure;
40
+ dependencies, branches, working trees, blockers and risks: current evidence wins over the declared
41
+ partition. The declared section remains planning structure;
50
42
  the effective batches and any difference are recorded in `CHECKPOINT`.
51
43
 
52
44
  A legacy plan without `## Execution batches` is valid. Execution infers effective batches and
@@ -54,20 +46,10 @@ records them in `CHECKPOINT`; it does not normalize the plan merely to add the s
54
46
 
55
47
  ## Continuous cycle
56
48
 
57
- For one effective batch:
58
-
59
- 1. Verify every affected source and seed one batch intent before editing.
60
- 2. Implement its phases in order. Mark local tasks done and set reached phases to `en ejecución`,
61
- but run no phase proof, test runner, build, lint or closing review between them.
62
- 3. After all implementation is written, run every phase proof in order, then the justified
63
- focused/risk checks and applicable cross-cutting validations. The last pending batch also runs
64
- the plan's final validation here, before Git.
65
- 4. Fix failures autonomously and rerun the affected checks. Review the whole batch diff once.
66
- 5. Only when every check, exit condition and review is green, flip all batch phases to `validada`,
67
- update `CHECKPOINT`, and enter the Git step.
68
-
69
- This is the narrow exception to the chassis' per-phase artifact beat and clean-tree rule: the
70
- batch is the execution boundary. Task checkboxes and phase states keep it resumable.
49
+ The batch not the phase — is the execution boundary: implementation runs straight through, and
50
+ every proof, check, review and state flip happens once at its close. This is the narrow exception to
51
+ the chassis' per-phase artifact beat and clean-tree rule, and task checkboxes plus phase states are
52
+ what keep it resumable. The order of those closing steps is the CLI's, per the note above.
71
53
 
72
54
  A real blocker or structural/functional deviation stops immediately. No unproven phase becomes
73
55
  `validada`; the combined changes remain uncommitted and the actual states plus the unblocking
@@ -75,10 +57,9 @@ action go to `CHECKPOINT`.
75
57
 
76
58
  ## Git authorization
77
59
 
78
- A green batch produces exactly one proposed commit per affected source. One consolidated approval
79
- covers all of those commits. If the user explicitly pre-authorized commits conditional on every
80
- batch check passing, record that authorization before editing and commit without another question.
81
- A failed or unrun check never satisfies the condition and never creates a commit. For the last
82
- pending batch, the same authorization also marks the fully validated plan `done` before committing,
83
- so that final plan write is included in the source's single commit; there is no second completion
84
- question or commit.
60
+ A green batch produces exactly one proposed commit per affected source. Approving is not committing,
61
+ and a check that never ran is not a green batch. For the last pending batch the same approval also
62
+ covers marking the fully validated plan `done`, so that final write rides in the source's single
63
+ commit instead of asking a second time.
64
+
65
+ > **What proves the batch was green is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document — positionally, behind the delegated validation and the review, neither of which a narration can pass.
@@ -5,12 +5,14 @@ Loaded when the input is not plainly a `ready-for-plan` spec (signal `input`).
5
5
  ## plan-new — four modes
6
6
 
7
7
  1. **Ready spec** (`docs/specs/NNN-spec-<slug>.md` whose frontmatter declares `status: ready-for-plan`) → ideal. Proceed straight to the loop.
8
- 2. **Spec not ready** (`status: draft` / `refining`, or no mark at all) → **soft-suggest** running `/w:spec-refine` first. It is a suggestion, **never a block**: the user may proceed. Questions the spec left with destination `PLAN` are this flow's **input**, not a reason to send it back.
8
+ 2. **Spec not ready** (`status: draft` / `refining`, or no mark at all) → **soft-suggest** running `/w:spec-refine` first, **never a block**. Questions the spec left with destination `PLAN` are this flow's **input**, not a reason to send it back.
9
9
  3. **Prompt** (no spec referenced) → propose the SPEC flow; **by default launch `/w:spec-new`** with that prompt and continue the natural flow from there.
10
- 4. **External plan content** — the argument carries an **already-built plan** (host plan mode, hand-written, another agent's) → **adopt it**. Single pass, **NO RESEARCH**: materialize as `docs/plans/PPP-plan-<slug>.md` (`aw next-number docs/plans`), normalized to the rich-plan schema with only what the source provides. `## Origin` = "adopted from <source>" + attribution (host · model · date). Then offer `/w:plan-refine` or `/w:plan-exec`. Anti-duplicate: a plan whose `## Origin` matches this objective recommend resuming it, never a second one. Adoption **never regenerates over** an existing plan-doc.
10
+ 4. **External plan content** — the argument carries an **already-built plan** (host plan mode, hand-written, another agent's) → **adopt it**. Single pass, **NO RESEARCH**: materialize as `docs/plans/PPP-plan-<slug>.md`, normalized to the rich-plan schema with only what the source provides. `## Origin` = "adopted from <source>" + attribution (host · model · date). Then offer `/w:plan-refine` or `/w:plan-exec`. Anti-duplicate: a plan whose `## Origin` matches this objective is resumed, never duplicated. Adoption **never regenerates over** an existing plan-doc.
11
11
 
12
12
  > **Mode 3 vs 4:** a prompt that *describes a wish* → SPEC (mode 3); content that *already is a plan* → adopt (mode 4).
13
13
 
14
+ > **What adoption may do once the mode is settled is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document.
15
+
14
16
  > **Ready vs not** is read from the spec's frontmatter `status`, never from the filename. **Legacy compat:** a spec with no frontmatter that carries `## Refinement decisions` — or the older `## Q&A traceability` — counts as ready the same way.
15
17
 
16
18
  ## plan-refine — three modes
@@ -23,4 +25,4 @@ Loaded when the input is not plainly a `ready-for-plan` spec (signal `input`).
23
25
 
24
26
  ## Numbering
25
27
 
26
- The plan is named `docs/plans/PPP-plan-<slug>.md`. `aw next-number docs/plans` returns JSON (field `next` = `PPP`); the slug is short kebab-case from the Requirement (`[a-z0-9-]`, ≤ ~5 words / ≤ 40 chars). It does **not inherit the spec's `NNN`** — the link is established by reference in `## Origin`, never by number.
28
+ The plan is named `docs/plans/PPP-plan-<slug>.md`; `aw next-number docs/plans` mints `PPP` and the slug comes from the Requirement. It does **not inherit the spec's `NNN`** — the link is established by reference in `## Origin`, never by number.
@@ -9,4 +9,6 @@ The gate itself — signals, offer, anti-duplicate, sibling contract, partition
9
9
  - The original plan **keeps its number/path**: it is rewritten **reduced** to its remaining tranche (in place, with confirmation). The extracted tranches become newly minted sibling plans (`aw next-number docs/plans` immediately before each write); their `## Origin` records "split from `docs/plans/PPP-plan-<slug>.md`" + the source spec + the siblings by path.
10
10
  - The gate also fires on **partially executed** plans. **Completed tasks (`- [x]`) never move to a sibling** — execution history stays anchored to the original path (plan-exec sessions' `## Origin` keep resolving); only pending work is extracted.
11
11
  - The split is recorded in `## Refinement decisions` (what moved where + why); original + siblings together keep the **complete, disjoint partition** of the spec criteria (spec-less: the Delta 2 degradation applies).
12
- - **Closing action** on the split branch: `Guardar planes` (edit the original reduced + write the extracted siblings); the normal branch keeps `Guardar plan refinado`.
12
+ - **Closing action** on the split branch edits the original reduced and writes the extracted siblings after the confirmation, never before it.
13
+
14
+ > **When the cut fires, and that the write follows the confirmation, is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document. The offer's alternatives are its too.
@@ -4,11 +4,13 @@ Loaded when the plan may have to become more than one document (signal `split`).
4
4
 
5
5
  ## Split gate (multi-plan)
6
6
 
7
- Resolves the **Plan splittable** gap (Delta 2) — the canonical definition for **both** plan loops (`plan-refine-loop` references it, never redefines it). It fires **only on clear signals** (≥2 of: tranches independently executable/deliverable · no shared deps/risk between tranches · different requested moments/priorities · the plan far exceeds S-complexity phases · the user asked for staging); borderline → **one plan, no question**. It can be assessed during decomposition or at the coherence gate, always **before** `Guardar`.
7
+ Resolves the **Plan splittable** gap (Delta 2) — the canonical definition for **both** plan loops (`plan-refine-loop` references it, never redefines it). It fires **only on clear signals** of independently deliverable tranches, and never on a borderline plan.
8
8
 
9
- - **The offer** enters the batch as a **content question** (counts in the ≤3): the body shows the proposed cut in the **user's language** per sibling, a name + slug, a 1-line scope, the phase mapping and the order. Labels: `Dividir en varios planes` (recommended when the signals hold) | `Un solo plan`. Declining marks the gap **exhausted** (no re-offer this run); a free-form answer adjusts the cut. The accepted cut is seeded into `CHECKPOINT` a resume does **not** re-ask.
10
- - **Anti-duplicate** (the `create_or_resume` spirit): if sibling plans whose `## Origin` references this same spec/split already exist, the recommended option becomes resuming them (`/w:plan-refine` / `/w:plan-exec` semantics) — never a second set.
11
- - **On acceptance** same run, same session (one session per run, one HISTORY row): **all N siblings are elaborated complete** in this run — each gets the full Delta 1 schema and is immediately executable (`plan-exec` runs any plan; a seed without `## Tasks` would break that contract). Context pressure is absorbed by self-regulation (chassis § *Compact / resume*). Numbering: `aw next-number docs/plans` **immediately before each write** numbers come out consecutive, so every sibling path is known after the first mint.
9
+ > **Which signals count, how many it takes, and therefore whether the offer appears at all, is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document. Recognizing a signal is judgment; counting them is a rule.
10
+
11
+ - **The offer** enters the batch as a **content question** (counts in the ≤3): the body shows the proposed cut in the **user's language** per sibling, a name + slug, a 1-line scope, the phase mapping and the order. Declining marks the gap **exhausted** (no re-offer this run); a free-form answer adjusts the cut. The accepted cut is seeded into `CHECKPOINT` a resume does **not** re-ask.
12
+ - **Anti-duplicate** (the `create_or_resume` spirit): sibling plans whose `## Origin` references this same spec/split are resumed, never minted a second time.
13
+ - **On acceptance** — same run, same session (one session per run, one HISTORY row): **all N siblings are elaborated complete** in this run — each gets the full Delta 1 schema and is immediately executable (`plan-exec` runs any plan; a seed without `## Tasks` would break that contract). Context pressure is absorbed by self-regulation (chassis § *Compact / resume*). Numbering follows [`PLAN-INPUT`](PLAN-INPUT.md) § *Numbering*, minted immediately before each write.
12
14
  - **Sibling contract**: each `## Origin` records the shared source spec + `split (part i/N)` + the **siblings by path** + the order; `## Dependencies` (the existing optional section) carries the inter-plan order — **acyclic and advisory** (`plan-exec` does not enforce it; it only orients what to attack first).
13
15
  - **Coherence gate, re-framed**: every spec acceptance criterion traces to **exactly one** sibling — a **complete, disjoint partition**; each sibling's Final behavior block (in `## Solution`) covers its subset; the union covers the spec. Spec-less plans anchor the partition to their own Final behavior block / `Validations`.
14
- - **Closing action** on the split branch: `Guardar planes` (the single-plan branch keeps `Guardar plan`).
16
+ - **Closing action** on the split branch writes every sibling in the same run; the single-plan branch writes one document. Both are the same confirmation step, and its alternatives are the CLI's.
@@ -10,4 +10,6 @@ Loaded when a bare prompt continues an existing work line (signal `resume`).
10
10
  2. `"second prompt"` (**no command**, related work) → does **not** create another session: **continues/reopens the most recent one** (from step 1) and appends the new scripts to **that same** `SCRIPTS.sql`.
11
11
  3. `/w:quick "third prompt"` (**command** again) → **new** session, new loop.
12
12
 
13
- > The **command** signals "new work line"; a **bare prompt** means "same line" by default continue/reopen the most recent session (the *last started*). Clearly unrelated offer choosing (`continuar NNN` | `trabajo nuevo`) or fall to the **no-flow** branch (write into `docs/` by convention + numbering). No workspace **vanilla** behavior.
13
+ > **Which line a prompt joins is not this document's call:** a command opens a new one through `aw session-create`, a bare prompt continues the most recent through `aw resume`. Both fire **before** a run exists, so no journey has a step for them. The reason stays: the **command** is the signal for "new work line", so nobody loses a thread by not typing one, or forks one by typing it twice.
14
+
15
+ Whether a prompt really belongs to the open line is judgment. Clearly unrelated → offer choosing (`continuar NNN` | `trabajo nuevo`) or fall to the **no-flow** branch (`docs/` by convention + numbering). No workspace → **vanilla** behavior.
@@ -8,14 +8,14 @@ Loaded when the investigation may have changed the spec shape (signal `shape`).
8
8
 
9
9
  | Finding | What it asks | What it writes |
10
10
  |---|---|---|
11
- | **`split`** — independent functional outcomes discovered | `Dividir en varias specs` \| `Una sola spec` | the original, rewritten reduced, **plus** one new file per extracted outcome |
11
+ | **`split`** — independent functional outcomes discovered | cardinality: one spec, or several siblings | the original, rewritten reduced, **plus** one new file per extracted outcome |
12
12
  | **`replace`** — the purpose itself changed | `Crear una nueva spec` \| `Reformular esta spec` | `Crear` → one **new** file, this spec untouched · `Reformular` → **no new file**: this same file, same number, same path |
13
13
 
14
14
  ## Change-shape gate
15
15
 
16
- 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.
16
+ 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.
17
17
 
18
- > **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.
18
+ > **When it runs, and that it never travels inside the gap loop, is not this document's call:** the deterministic steps below are decided by the CLI (`aw flow advance`), not by this document. Why it matters: a shape decision parked among the gap questions is erased by the next batch — or never asked at all, because a spec with no blocking gap leaves the loop before a batch is built.
19
19
 
20
20
  - same outcome — more clarity, or more technical components → **`same`**: no shape question, keep refining this spec;
21
21
  - independent functional outcomes discovered → **`split`** (below);
@@ -25,7 +25,7 @@ Runs once the baseline exists and **before** closing details: the investigation
25
25
 
26
26
  **Split criterion** — the one `spec-new` already uses ([`SPLIT-GATE.md`](SPLIT-GATE.md), `spec-new`'s `split` module), never a different one: divide **only** when each part can be refined, accepted and planned on its own. Repos, technologies, layers or teams are **secondary evidence**, never the reason.
27
27
 
28
- **Split semantics (in place).** The offer enters the batch as a content question — `Dividir en varias specs` | `Una sola spec`; declining marks it **exhausted** for the run. On acceptance: the original **keeps its number/path**, rewritten reduced to its remaining outcome; each extracted outcome is minted with `aw next-number docs/specs` right before its write and is born **`status: draft`**. Siblings are **not** elaborated here — unlike the multi-plan gate, where `plan-exec` would break on a plan with no `## Tasks`; a draft spec is legitimate input to this very loop — so the run keeps refining the **reduced original** and reports `/w:spec-refine` as each sibling's next step. Every `## Origin` records "split from `docs/specs/NNN-spec-<slug>.md`" + the siblings **by path**. Closing action on this branch: `Guardar specs`.
28
+ **Split semantics (in place).** The offer enters the batch as a content question. On acceptance: the original **keeps its number/path**, rewritten reduced to its remaining outcome; each extracted outcome is minted with `aw next-number docs/specs` right before its write and is born **`status: draft`**. Siblings are **not** elaborated here — unlike the multi-plan gate, where `plan-exec` would break on a plan with no `## Tasks`; a draft spec is legitimate input to this very loop — so the run keeps refining the **reduced original** and reports `/w:spec-refine` as each sibling's next step. Every `## Origin` records "split from `docs/specs/NNN-spec-<slug>.md`" + the siblings **by path**. Closing action on this branch: `Guardar specs`.
29
29
 
30
30
  **Replace semantics.** Its offer is its own — `Crear una nueva spec` | `Reformular esta spec`, **never** the split labels: what gets decided is which identity carries the new purpose. Recommend **a new spec** when the main functional outcome or the actor/consumer changed; **reformulating** when the user confirms this file is still the same unit of work and wants to keep its identity.
31
31
 
@@ -51,6 +51,8 @@ built-in default
51
51
  2. **Role with no binding at any level** → use the built-in default (table above). No config needed for the common case.
52
52
  3. **`off`** → capability disabled. The loop continues without it; if the task required it, the loop reports why it cannot proceed or asks the human.
53
53
 
54
+ **A role whose skill declares a capability descriptor is stricter**, because there the binding decides what RUNS and not just which name is written: unset or the canonical name enables the built-in floor plus whatever compatible improvements the host selected; `off` applies the descriptor's per-operation policy and no host, wrapper or legacy name reverts it; anything else is `misconfigured` — a replacement binding does not select an improvement, and the file is never rewritten for you. Existing workspaces are not migrated: `aw skills --detail` explains the reclassification and the owner adopts unset, the canonical name or `off`.
55
+
54
56
  ---
55
57
 
56
58
  ## skills.toml format
@@ -0,0 +1,80 @@
1
+ # design — invocation contract
2
+
3
+ The single authority for **how** `design` is invoked. The installed wrapper
4
+ (`design/SKILL.md`) and [`ROLE.md`](ROLE.md) both point here instead of
5
+ restating it: two descriptions of one contract disagree the day either changes.
6
+
7
+ The machine-readable form is the descriptor published next to the wrapper
8
+ (`workline-capability.json`, schema `../../schemas/capability-descriptor.schema.json`).
9
+ This file is what a person or a loop reads.
10
+
11
+ ## One door, four stages
12
+
13
+ ```
14
+ aw capability prepare --capability design --operation <op> [--input k=v ...]
15
+ aw capability continue # stdin: {"parent": <request>}
16
+ aw capability validate # stdin: {"request": …, "answer": …}
17
+ aw capability apply --approval <digest> # stdin: {"request": …, "plan": …}
18
+ ```
19
+
20
+ The verbs are **stages**, never operations: the operation travels in the
21
+ envelope. Every attempt returns `outcome`, `output` and `receipt`. A
22
+ `needs_input` is answered with `continue`, which builds the NEXT attempt of the
23
+ same `invocation_id` — it never reuses the previous request.
24
+
25
+ ## What each caller may invoke
26
+
27
+ | Caller | Operations | Then |
28
+ |---|---|---|
29
+ | direct wrapper | all five | converses in the host; opens no flow session or document |
30
+ | SPEC REFINE | `create` · `update` · `validate` | keeps its own questions, gate and publication |
31
+ | PLAN NEW · PLAN REFINE | `update` · `validate` | closes its plan over the revision it references |
32
+ | PLAN EXEC · QUICK | `validate` | **consumes** the package inside its own lifecycle |
33
+
34
+ There is no sixth `consume` operation: consuming is what a flow DOES with a
35
+ validated package, not something it asks the capability to do. An operation
36
+ outside its row is refused, never improvised. A flow may add gates of its own and
37
+ may never lower one the capability already failed; a durable output produced
38
+ through the direct route is adopted later **by exact reference** — same identity,
39
+ revision and digest — with no recreation and no format conversion.
40
+
41
+ ## Sources, and what an omission costs
42
+
43
+ The v1 catalog: Markdown or text, images and screenshots, PDF, DOCX, PPTX, host
44
+ context or attachments, an existing package, and provider locators. Binary
45
+ documents are read by the **host's** multimodal capability — no parser ships in
46
+ the CLI — so what the catalog declares is what the domain can account for.
47
+
48
+ Every source ends in one of five dispositions, and each one that is not `used`
49
+ carries its reason: `used` · `skipped` (a decision) · `unsupported` (a format v1
50
+ never promised, every retired UI format included) · `unavailable` (it should
51
+ have been readable and was not) · `redacted` (withheld on purpose).
52
+
53
+ The consequence is fail-closed: a source that did not contribute blocks
54
+ `handoff` unless someone states, in writing, why the design does not need it. A
55
+ run that silently dropped a requirements document and still declared itself
56
+ ready for implementation is the failure this exists to prevent. Original
57
+ documents are never copied into the package unless a person names them, and
58
+ never when they are sensitive.
59
+
60
+ ## Where the output lands
61
+
62
+ Inside a workspace the package defaults to `docs/designs/` and is discoverable
63
+ by the index — which is what lets a spec or a plan reference it later without it
64
+ ever having had a relationship with those flows. Outside a workspace the caller
65
+ must name an explicit root; the result is still a conformant, portable package,
66
+ and it is simply not indexed. What never happens is a guess: no root declared,
67
+ nothing written.
68
+
69
+ ## What the direct route does not do
70
+
71
+ - Never creates, advances, closes or publishes a SPEC, PLAN or QUICK session or
72
+ document.
73
+ - Never initializes a workspace: an operation that needs one and does not find
74
+ it returns an explicit result.
75
+ - Never exercises an effect the descriptor does not declare, nor one that
76
+ requires approval without asking for it first.
77
+
78
+ `off` is decided per operation by the descriptor and no host, wrapper or legacy
79
+ name reverts it. `aw skills --detail` reports the live state, its evidence and
80
+ the next action.
@@ -164,6 +164,13 @@ validators and completeness. Where the two meet, Spec 014 decides the envelope
164
164
  and this one decides the payload. Duplicating either side is the failure mode
165
165
  being avoided.
166
166
 
167
+ ### How it is invoked
168
+
169
+ Both routes reach the same dispatcher and each caller has a fixed row of
170
+ operations it may ask for. That contract is stated once, in
171
+ [`CONTRACT.md`](CONTRACT.md) — the same file the installed wrapper points at.
172
+ Nothing about invocation is restated here.
173
+
167
174
  ## CLI ↔ agent split
168
175
 
169
176
  Explicit, and it is the whole point of the handshake:
@@ -0,0 +1,260 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://workline.dev/schemas/capability-descriptor.schema.json",
4
+ "title": "Workline capability descriptor v1",
5
+ "description": "The cross-cutting contract an Agent Skill declares to become invocable by Workline. Not a design format and not part of the UI Design Package catalog: it says what a capability IS — operations, inputs, outputs, context, interaction, effects, floor, degradations, off policy and retirement — for any capability, design included.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "contract_version",
10
+ "name",
11
+ "purpose",
12
+ "exposure",
13
+ "default_operation",
14
+ "operations",
15
+ "floor",
16
+ "degradations",
17
+ "compatibility"
18
+ ],
19
+ "properties": {
20
+ "contract_version": {
21
+ "description": "Version of THIS contract, not of the skill. An unknown value stops validation before any field is read.",
22
+ "const": 1
23
+ },
24
+ "name": {
25
+ "description": "The capability's only public identity. There is no parallel role ID: the binding slot and the capability are one name.",
26
+ "type": "string",
27
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
28
+ },
29
+ "purpose": {
30
+ "description": "What the capability resolves, in one sentence. Discovery and generated help derive from here rather than restating it.",
31
+ "type": "string",
32
+ "minLength": 1
33
+ },
34
+ "exposure": {
35
+ "description": "Routes the capability opens. A skill declaring neither gets no Workline surface — installing a utility does not make it a capability.",
36
+ "type": "array",
37
+ "minItems": 1,
38
+ "uniqueItems": true,
39
+ "items": { "enum": ["direct", "compose"] }
40
+ },
41
+ "default_operation": {
42
+ "description": "Operation assumed when a caller names none. Null when every invocation must be explicit.",
43
+ "type": ["string", "null"],
44
+ "pattern": "^[a-z][a-z0-9_]*$"
45
+ },
46
+ "operations": {
47
+ "description": "The finite operation catalog. Anything outside it is refused, never improvised.",
48
+ "type": "array",
49
+ "minItems": 1,
50
+ "items": {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": [
54
+ "name",
55
+ "summary",
56
+ "exposure",
57
+ "workspace",
58
+ "interaction",
59
+ "inputs",
60
+ "output",
61
+ "effects",
62
+ "off"
63
+ ],
64
+ "properties": {
65
+ "name": {
66
+ "type": "string",
67
+ "pattern": "^[a-z][a-z0-9_]*$"
68
+ },
69
+ "summary": {
70
+ "type": "string",
71
+ "minLength": 1
72
+ },
73
+ "exposure": {
74
+ "description": "Routes this operation answers on. Always a subset of the capability's own exposure.",
75
+ "type": "array",
76
+ "minItems": 1,
77
+ "uniqueItems": true,
78
+ "items": { "enum": ["direct", "compose"] }
79
+ },
80
+ "workspace": {
81
+ "description": "Whether the operation needs a Workline workspace. Being outside one returns an explicit result and never initializes Workline implicitly.",
82
+ "enum": ["required", "optional", "standalone"]
83
+ },
84
+ "interaction": {
85
+ "description": "Whether one attempt is the whole conversation, or the operation may answer `needs_input` and continue.",
86
+ "enum": ["single_pass", "needs_input"]
87
+ },
88
+ "inputs": {
89
+ "type": "array",
90
+ "items": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "required": ["name", "kind", "required", "sensitivity", "schema"],
94
+ "properties": {
95
+ "name": {
96
+ "type": "string",
97
+ "pattern": "^[a-z][a-z0-9_]*$"
98
+ },
99
+ "kind": { "enum": ["text", "reference", "attachment", "selection"] },
100
+ "required": { "type": "boolean" },
101
+ "sensitivity": {
102
+ "description": "Reading a sensitive source is never authorized by the invocation alone.",
103
+ "enum": ["public", "sensitive"]
104
+ },
105
+ "schema": {
106
+ "description": "Canonical format id when the input is schema-bearing, else null.",
107
+ "type": ["string", "null"],
108
+ "pattern": "^[a-z][a-z0-9.-]*/v[1-9][0-9]*$"
109
+ }
110
+ }
111
+ }
112
+ },
113
+ "output": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "required": ["kind", "schema", "completeness"],
117
+ "properties": {
118
+ "kind": {
119
+ "description": "A typed value, a durable reference, or both. Host prose is never the payload a flow consumes.",
120
+ "enum": ["value", "reference", "value_and_reference"]
121
+ },
122
+ "schema": {
123
+ "type": ["string", "null"],
124
+ "pattern": "^[a-z][a-z0-9.-]*/v[1-9][0-9]*$"
125
+ },
126
+ "completeness": {
127
+ "description": "Completeness values this operation may report. A dimension separate from the outcome: `completed` still requires the requested profile's completeness.",
128
+ "type": "array",
129
+ "minItems": 1,
130
+ "uniqueItems": true,
131
+ "items": { "enum": ["complete", "partial"] }
132
+ }
133
+ }
134
+ },
135
+ "effects": {
136
+ "description": "Every class of effect the operation may exercise. An undeclared effect is never exercised, so `read_only` is a declaration and not the absence of one.",
137
+ "type": "array",
138
+ "minItems": 1,
139
+ "items": {
140
+ "type": "object",
141
+ "additionalProperties": false,
142
+ "required": ["class", "idempotent", "authorization", "approval"],
143
+ "properties": {
144
+ "class": {
145
+ "enum": [
146
+ "read_only",
147
+ "local_additive",
148
+ "mutate_overwrite",
149
+ "execute",
150
+ "network_external",
151
+ "destructive"
152
+ ]
153
+ },
154
+ "idempotent": { "type": "boolean" },
155
+ "authorization": {
156
+ "description": "Granted by the invocation itself, or by a preflight the human sees first.",
157
+ "enum": ["invocation", "preflight"]
158
+ },
159
+ "approval": { "enum": ["none", "visible"] }
160
+ }
161
+ }
162
+ },
163
+ "off": {
164
+ "description": "What binding the capability `off` does to this operation. Never reverted by a host, a wrapper or a legacy name.",
165
+ "enum": ["blocked", "allowed"]
166
+ }
167
+ }
168
+ }
169
+ },
170
+ "floor": {
171
+ "description": "What runs with nothing installed. A capability a core gate needs carries its own implementation, so a missing external skill never blocks SPEC, PLAN or QUICK.",
172
+ "type": "object",
173
+ "additionalProperties": false,
174
+ "required": ["builtin", "kind", "improvements"],
175
+ "properties": {
176
+ "builtin": { "type": "boolean" },
177
+ "kind": { "enum": ["core", "feature"] },
178
+ "improvements": {
179
+ "description": "`host_selected` means the host decides which compatible improvements contribute and in what order; Workline imposes no universal precedence.",
180
+ "enum": ["host_selected", "none"]
181
+ }
182
+ }
183
+ },
184
+ "degradations": {
185
+ "description": "The observable reasons a run may fall back, and what each one does. A cause not declared here is not a degradation, it is a failure.",
186
+ "type": "array",
187
+ "items": {
188
+ "type": "object",
189
+ "additionalProperties": false,
190
+ "required": ["cause", "action"],
191
+ "properties": {
192
+ "cause": {
193
+ "enum": [
194
+ "opaque_selection",
195
+ "incompatible_improvement",
196
+ "invalid_binding",
197
+ "digest_changed"
198
+ ]
199
+ },
200
+ "action": { "enum": ["floor", "reject"] }
201
+ }
202
+ }
203
+ },
204
+ "compatibility": {
205
+ "type": "object",
206
+ "additionalProperties": false,
207
+ "required": [
208
+ "status",
209
+ "minimum_contract_version",
210
+ "improves",
211
+ "retired_names",
212
+ "retired_formats"
213
+ ],
214
+ "properties": {
215
+ "status": { "enum": ["active", "deprecated"] },
216
+ "minimum_contract_version": {
217
+ "type": "integer",
218
+ "minimum": 1
219
+ },
220
+ "improves": {
221
+ "description": "What this descriptor improves, in its OWN words. Null when the descriptor IS the capability. Installed never implies compatible: the resolution verifies this claim against the capability being resolved before the improvement contributes or produces any effect.",
222
+ "type": ["object", "null"],
223
+ "additionalProperties": false,
224
+ "required": ["capability", "operations", "contract_version"],
225
+ "properties": {
226
+ "capability": {
227
+ "type": "string",
228
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
229
+ },
230
+ "operations": {
231
+ "type": "array",
232
+ "minItems": 1,
233
+ "items": {
234
+ "type": "string",
235
+ "pattern": "^[a-z][a-z0-9_]*$"
236
+ }
237
+ },
238
+ "contract_version": {
239
+ "type": "integer",
240
+ "minimum": 1
241
+ }
242
+ }
243
+ },
244
+ "retired_names": {
245
+ "description": "Names that are NOT aliases. A binding, invocation or descriptor using one fails with guidance to adopt the live name; it never resolves silently.",
246
+ "type": "array",
247
+ "items": {
248
+ "type": "string",
249
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
250
+ }
251
+ },
252
+ "retired_formats": {
253
+ "description": "Formats unsupported as a source: never read, imported, converted or migrated, and unable to satisfy a gate. The files themselves are left intact.",
254
+ "type": "array",
255
+ "items": { "type": "string", "minLength": 1 }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }