@tacuchi/agent-workflow-cli 25.2.0 → 25.3.1

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 (61) hide show
  1. package/README.md +1 -0
  2. package/dist/application/decision-note-service.js +20 -3
  3. package/dist/application/decision-note-service.js.map +1 -1
  4. package/dist/application/elicitation-server.js +19 -3
  5. package/dist/application/elicitation-server.js.map +1 -1
  6. package/dist/application/flow/advance.js +91 -5
  7. package/dist/application/flow/advance.js.map +1 -1
  8. package/dist/application/flow/internal-actions.js +167 -7
  9. package/dist/application/flow/internal-actions.js.map +1 -1
  10. package/dist/application/flow/submit.js +187 -4
  11. package/dist/application/flow/submit.js.map +1 -1
  12. package/dist/application/plan-current-point.js +54 -0
  13. package/dist/application/plan-current-point.js.map +1 -0
  14. package/dist/application/plan-exec-decision-service.js +143 -4
  15. package/dist/application/plan-exec-decision-service.js.map +1 -1
  16. package/dist/application/plan-locator.js +78 -0
  17. package/dist/application/plan-locator.js.map +1 -0
  18. package/dist/application/plan-open-run.js +129 -0
  19. package/dist/application/plan-open-run.js.map +1 -0
  20. package/dist/application/reseal-service.js +14 -44
  21. package/dist/application/reseal-service.js.map +1 -1
  22. package/dist/application/resume-service.js +9 -3
  23. package/dist/application/resume-service.js.map +1 -1
  24. package/dist/application/settle-service.js +442 -0
  25. package/dist/application/settle-service.js.map +1 -0
  26. package/dist/application/workline-index-service.js +165 -62
  27. package/dist/application/workline-index-service.js.map +1 -1
  28. package/dist/cli/commands/index.js +2 -0
  29. package/dist/cli/commands/index.js.map +1 -1
  30. package/dist/cli/commands/settle.js +197 -0
  31. package/dist/cli/commands/settle.js.map +1 -0
  32. package/dist/cli/commands/status.js +2 -0
  33. package/dist/cli/commands/status.js.map +1 -1
  34. package/dist/cli/help-groups.js +7 -0
  35. package/dist/cli/help-groups.js.map +1 -1
  36. package/dist/cli/parser.js +6 -0
  37. package/dist/cli/parser.js.map +1 -1
  38. package/dist/domain/decision-note.js +166 -3
  39. package/dist/domain/decision-note.js.map +1 -1
  40. package/dist/domain/decision-preview.js.map +1 -1
  41. package/dist/domain/effective-contract.js +4 -3
  42. package/dist/domain/effective-contract.js.map +1 -1
  43. package/dist/domain/elicitation.js +26 -16
  44. package/dist/domain/elicitation.js.map +1 -1
  45. package/dist/domain/flow/answer.js +10 -0
  46. package/dist/domain/flow/answer.js.map +1 -1
  47. package/dist/domain/flow/authority.js +116 -0
  48. package/dist/domain/flow/authority.js.map +1 -1
  49. package/dist/domain/flow/directive.js +8 -1
  50. package/dist/domain/flow/directive.js.map +1 -1
  51. package/dist/domain/flow/run-state.js +95 -9
  52. package/dist/domain/flow/run-state.js.map +1 -1
  53. package/dist/domain/obligation-correspondence.js +95 -0
  54. package/dist/domain/obligation-correspondence.js.map +1 -0
  55. package/dist/domain/reconciliation.js +142 -25
  56. package/dist/domain/reconciliation.js.map +1 -1
  57. package/dist/domain/settlement.js +129 -0
  58. package/dist/domain/settlement.js.map +1 -0
  59. package/package.json +1 -1
  60. package/skills/w/commands/resume.md +2 -2
  61. package/skills/w/loops/plan-exec-loop/LOOP.md +31 -0
