@tacuchi/agent-workflow-cli 25.2.0 → 25.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 +1 -0
- package/dist/application/decision-note-service.js +20 -3
- package/dist/application/decision-note-service.js.map +1 -1
- package/dist/application/flow/advance.js +91 -5
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/internal-actions.js +167 -7
- package/dist/application/flow/internal-actions.js.map +1 -1
- package/dist/application/flow/submit.js +187 -4
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/plan-current-point.js +54 -0
- package/dist/application/plan-current-point.js.map +1 -0
- package/dist/application/plan-exec-decision-service.js +143 -4
- package/dist/application/plan-exec-decision-service.js.map +1 -1
- package/dist/application/plan-locator.js +78 -0
- package/dist/application/plan-locator.js.map +1 -0
- package/dist/application/plan-open-run.js +129 -0
- package/dist/application/plan-open-run.js.map +1 -0
- package/dist/application/reseal-service.js +14 -44
- package/dist/application/reseal-service.js.map +1 -1
- package/dist/application/resume-service.js +9 -3
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/settle-service.js +442 -0
- package/dist/application/settle-service.js.map +1 -0
- package/dist/application/workline-index-service.js +165 -62
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/settle.js +197 -0
- package/dist/cli/commands/settle.js.map +1 -0
- package/dist/cli/commands/status.js +2 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/help-groups.js +7 -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/domain/decision-note.js +166 -3
- package/dist/domain/decision-note.js.map +1 -1
- package/dist/domain/decision-preview.js.map +1 -1
- package/dist/domain/effective-contract.js +4 -3
- package/dist/domain/effective-contract.js.map +1 -1
- package/dist/domain/flow/answer.js +10 -0
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +116 -0
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/directive.js +8 -1
- package/dist/domain/flow/directive.js.map +1 -1
- package/dist/domain/flow/run-state.js +95 -9
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/obligation-correspondence.js +95 -0
- package/dist/domain/obligation-correspondence.js.map +1 -0
- package/dist/domain/reconciliation.js +142 -25
- package/dist/domain/reconciliation.js.map +1 -1
- package/dist/domain/settlement.js +129 -0
- package/dist/domain/settlement.js.map +1 -0
- package/package.json +1 -1
- package/skills/w/commands/resume.md +2 -2
- package/skills/w/loops/plan-exec-loop/LOOP.md +31 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { correspondingPlanItem, planHandoffItems } from "./obligation-correspondence.js";
|
|
1
2
|
/**
|
|
2
3
|
* Project what the composed contract still owes.
|
|
3
4
|
*
|
|
@@ -5,46 +6,162 @@
|
|
|
5
6
|
* is the one place that already decided which notes are in force. Walking the
|
|
6
7
|
* chain again here would be a second answer to that question.
|
|
7
8
|
*/
|
|
8
|
-
export function reconciliationOf(contract, chain) {
|
|
9
|
+
export function reconciliationOf(contract, chain, planText) {
|
|
9
10
|
const resumeOf = new Map(chain.map((note) => [note.id, note.resume_point]));
|
|
11
|
+
// Read once for the whole reconciliation: every legacy obligation of one plan
|
|
12
|
+
// is judged against one reading of that plan's own enumerated handoffs.
|
|
13
|
+
const items = planText === undefined ? [] : planHandoffItems(planText);
|
|
10
14
|
const pending = [];
|
|
15
|
+
const handoffs = [];
|
|
11
16
|
for (const obligation of contract.obligations) {
|
|
12
17
|
const resume = resumeOf.get(obligation.by);
|
|
13
18
|
// An obligation whose note is not in the chain handed over cannot say where
|
|
14
19
|
// to resume, and inventing a point would send the run somewhere nobody
|
|
15
20
|
// decided. It stays pending — which is the safe half — and names its note.
|
|
16
|
-
|
|
21
|
+
const cited = obligation.declared ? null : correspondingPlanItem(obligation.text, items);
|
|
22
|
+
const entry = {
|
|
17
23
|
text: obligation.text,
|
|
18
24
|
by: obligation.by,
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
index: obligation.index,
|
|
26
|
+
declared_point: resume ?? `${obligation.by} (nota ausente de la cadena)`,
|
|
27
|
+
// A declared class is the note's own word and is never second-guessed. An
|
|
28
|
+
// undeclared one reads as a handoff only when the plan itself enumerates
|
|
29
|
+
// that exact work; anything else keeps the safe reading.
|
|
30
|
+
kind: obligation.declared ? obligation.kind : cited === null ? "compensation" : "handoff",
|
|
31
|
+
legacy: !obligation.declared,
|
|
32
|
+
...(cited === null ? {} : { corresponds_to: cited }),
|
|
33
|
+
};
|
|
34
|
+
(entry.kind === "handoff" ? handoffs : pending).push(entry);
|
|
21
35
|
}
|
|
36
|
+
return { pending, handoffs, closable: pending.length === 0 };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* WHAT A PLAN OWES AND HOW SOMEBODY GETS OUT OF IT — said once, for everybody.
|
|
40
|
+
*
|
|
41
|
+
* Three surfaces used to describe this one situation in three sets of words: the
|
|
42
|
+
* refusal that would not let the plan be sealed, the board's headline, and the
|
|
43
|
+
* action under the pipeline row. They drifted, as three texts about one fact
|
|
44
|
+
* always do — and the drift was not cosmetic. One of them sent the reader back
|
|
45
|
+
* to the point a note recorded at birth, one offered no command at all, and none
|
|
46
|
+
* of them mentioned the command that actually settles anything. So the exit is
|
|
47
|
+
* derived HERE, and each surface takes the part it renders.
|
|
48
|
+
*
|
|
49
|
+
* `null` means nothing is owed. Otherwise there is always a `command`: a refusal
|
|
50
|
+
* with no exit is a wall, and this whole phase exists because the board had one.
|
|
51
|
+
*/
|
|
52
|
+
export function obligationExit(reconciliation, context) {
|
|
53
|
+
const owed = whatIsOwed(reconciliation);
|
|
54
|
+
if (owed === null)
|
|
55
|
+
return null;
|
|
56
|
+
if (owed.repair !== undefined)
|
|
57
|
+
return unreadableExit(owed.text, owed.repair, context);
|
|
58
|
+
return owed.kind === "compensation"
|
|
59
|
+
? compensationExit(owed.text, context)
|
|
60
|
+
: handoffExit(owed.text, context);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The first thing owed, and of which class — compensation before handoff.
|
|
64
|
+
*
|
|
65
|
+
* A plan owing both is held by the compensation, so that is what its exit has to
|
|
66
|
+
* be about; the handoff is still listed underneath. And "not closable with
|
|
67
|
+
* nothing named" is the composition refusing itself — reported as the shape it
|
|
68
|
+
* is, because falling through to the handoffs there would describe a plan that
|
|
69
|
+
* cannot be read as one that merely delegated some work.
|
|
70
|
+
*/
|
|
71
|
+
function whatIsOwed(reconciliation) {
|
|
72
|
+
const [compensation] = reconciliation.pending;
|
|
73
|
+
if (compensation !== undefined) {
|
|
74
|
+
return {
|
|
75
|
+
kind: "compensation",
|
|
76
|
+
text: named(compensation, reconciliation.pending.length),
|
|
77
|
+
...(compensation.repair === undefined ? {} : { repair: compensation.repair }),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (!reconciliation.closable) {
|
|
81
|
+
return { kind: "compensation", text: "el contrato efectivo no se puede componer" };
|
|
82
|
+
}
|
|
83
|
+
const [handoff] = reconciliation.handoffs;
|
|
84
|
+
if (handoff === undefined)
|
|
85
|
+
return null;
|
|
86
|
+
return { kind: "handoff", text: named(handoff, reconciliation.handoffs.length) };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* How a surface says that a class is a READING, not the note's own word.
|
|
90
|
+
*
|
|
91
|
+
* One phrase for every surface that shows it, because two spellings of it is
|
|
92
|
+
* two answers to "did a person ratify this?" — and that question is the whole
|
|
93
|
+
* point of keeping the distinction.
|
|
94
|
+
*/
|
|
95
|
+
export function readingMark(kind) {
|
|
96
|
+
return `clase no declarada, leída ${kind === "handoff" ? "traspaso" : "compensación"}`;
|
|
97
|
+
}
|
|
98
|
+
/** `DEC-001 — revalidar F1 (+2 más)`: the cause, the work, and the rest of them. */
|
|
99
|
+
function named(obligation, total) {
|
|
100
|
+
const more = total - 1;
|
|
101
|
+
const rest = more > 0 ? ` (+${more} más)` : "";
|
|
102
|
+
// A fabricated pending has no cause to keep: its `by` is a label the
|
|
103
|
+
// projection invented for a note nobody wrote, and printing it as the author
|
|
104
|
+
// of the work would be the second wrong text about the same fact.
|
|
105
|
+
const cause = obligation.repair === undefined ? `${obligation.by} — ` : "";
|
|
106
|
+
// And an undeclared class travels as what it is. The non-blocking reading is
|
|
107
|
+
// the one most worth flagging: a legacy handoff makes the plan closable, and a
|
|
108
|
+
// board asserting it as the note's own word hides that nobody ratified it.
|
|
109
|
+
const read = obligation.legacy ? ` (${readingMark(obligation.kind)})` : "";
|
|
110
|
+
return `${cause}${obligation.text}${read}${rest}`;
|
|
111
|
+
}
|
|
112
|
+
function compensationExit(owed, context) {
|
|
113
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
114
|
+
const run = context.run;
|
|
22
115
|
return {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
116
|
+
kind: "compensation",
|
|
117
|
+
owed,
|
|
118
|
+
point: context.current_point,
|
|
119
|
+
command: run === null ? settle : run.command,
|
|
120
|
+
// With a run open the settlement rows are inside it, and the hedge is not
|
|
121
|
+
// padding: the cursor only ever grows, so a run already past them cannot go
|
|
122
|
+
// back — and for that one the exit is the command, once its journey ends.
|
|
123
|
+
action: run === null
|
|
124
|
+
? `no hay corrida abierta sobre '${context.plan}': leé y declará el saldo con '${settle}', y aplicalo con el digest que devuelve`
|
|
125
|
+
: `la sesión ${run.session} ${run.why}, y la frontera de saldo de una corrida es donde se declara la evidencia: si todavía no la pasó, seguila con '${run.command}'; si ya la pasó, la salida es '${settle}' cuando el recorrido termine`,
|
|
126
|
+
headline: `COMPENSACIÓN VIGENTE por ${owed}: retomá en ${context.current_point}, ni ejecutable ni cerrable tal cual`,
|
|
26
127
|
};
|
|
27
128
|
}
|
|
28
129
|
/**
|
|
29
|
-
*
|
|
130
|
+
* The exit of a lineage nobody can read — the repair, and nothing about phases.
|
|
30
131
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
132
|
+
* `point` carries the plan's current point anyway, because a caller may still
|
|
133
|
+
* want to say where the plan stands; what changes is that no TEXT offers it,
|
|
134
|
+
* since a broken chain is not fixed by going back to a phase. The old board
|
|
135
|
+
* printed `retomá en <repair>` — the right instruction under the wrong label —
|
|
136
|
+
* and F4's rule that a declared point never reaches a surface would have dropped
|
|
137
|
+
* it altogether: the one actionable sentence in the whole situation.
|
|
35
138
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
139
|
+
function unreadableExit(owed, repair, context) {
|
|
140
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
141
|
+
const run = context.run;
|
|
142
|
+
return {
|
|
143
|
+
kind: "compensation",
|
|
144
|
+
owed,
|
|
145
|
+
point: context.current_point,
|
|
146
|
+
command: run === null ? settle : run.command,
|
|
147
|
+
action: `${repair}. Después de eso el linaje vuelve a leerse${run === null
|
|
148
|
+
? `, y la salida es '${settle}'`
|
|
149
|
+
: `, y la sesión ${run.session} —que ${run.why}— sigue con '${run.command}'`}`,
|
|
150
|
+
headline: `LINAJE ILEGIBLE por ${owed} — ${repair}: ni ejecutable ni cerrable tal cual`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function handoffExit(owed, context) {
|
|
154
|
+
const settle = `aw settle prepare ${context.plan}`;
|
|
155
|
+
const run = context.run;
|
|
156
|
+
return {
|
|
157
|
+
kind: "handoff",
|
|
158
|
+
owed,
|
|
159
|
+
point: context.current_point,
|
|
160
|
+
command: run === null ? settle : run.command,
|
|
161
|
+
action: run === null
|
|
162
|
+
? `el traspaso no bloquea nada: reconocelo con '${settle}', y saldalo ahí mismo cuando el trabajo de afuera esté hecho`
|
|
163
|
+
: `el traspaso no bloquea nada: la sesión ${run.session} ${run.why}, así que lo ve en la frontera de saldo de esa corrida; fuera de una corrida se reconoce con '${settle}'`,
|
|
164
|
+
headline: `TRASPASO VIGENTE por ${owed}: es trabajo de afuera y no bloquea el cierre; el plan está en ${context.current_point}`,
|
|
165
|
+
};
|
|
49
166
|
}
|
|
50
167
|
//# sourceMappingURL=reconciliation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconciliation.js","sourceRoot":"","sources":["../../src/domain/reconciliation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reconciliation.js","sourceRoot":"","sources":["../../src/domain/reconciliation.ts"],"names":[],"mappings":"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"}
|
|
@@ -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.
|
|
3
|
+
"version": "25.3.0",
|
|
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
|
|
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
|