@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.
- package/README.md +3 -2
- package/dist/adapters/git-cli.js +12 -7
- package/dist/adapters/git-cli.js.map +1 -1
- package/dist/application/capability/compose.js +161 -0
- package/dist/application/capability/compose.js.map +1 -0
- package/dist/application/capability/descriptor-loader.js +109 -0
- package/dist/application/capability/descriptor-loader.js.map +1 -0
- package/dist/application/capability/design-handler.js +299 -0
- package/dist/application/capability/design-handler.js.map +1 -0
- package/dist/application/capability/dispatcher.js +312 -0
- package/dist/application/capability/dispatcher.js.map +1 -0
- package/dist/application/capability/durable-effect.js +220 -0
- package/dist/application/capability/durable-effect.js.map +1 -0
- package/dist/application/capability/installed-inventory.js +168 -0
- package/dist/application/capability/installed-inventory.js.map +1 -0
- package/dist/application/capability/readiness.js +204 -0
- package/dist/application/capability/readiness.js.map +1 -0
- package/dist/application/capability/resolution.js +264 -0
- package/dist/application/capability/resolution.js.map +1 -0
- package/dist/application/capability/wrapper.js +195 -0
- package/dist/application/capability/wrapper.js.map +1 -0
- package/dist/application/context/manifest.js +11 -5
- package/dist/application/context/manifest.js.map +1 -1
- package/dist/application/context/measure.js +5 -2
- package/dist/application/context/measure.js.map +1 -1
- package/dist/application/context/plan-service.js +6 -6
- package/dist/application/context/plan-service.js.map +1 -1
- package/dist/application/design/design-bundle-service.js +148 -0
- package/dist/application/design/design-bundle-service.js.map +1 -0
- package/dist/application/design/design-proposal-service.js +69 -0
- package/dist/application/design/design-proposal-service.js.map +1 -0
- package/dist/application/design/design-publish-service.js +275 -7
- package/dist/application/design/design-publish-service.js.map +1 -1
- package/dist/application/design/design-record-service.js +100 -0
- package/dist/application/design/design-record-service.js.map +1 -0
- package/dist/application/flow/advance.js +533 -0
- package/dist/application/flow/advance.js.map +1 -0
- package/dist/application/flow/flow-service.js +65 -0
- package/dist/application/flow/flow-service.js.map +1 -0
- package/dist/application/flow/run-projection.js +80 -0
- package/dist/application/flow/run-projection.js.map +1 -0
- package/dist/application/flow/run-state-service.js +107 -0
- package/dist/application/flow/run-state-service.js.map +1 -0
- package/dist/application/flow/submit.js +423 -0
- package/dist/application/flow/submit.js.map +1 -0
- package/dist/application/markdown.js +16 -2
- package/dist/application/markdown.js.map +1 -1
- package/dist/application/resume-service.js +23 -10
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/self/hooks-toml.js +137 -17
- package/dist/application/self/hooks-toml.js.map +1 -1
- package/dist/application/self/host-states.js +87 -1
- package/dist/application/self/host-states.js.map +1 -1
- package/dist/application/self/install-hooks.js +62 -6
- package/dist/application/self/install-hooks.js.map +1 -1
- package/dist/application/self/install-skill.js +37 -6
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/uninstall.js +21 -0
- package/dist/application/self/uninstall.js.map +1 -1
- package/dist/application/skills-resolver-service.js +8 -2
- package/dist/application/skills-resolver-service.js.map +1 -1
- package/dist/application/status-service.js +4 -1
- package/dist/application/status-service.js.map +1 -1
- package/dist/application/workline-index-service.js +15 -2
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/application/workspace-init-service.js +13 -1
- package/dist/application/workspace-init-service.js.map +1 -1
- package/dist/cli/commands/capability.js +182 -0
- package/dist/cli/commands/capability.js.map +1 -0
- package/dist/cli/commands/flow.js +71 -0
- package/dist/cli/commands/flow.js.map +1 -0
- package/dist/cli/commands/index.js +4 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/skills.js +55 -2
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/status.js +5 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/help-groups.js +6 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/parser.js +6 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/tui/components/host-admin-section.js +14 -2
- package/dist/cli/tui/components/host-admin-section.js.map +1 -1
- package/dist/cli/tui/data/workflow-content.js +13 -1
- package/dist/cli/tui/data/workflow-content.js.map +1 -1
- package/dist/cli/tui/tabs/workflow-tab.js +8 -1
- package/dist/cli/tui/tabs/workflow-tab.js.map +1 -1
- package/dist/domain/capability/descriptor.js +553 -0
- package/dist/domain/capability/descriptor.js.map +1 -0
- package/dist/domain/capability/effects.js +90 -0
- package/dist/domain/capability/effects.js.map +1 -0
- package/dist/domain/capability/protocol.js +494 -0
- package/dist/domain/capability/protocol.js.map +1 -0
- package/dist/domain/contract-reader.js +84 -0
- package/dist/domain/contract-reader.js.map +1 -0
- package/dist/domain/design/adapter.js +161 -0
- package/dist/domain/design/adapter.js.map +1 -0
- package/dist/domain/design/artifact.js +148 -4
- package/dist/domain/design/artifact.js.map +1 -1
- package/dist/domain/design/capability.js +263 -4
- package/dist/domain/design/capability.js.map +1 -1
- package/dist/domain/design/direct.js +108 -0
- package/dist/domain/design/direct.js.map +1 -0
- package/dist/domain/design/external-send.js +65 -0
- package/dist/domain/design/external-send.js.map +1 -0
- package/dist/domain/design/maturity.js +71 -0
- package/dist/domain/design/maturity.js.map +1 -1
- package/dist/domain/design/offline.js +92 -0
- package/dist/domain/design/offline.js.map +1 -0
- package/dist/domain/design/profiles.js +212 -0
- package/dist/domain/design/profiles.js.map +1 -0
- package/dist/domain/design/proposal.js +234 -0
- package/dist/domain/design/proposal.js.map +1 -0
- package/dist/domain/design/render-bundle.js +0 -0
- package/dist/domain/design/render-bundle.js.map +1 -0
- package/dist/domain/design/rendition.js +472 -0
- package/dist/domain/design/rendition.js.map +1 -0
- package/dist/domain/design/sources.js +180 -0
- package/dist/domain/design/sources.js.map +1 -0
- package/dist/domain/design/validation.js +12 -68
- package/dist/domain/design/validation.js.map +1 -1
- package/dist/domain/design/visual-evidence.js +155 -0
- package/dist/domain/design/visual-evidence.js.map +1 -0
- package/dist/domain/flow/answer.js +459 -0
- package/dist/domain/flow/answer.js.map +1 -0
- package/dist/domain/flow/authority.js +2338 -0
- package/dist/domain/flow/authority.js.map +1 -0
- package/dist/domain/flow/authorization.js +62 -0
- package/dist/domain/flow/authorization.js.map +1 -0
- package/dist/domain/flow/directive.js +421 -0
- package/dist/domain/flow/directive.js.map +1 -0
- package/dist/domain/flow/rules.js +140 -0
- package/dist/domain/flow/rules.js.map +1 -0
- package/dist/domain/flow/run-state.js +317 -0
- package/dist/domain/flow/run-state.js.map +1 -0
- package/dist/domain/harnesses.js +124 -4
- package/dist/domain/harnesses.js.map +1 -1
- package/dist/domain/host-verification.js +8 -8
- package/dist/domain/skills.js +13 -14
- package/dist/domain/skills.js.map +1 -1
- package/dist/domain/structured-choice-stamp.js +106 -0
- package/dist/domain/structured-choice-stamp.js.map +1 -0
- package/package.json +1 -1
- package/skills/w/SKILL.md +5 -5
- package/skills/w/context/MANIFEST.json +42 -1
- package/skills/w/harness/HARNESS.md +30 -4
- package/skills/w/loops/CHASSIS.md +11 -20
- package/skills/w/loops/CODE-POLICIES.md +9 -15
- package/skills/w/loops/plan-exec-loop/LOOP.md +11 -13
- package/skills/w/loops/plan-new-loop/LOOP.md +6 -4
- package/skills/w/loops/plan-refine-loop/LOOP.md +5 -3
- package/skills/w/loops/quick-loop/LOOP.md +18 -26
- package/skills/w/loops/spec-refine-loop/LOOP.md +14 -18
- package/skills/w/modules/COMPACTION.md +2 -6
- package/skills/w/modules/DB-SCRIPTS-ONLY.md +2 -0
- package/skills/w/modules/DESIGN-REFERENCES.md +15 -11
- package/skills/w/modules/IDEATION-GATE.md +3 -3
- package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +17 -36
- package/skills/w/modules/PLAN-INPUT.md +5 -3
- package/skills/w/modules/PLAN-REFINE-SPLIT.md +3 -1
- package/skills/w/modules/PLAN-SPLIT-GATE.md +7 -5
- package/skills/w/modules/PROMPT-CONTINUITY.md +3 -1
- package/skills/w/modules/SPEC-CHANGE-SHAPE.md +4 -4
- package/skills/w/roles/README.md +2 -0
- package/skills/w/roles/design/CONTRACT.md +80 -0
- package/skills/w/roles/design/ROLE.md +7 -0
- package/skills/w/schemas/capability-descriptor.schema.json +260 -0
- package/skills/w/schemas/design/design-render-bundle.v1.schema.json +191 -0
- package/skills/w/schemas/design/design-rendition.v1.schema.json +232 -0
- 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
|
|
30
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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**
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
- **
|
|
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
|
|
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
|
-
>
|
|
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 |
|
|
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
|
-
|
|
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
|
-
> **
|
|
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
|
|
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
|
|
package/skills/w/roles/README.md
CHANGED
|
@@ -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
|
+
}
|