@@ -0,0 +1,129 @@
1
+ /**
2
+ * The successor of one carrier note, or `null` when it would change nothing.
3
+ *
4
+ * Everything but the settled obligations crosses over: the decision, its reason,
5
+ * the assertions it amends, its scope, its consumers and its evidence. What the
6
+ * settlement adds is the evidence each discharge produced — evidence that still
7
+ * counts is exactly what `evidence_preserved` is for — and what it removes is
8
+ * the obligations somebody actually did.
9
+ *
10
+ * `null` and not an empty note: publishing a successor identical in force to its
11
+ * predecessor would grow the chain by one record per attempt and say nothing.
12
+ */
13
+ export function deriveSettlementNote(carrier, settlements, at) {
14
+ const mine = settlements.filter((settlement) => settlement.note === carrier.id);
15
+ const failures = checkSettlements(carrier, mine);
16
+ if (failures.length > 0)
17
+ return { ok: false, failures };
18
+ const byIndex = new Map(mine.map((settlement) => [settlement.index, settlement]));
19
+ const kept = [];
20
+ const classified = [];
21
+ const settled = [];
22
+ const evidence = [];
23
+ for (const [index, obligation] of carrier.obligations.entries()) {
24
+ const settlement = byIndex.get(index);
25
+ if (settlement !== undefined && settlement.outcome === "settled") {
26
+ settled.push(obligation.text);
27
+ if (settlement.evidence !== undefined)
28
+ evidence.push(settlement.evidence);
29
+ continue;
30
+ }
31
+ const held = settlement?.outcome === "handoff" ? reclassified(obligation, "handoff") : obligation;
32
+ kept.push(held);
33
+ // Anything still unclassed leaves carrying the reading the board already
34
+ // reported FOR THAT POSITION — that is what "clasifica lo que queda" means,
35
+ // and without it the successor could not be appended at all. The position is
36
+ // the carrier's, never the survivors': dropping one shifts the rest.
37
+ classified.push(held.declared ? held : reclassified(held, at.resolved.get(index) ?? held.kind));
38
+ }
39
+ if (settled.length === 0 && sameObligations(carrier.obligations, classified)) {
40
+ return { ok: true, draft: null, settled: [] };
41
+ }
42
+ return {
43
+ ok: true,
44
+ settled,
45
+ draft: {
46
+ schema: carrier.schema,
47
+ lineage: {
48
+ spec: carrier.lineage.spec,
49
+ plan: carrier.lineage.plan,
50
+ // The settling run when there is one; the carrier's own when `aw settle`
51
+ // acts on a plan whose run is long closed. Either way it is a real
52
+ // session and a real phase, never a placeholder.
53
+ execution: { session: at.session, phase: at.phase },
54
+ },
55
+ decision: carrier.decision,
56
+ reason: carrier.reason,
57
+ supersedes_assertions: [...carrier.supersedes_assertions],
58
+ supersedes_note: carrier.id,
59
+ scope: carrier.scope,
60
+ consumers: [...carrier.consumers],
61
+ evidence_preserved: [...carrier.evidence_preserved, ...evidence],
62
+ evidence_invalidated: [...carrier.evidence_invalidated],
63
+ obligations: classified,
64
+ resume_point: carrier.resume_point,
65
+ date: at.date,
66
+ },
67
+ };
68
+ }
69
+ function reclassified(obligation, kind) {
70
+ return { text: obligation.text, kind, declared: true };
71
+ }
72
+ function sameObligations(before, after) {
73
+ return (before.length === after.length &&
74
+ before.every((obligation, index) => {
75
+ const other = after[index];
76
+ return (other !== undefined &&
77
+ other.text === obligation.text &&
78
+ other.kind === obligation.kind &&
79
+ other.declared === obligation.declared);
80
+ }));
81
+ }
82
+ /**
83
+ * Every way a settlement can fail to name real work, each with its own code.
84
+ *
85
+ * A settlement that points at an obligation the note does not carry, or that
86
+ * claims work is done without saying what proves it, is not a slightly worse
87
+ * settlement: it is a discharge nobody can audit, and the chain would record it
88
+ * as authoritative.
89
+ */
90
+ function checkSettlements(carrier, settlements) {
91
+ const failures = [];
92
+ const seen = new Set();
93
+ for (const settlement of settlements) {
94
+ const obligation = carrier.obligations[settlement.index];
95
+ if (obligation === undefined) {
96
+ failures.push({
97
+ code: "SETTLEMENT_OBLIGATION_ABSENT",
98
+ message: `${carrier.id} no tiene una obligación en la posición ${settlement.index}`,
99
+ action: `esa nota carga ${carrier.obligations.length} obligación(es): saldá una que exista`,
100
+ });
101
+ continue;
102
+ }
103
+ if (seen.has(settlement.index)) {
104
+ failures.push({
105
+ code: "SETTLEMENT_OBLIGATION_REPEATED",
106
+ message: `${carrier.id} recibe dos saldos para la misma obligación: ${obligation.text}`,
107
+ action: "una obligación se salda una vez; decidí cuál de las dos lecturas vale",
108
+ });
109
+ continue;
110
+ }
111
+ seen.add(settlement.index);
112
+ if (settlement.outcome === "settled" && (settlement.evidence ?? "").trim().length === 0) {
113
+ failures.push({
114
+ code: "SETTLEMENT_EVIDENCE_MISSING",
115
+ message: `se declara cumplida '${obligation.text}' sin decir qué lo prueba`,
116
+ action: "declará la evidencia del saldo: un comando corrido, una prueba o una inspección; sin eso no es un saldo, es una afirmación",
117
+ });
118
+ }
119
+ if (settlement.outcome !== "settled" && settlement.evidence !== undefined) {
120
+ failures.push({
121
+ code: "SETTLEMENT_EVIDENCE_UNEXPECTED",
122
+ message: `'${obligation.text}' no se declara cumplida y aun así trae evidencia`,
123
+ action: "la evidencia acredita un saldo: sacala, o declará la obligación cumplida",
124
+ });
125
+ }
126
+ }
127
+ return failures;
128
+ }
129
+ //# sourceMappingURL=settlement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlement.js","sourceRoot":"","sources":["../../src/domain/settlement.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tacuchi/agent-workflow-cli",
3
- "version": "25.2.0",
3
+ "version": "25.3.1",
4
4
  "description": "Runtime CLI for Workline — the stages + loops + artifacts system for agent work. Bundles the universal `w` skill set under `skills/w/` (slash commands `/w:*`: spec-new/spec-refine, plan-new/plan-exec, quick, persist, workspace-init, export-*); `self install --target <host>` copies SKILL + commands + hooks into the host. Pluggable capability skills resolve through `.workflow/skills.toml`. Namespace auto-detected from any `.<ns>/sessions/` dir in CWD; default `workflow`.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,10 +32,10 @@ No target → **every** pending item as `candidates` in the CLI's order, `propos
32
32
 
33
33
  ## What the CLI decides (do not re-derive)
34
34
 
35
- - **Priority**: unrefined spec → refined spec with no plan → plan not `done`; started first. A loose session is a notice, never a candidate.
35
+ - **Priority**: unrefined spec → refined spec with no plan → plan not `done` → live handoff; started first. A loose session is a notice, never a candidate.
36
36
  - **Ties**: equal priority and progress → no single recommendation; date never splits.
37
37
  - **Spec→plan link**: `Derived from` or `## Origin`, never the slug; unproven stays unplanned.
38
- - **The route**: `/w:spec-refine`, `/w:plan-new`, `/w:plan-exec`, `aw session-resume --reopen`.
38
+ - **The route**: `/w:spec-refine`, `/w:plan-new`, `/w:plan-exec`, `aw settle prepare`, `aw session-resume --reopen`.
39
39
 
40
40
  > A plan is not finished because its boxes are ticked: re-entry is the first phase not `validada`, a `bloqueada` phase with its declared reason, or — phases green, plan never closed — the final validation. One declaring `done` over open work comes back as inconsistent. An obligation leaving it neither runnable nor closable is said before its percentage.
41
41
 
@@ -151,6 +151,37 @@ run stops at it: declaring a deviation no longer carries on to the commit by its
151
151
 
152
152
  > **How an affirmation is addressed:** a decision note names the criteria it amends as `S{NNN}/AC-nn` — `NNN` from the spec file's number, `AC-nn` the label the criterion carries in the spec's checklist. The CLI **derives** that id from the label plus the file number, so the readable form the spec template writes is already addressable (a criterion that spells the full id is read the same way, never counted twice). A note amending a criterion the spec does not state **at all** is refused with `CONTRACT_ASSERTION_ABSENT`, and the exit is the spec stating it (`spec-refine`), never a second spelling of the id here.
153
153
 
154
+ ### Obligations — the two classes, and how each one is settled
155
+
156
+ A note may leave work behind, and it declares **which of two classes** each piece is. A
157
+ **compensation** is work this lineage owes: it holds the plan's closure shut until it is settled. A
158
+ **handoff** is work somebody outside the run took on: it stays listed, it stays visible after the plan
159
+ closes, and it blocks nothing — a run that cannot discharge it could never close. Nothing historical
160
+ moves: the boxes and the phase states record what happened, and the obligation is new work of the
161
+ effective contract.
162
+
163
+ The class is the agent's to state while drafting the note, and the person sees it in the sealed
164
+ preview before registering it; a new note leaving work without saying which class is refused. A note
165
+ published before the class existed is read tolerantly — an undeclared obligation is a **compensation**
166
+ unless the plan itself enumerates that exact work as a handoff — and every surface marks that as a
167
+ reading somebody supplied, never as the note's own word. The class is revocable: the
168
+ settlement boundary may declare a live compensation a handoff after all. So **when in doubt,
169
+ compensation** — the only error a later boundary still catches.
170
+
171
+ Settling one is publishing a note that **supersedes** the one carrying it without carrying it forward;
172
+ there is no second ledger of discharged obligations: one recorded outside the chain
173
+ could disagree with it. The closure does this by itself: between the last `batch-close` and
174
+ the final validation the run declares, per compensation, whether it is done and with what evidence,
175
+ and the CLI derives and publishes the settlement note. A compensation still pending leaves that
176
+ boundary open with an executable action and costs the run no attempt. With **no** open run — a plan
177
+ blocked today whose run closed long ago — the exit is `aw settle`: it lists what is owed, previews the
178
+ note, and publishes it against an approval.
179
+
180
+ **The split between scaffolding and content**, in three lines. A gap with a **single** reading is
181
+ repaired by the run itself, and the repair is recorded. A gap with **more than one** reading is asked
182
+ **once for all of them**, with the run's own reading offered as the recommendation. Everything else
183
+ is **content**, and content is the person's.
184
+
154
185
  **Eligibility is closure, never size.** The composable exit opens only when the four close: the
155
186
  divergence stays in the **same functional lineage**; its **intent is settled**, so nothing further has
156
187
  to be elicited; its **transitive impact can be enumerated**, every consumer nameable; and its