@tacuchi/agent-workflow-cli 25.1.2 → 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 +3 -1
- package/dist/adapters/node-process.js +35 -0
- package/dist/adapters/node-process.js.map +1 -1
- package/dist/application/amend-service.js +393 -0
- package/dist/application/amend-service.js.map +1 -0
- package/dist/application/decision-note-service.js +20 -3
- package/dist/application/decision-note-service.js.map +1 -1
- package/dist/application/doctor/actions.js +158 -0
- package/dist/application/doctor/actions.js.map +1 -0
- package/dist/application/doctor/apply.js +399 -0
- package/dist/application/doctor/apply.js.map +1 -0
- package/dist/application/doctor/auth-dsn.js +143 -0
- package/dist/application/doctor/auth-dsn.js.map +1 -0
- package/dist/application/doctor/auth-flow.js +28 -0
- package/dist/application/doctor/auth-flow.js.map +1 -0
- package/dist/application/doctor/auth-registry.js +12 -0
- package/dist/application/doctor/auth-registry.js.map +1 -0
- package/dist/application/doctor/hosts.js +41 -0
- package/dist/application/doctor/hosts.js.map +1 -0
- package/dist/application/doctor/native-host-state.js +211 -0
- package/dist/application/doctor/native-host-state.js.map +1 -0
- package/dist/application/doctor/prepare.js +262 -0
- package/dist/application/doctor/prepare.js.map +1 -0
- package/dist/application/doctor/provider-installation.js +124 -0
- package/dist/application/doctor/provider-installation.js.map +1 -0
- package/dist/application/doctor/provider-mcps.js +650 -0
- package/dist/application/doctor/provider-mcps.js.map +1 -0
- package/dist/application/doctor/provider-plugins-hooks.js +112 -0
- package/dist/application/doctor/provider-plugins-hooks.js.map +1 -0
- package/dist/application/doctor/provider-skills.js +212 -0
- package/dist/application/doctor/provider-skills.js.map +1 -0
- package/dist/application/doctor/provider-tools-auth.js +201 -0
- package/dist/application/doctor/provider-tools-auth.js.map +1 -0
- package/dist/application/doctor/provider-visibility.js +149 -0
- package/dist/application/doctor/provider-visibility.js.map +1 -0
- package/dist/application/doctor/repair-runner.js +169 -0
- package/dist/application/doctor/repair-runner.js.map +1 -0
- package/dist/application/doctor/report.js +155 -0
- package/dist/application/doctor/report.js.map +1 -0
- package/dist/application/doctor/types.js +5 -0
- package/dist/application/doctor/types.js.map +1 -0
- package/dist/application/flow/advance.js +152 -13
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/flow-service.js +18 -7
- package/dist/application/flow/flow-service.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/run-projection.js +6 -1
- package/dist/application/flow/run-projection.js.map +1 -1
- package/dist/application/flow/submit.js +330 -7
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/mcp-doctor-service.js +1 -1
- package/dist/application/mcp-doctor-service.js.map +1 -1
- package/dist/application/mcp-host-reader.js +134 -26
- package/dist/application/mcp-host-reader.js.map +1 -1
- package/dist/application/mcp-host-receipt-service.js +9 -7
- package/dist/application/mcp-host-receipt-service.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/self/install-skill.js +10 -2
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/mcp-config.js +1 -1
- package/dist/application/self/mcp-config.js.map +1 -1
- package/dist/application/session-narrative.js +15 -0
- package/dist/application/session-narrative.js.map +1 -1
- package/dist/application/settle-service.js +442 -0
- package/dist/application/settle-service.js.map +1 -0
- package/dist/application/source-boundary-policy.js +87 -6
- package/dist/application/source-boundary-policy.js.map +1 -1
- package/dist/application/workline-index-service.js +165 -62
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/cli/commands/amend.js +122 -0
- package/dist/cli/commands/amend.js.map +1 -0
- package/dist/cli/commands/doctor.js +300 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.js +6 -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/dispatch-plan.js +47 -0
- package/dist/cli/dispatch-plan.js.map +1 -0
- package/dist/cli/help-groups.js +15 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +54 -10
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/parser.js +26 -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/doctor/auth.js +65 -0
- package/dist/domain/doctor/auth.js.map +1 -0
- package/dist/domain/doctor/model.js +82 -0
- package/dist/domain/doctor/model.js.map +1 -0
- package/dist/domain/doctor/operations.js +114 -0
- package/dist/domain/doctor/operations.js.map +1 -0
- 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 +124 -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 +276 -34
- 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/redaction.js +40 -0
- package/dist/domain/redaction.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/SKILL.md +2 -1
- package/skills/w/commands/README.md +2 -1
- package/skills/w/commands/doctor.md +31 -0
- package/skills/w/commands/resume.md +2 -2
- package/skills/w/context/MANIFEST.json +4 -0
- package/skills/w/loops/plan-exec-loop/LOOP.md +31 -0
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aw settle`: saldar las obligaciones de un plan que ya no tiene recorrido abierto.
|
|
3
|
+
*
|
|
4
|
+
* The closure of a `plan-exec` run settles its own obligations, and that is the
|
|
5
|
+
* ordinary path. This is the other half: a plan blocked TODAY, in a workspace
|
|
6
|
+
* where the run that created the obligation closed months ago. Before this, the
|
|
7
|
+
* only way out was writing `docs/decisions/` by hand — the exact surgery the
|
|
8
|
+
* scaffolding exists to make unnecessary.
|
|
9
|
+
*
|
|
10
|
+
* CROSS-CUTTING, like `reseal` and the retirement pair: it opens no flow and
|
|
11
|
+
* creates no session. And it has `reseal`'s two steps for `reseal`'s reason —
|
|
12
|
+
* a person ASSERTS something between them: that the compensatory work was done,
|
|
13
|
+
* or that it was somebody else's all along. `prepare` shows what each settlement
|
|
14
|
+
* would publish and the digest that authorizes it; `apply` re-derives everything
|
|
15
|
+
* from the live workspace, demands that digest back, and publishes under the
|
|
16
|
+
* lock. Two steps, and never one more: `list` is the same reading without a seal.
|
|
17
|
+
*
|
|
18
|
+
* What it never does is compete with a run. A `plan-exec` run holding this plan
|
|
19
|
+
* owns its closure, and settling underneath it would publish a note the run's
|
|
20
|
+
* own boundary is about to derive. So the command refuses and names the run.
|
|
21
|
+
*/
|
|
22
|
+
import { basename, join } from "node:path";
|
|
23
|
+
import { composeEffectiveContract } from "../domain/effective-contract.js";
|
|
24
|
+
import { specBaselineDigest } from "../domain/lineage.js";
|
|
25
|
+
import { reconciliationOf } from "../domain/reconciliation.js";
|
|
26
|
+
import { deriveSettlementNote } from "../domain/settlement.js";
|
|
27
|
+
import { noteIndexPath, readNoteIndex } from "./decision-note-service.js";
|
|
28
|
+
import { DEFAULT_DOCS_CANON, resolveCoreDocsCanon } from "./docs-canon-service.js";
|
|
29
|
+
import { functionalSpecDigest } from "./parsers/spec-functional.js";
|
|
30
|
+
import { parseDerivedFromPath, parseSpecCriteria, parseSpecRelation, } from "./parsers/spec-relation.js";
|
|
31
|
+
import { resolveWorkspaceRoot } from "./paths-service.js";
|
|
32
|
+
import { currentResumePoint } from "./plan-current-point.js";
|
|
33
|
+
import { settlePlanExecObligations } from "./plan-exec-decision-service.js";
|
|
34
|
+
import { locatePlanDocument } from "./plan-locator.js";
|
|
35
|
+
import { holdingRunOf, readHoldingRuns } from "./plan-open-run.js";
|
|
36
|
+
import { semanticDigest } from "./semantic-operation/protocol.js";
|
|
37
|
+
function fail(code, message, action) {
|
|
38
|
+
return { status: "failed", failure: { code, message, action } };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* What a plan still owes, read and reported without writing anything.
|
|
42
|
+
*
|
|
43
|
+
* Read-only so it is safe to run on the wrong plan — which is what somebody
|
|
44
|
+
* about to assert "this work was done" needs. It is also the first half of both
|
|
45
|
+
* other verbs: the listing a person reads, the successors they approve and the
|
|
46
|
+
* notes `apply` publishes are three views of ONE derivation.
|
|
47
|
+
*/
|
|
48
|
+
export async function listSettle(fs, env, paths, target) {
|
|
49
|
+
const read = await readLineage(fs, env, paths, target);
|
|
50
|
+
if ("failure" in read)
|
|
51
|
+
return read;
|
|
52
|
+
return { status: "listed", listing: read.listing };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Derive every successor and seal what approving them authorizes.
|
|
56
|
+
*
|
|
57
|
+
* With no declarations it is `list` with another name, and that is deliberate:
|
|
58
|
+
* the first thing anybody does is look, and making them approve a seal in order
|
|
59
|
+
* to see what they owe would be a confirmation over nothing.
|
|
60
|
+
*/
|
|
61
|
+
export async function prepareSettle(fs, env, paths, target, declarations) {
|
|
62
|
+
const read = await readLineage(fs, env, paths, target);
|
|
63
|
+
if ("failure" in read)
|
|
64
|
+
return read;
|
|
65
|
+
const { listing, chain, baseline, planText } = read;
|
|
66
|
+
// La misma lectura que el tablero proyecta: si dos superficies contestaran por
|
|
67
|
+
// su cuenta «hay una corrida sobre este plan», una de las dos se equivocaría.
|
|
68
|
+
const open = holdingRunOf(await readHoldingRuns(fs, paths), listing.plan);
|
|
69
|
+
if (open !== null) {
|
|
70
|
+
return fail("SETTLE_RUN_OPEN", `la sesión ${open.session} ${open.why}`, `seguí esa corrida con '${open.command}'; 'aw settle' es la salida cuando NO hay recorrido abierto`);
|
|
71
|
+
}
|
|
72
|
+
const declared = parseDeclarations(declarations, listing);
|
|
73
|
+
if ("failure" in declared)
|
|
74
|
+
return declared;
|
|
75
|
+
// With nothing declared this IS `list`, whatever the plan owes: making
|
|
76
|
+
// somebody approve a seal in order to see what they owe would be a
|
|
77
|
+
// confirmation over nothing, and failing when they owe nothing would make the
|
|
78
|
+
// two verbs disagree about the same plan.
|
|
79
|
+
if (declared.value.length === 0)
|
|
80
|
+
return { status: "listed", listing };
|
|
81
|
+
const planned = plannedFor(chain, declared.value, listing);
|
|
82
|
+
if ("failure" in planned)
|
|
83
|
+
return planned;
|
|
84
|
+
// The seal covers WHAT WAS SHOWN and the bytes it was read from: the plan, the
|
|
85
|
+
// chain and every successor. Any of the three moving makes the approval stop
|
|
86
|
+
// fitting, which is what keeps a `plan-exec` publication in flight from being
|
|
87
|
+
// overwritten by a yes given over an older reading.
|
|
88
|
+
const sealed = semanticDigest({
|
|
89
|
+
operation: "settle.obligations",
|
|
90
|
+
plan: listing.plan,
|
|
91
|
+
plan_digest: specBaselineDigest(planText),
|
|
92
|
+
spec_digest: baseline.digest,
|
|
93
|
+
chain: chain.map((note) => note.digest),
|
|
94
|
+
planned: planned.value,
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
status: "prepared",
|
|
98
|
+
listing,
|
|
99
|
+
planned: planned.value,
|
|
100
|
+
digest: sealed,
|
|
101
|
+
next: applyCommand(listing.plan, declarations, sealed),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Publish exactly what was previewed, or nothing at all.
|
|
106
|
+
*
|
|
107
|
+
* The preparation runs AGAIN from the live workspace and the approval is
|
|
108
|
+
* compared against what THAT produces — never against the digest a preview
|
|
109
|
+
* handed back, which may describe a workspace that no longer exists. What
|
|
110
|
+
* publishes is `settlePlanExecObligations`, the same path the closure of a run
|
|
111
|
+
* takes, so the two cannot disagree about what a settlement writes.
|
|
112
|
+
*/
|
|
113
|
+
export async function applySettle(fs, env, paths, input) {
|
|
114
|
+
const prepared = await prepareSettle(fs, env, paths, input.target, input.declarations);
|
|
115
|
+
if (prepared.status === "failed")
|
|
116
|
+
return prepared;
|
|
117
|
+
if (prepared.status === "listed") {
|
|
118
|
+
return fail("SETTLE_DECLARATION_INVALID", "no se declaró ningún saldo: no hay nada que aplicar", `corré 'aw settle prepare ${prepared.listing.plan}' con --settle, --handoff o --pending y aprobá el digest que muestra`);
|
|
119
|
+
}
|
|
120
|
+
if (input.approval.trim() !== prepared.digest) {
|
|
121
|
+
return fail("SETTLE_APPROVAL_MISMATCH", "lo aprobado no es lo que se publicaría: el plan, su spec o su cadena cambiaron desde la vista previa", `volvé a correr 'aw settle prepare ${prepared.listing.plan}' con las mismas declaraciones, leé la vista previa vigente y aprobá ese digest`);
|
|
122
|
+
}
|
|
123
|
+
const root = await resolveWorkspaceRoot(fs, env, paths);
|
|
124
|
+
const declared = parseDeclarations(input.declarations, prepared.listing);
|
|
125
|
+
if ("failure" in declared)
|
|
126
|
+
return declared;
|
|
127
|
+
const settled = await settlePlanExecObligations(fs, paths, {
|
|
128
|
+
root,
|
|
129
|
+
// No run acts here, so each successor records the lineage of the note it
|
|
130
|
+
// supersedes: a real session and a real phase, never a placeholder and never
|
|
131
|
+
// another carrier's.
|
|
132
|
+
execution: (carrier) => ({
|
|
133
|
+
session: carrier.lineage.execution.session,
|
|
134
|
+
phase: carrier.lineage.execution.phase,
|
|
135
|
+
}),
|
|
136
|
+
plan: prepared.listing.plan,
|
|
137
|
+
date: new Date().toISOString().slice(0, 10),
|
|
138
|
+
declarations: declared.value,
|
|
139
|
+
});
|
|
140
|
+
if (!settled.ok) {
|
|
141
|
+
return {
|
|
142
|
+
status: "failed",
|
|
143
|
+
failure: {
|
|
144
|
+
code: settled.failure.code,
|
|
145
|
+
message: settled.failure.message,
|
|
146
|
+
action: settled.failure.action,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
status: "applied",
|
|
152
|
+
listing: prepared.listing,
|
|
153
|
+
published: settled.published.map((note) => note.id),
|
|
154
|
+
settled: settled.settled,
|
|
155
|
+
reconciliation: settled.reconciliation,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
async function readLineage(fs, env, paths, target) {
|
|
159
|
+
const root = await resolveWorkspaceRoot(fs, env, paths);
|
|
160
|
+
const canon = await resolveCoreDocsCanon(fs, paths);
|
|
161
|
+
if (!canon.ok) {
|
|
162
|
+
return fail("SETTLE_DOCS_CANON_INVALID", `no se puede ubicar el plan: ${canon.error}`, "corregí [docs] para conservar el layout canónico y volvé a leer las obligaciones");
|
|
163
|
+
}
|
|
164
|
+
const located = await locatePlanDocument(fs, root, canon.canon.plan, target, {
|
|
165
|
+
outside: "un saldo se lee y se publica sobre un plan, y sobre nada más",
|
|
166
|
+
ambiguous: "pasá la ruta exacta del plan cuyas obligaciones querés saldar",
|
|
167
|
+
});
|
|
168
|
+
if (!located.ok) {
|
|
169
|
+
const code = located.reason === "absent"
|
|
170
|
+
? "SETTLE_PLAN_ABSENT"
|
|
171
|
+
: located.reason === "ambiguous"
|
|
172
|
+
? "SETTLE_TARGET_AMBIGUOUS"
|
|
173
|
+
: "SETTLE_TARGET_INVALID";
|
|
174
|
+
return fail(code, located.message, located.action);
|
|
175
|
+
}
|
|
176
|
+
const planPath = located.path;
|
|
177
|
+
const documents = await readDocuments(fs, root, planPath, canon.canon.plan);
|
|
178
|
+
if ("failure" in documents)
|
|
179
|
+
return documents;
|
|
180
|
+
const { planText, specPath, specText, relation } = documents;
|
|
181
|
+
const slug = specSlug(specPath, relation.number);
|
|
182
|
+
if (slug === null) {
|
|
183
|
+
// Degrading to an index path that cannot exist would answer "this plan owes
|
|
184
|
+
// nothing" — a clean bill of health on the exact question the command
|
|
185
|
+
// answers — over a chain that is sitting right there under another name.
|
|
186
|
+
return fail("SETTLE_PLAN_LINEAGE_UNDECLARED", `'${specPath}' no expone el slug de la spec: no se puede ubicar su cadena de decisiones`, "normalizá el nombre de la spec a 'NNN-spec-<slug>.md' y volvé a leer las obligaciones");
|
|
187
|
+
}
|
|
188
|
+
const baseline = {
|
|
189
|
+
path: specPath,
|
|
190
|
+
number: relation.number,
|
|
191
|
+
digest: functionalSpecDigest(specText),
|
|
192
|
+
legacy_digest: specBaselineDigest(specText),
|
|
193
|
+
criteria: parseSpecCriteria(specText, relation.number),
|
|
194
|
+
};
|
|
195
|
+
const chain = await readNoteIndex(fs, root, noteIndexPath(DEFAULT_DOCS_CANON.decision, relation.number, slug), { path: specPath, number: relation.number });
|
|
196
|
+
if (!chain.ok)
|
|
197
|
+
return verbatim(chain.failures[0], "la cadena de decisiones no se puede leer");
|
|
198
|
+
const composed = composeEffectiveContract(baseline, chain.read.index.notes);
|
|
199
|
+
if (composed.status === "blocked") {
|
|
200
|
+
return verbatim(composed.failures[0], "el contrato efectivo no compone");
|
|
201
|
+
}
|
|
202
|
+
const reading = reconciliationOf(composed.contract, chain.read.index.notes, planText);
|
|
203
|
+
// THE CHAIN IS PER SPEC, AND A SPEC MAY HAVE SEVERAL PLANS. So the obligations
|
|
204
|
+
// of this plan are the ones whose note pinned THIS plan, and nobody else's.
|
|
205
|
+
// Without the filter, naming any plan of the lineage settled its siblings'
|
|
206
|
+
// obligations — under a live run holding one of them, because the open-run
|
|
207
|
+
// guard only ever compares the plan that was named — and it read their class
|
|
208
|
+
// against a handoff section they never had.
|
|
209
|
+
const mine = new Set(chain.read.index.notes
|
|
210
|
+
.filter((note) => note.lineage.plan.path === planPath)
|
|
211
|
+
.map((note) => note.id));
|
|
212
|
+
const project = (obligations) => obligations
|
|
213
|
+
.filter((obligation) => mine.has(obligation.by))
|
|
214
|
+
.map((obligation) => ({
|
|
215
|
+
note: obligation.by,
|
|
216
|
+
index: obligation.index,
|
|
217
|
+
text: obligation.text,
|
|
218
|
+
kind: obligation.kind,
|
|
219
|
+
legacy: obligation.legacy,
|
|
220
|
+
corresponds_to: obligation.corresponds_to ?? null,
|
|
221
|
+
declared_point: obligation.declared_point,
|
|
222
|
+
}));
|
|
223
|
+
return {
|
|
224
|
+
chain: chain.read.index.notes,
|
|
225
|
+
baseline,
|
|
226
|
+
planText,
|
|
227
|
+
listing: {
|
|
228
|
+
plan: planPath,
|
|
229
|
+
spec: specPath,
|
|
230
|
+
compensations: project(reading.pending),
|
|
231
|
+
handoffs: project(reading.handoffs),
|
|
232
|
+
closable: reading.closable,
|
|
233
|
+
current_point: currentResumePoint(planText),
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// ── the declarations ─────────────────────────────────────────────────────────
|
|
238
|
+
const REFERENCE = /^(DEC-(?:[0-9]{3}|[1-9][0-9]{3,}))\[(\d+)\]$/;
|
|
239
|
+
/**
|
|
240
|
+
* Parse `DEC-001[0]` and `DEC-001[0]=<evidencia>` into settlements.
|
|
241
|
+
*
|
|
242
|
+
* Every reference is checked against what the plan REALLY owes, and a reference
|
|
243
|
+
* that names something else is refused rather than ignored: a settlement silently
|
|
244
|
+
* dropped would report success over work nobody discharged.
|
|
245
|
+
*/
|
|
246
|
+
function parseDeclarations(declarations, listing) {
|
|
247
|
+
const out = [];
|
|
248
|
+
const seen = new Set();
|
|
249
|
+
const entries = [
|
|
250
|
+
["settled", declarations.settle],
|
|
251
|
+
["handoff", declarations.handoff],
|
|
252
|
+
["pending", declarations.pending],
|
|
253
|
+
];
|
|
254
|
+
for (const [outcome, raw] of entries) {
|
|
255
|
+
for (const item of raw) {
|
|
256
|
+
const parsed = parseDeclaration(item, outcome, listing, seen);
|
|
257
|
+
if ("failure" in parsed)
|
|
258
|
+
return parsed;
|
|
259
|
+
seen.add(`${parsed.value.note}[${parsed.value.index}]`);
|
|
260
|
+
out.push(parsed.value);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { value: out };
|
|
264
|
+
}
|
|
265
|
+
/** One `DEC-NNN[i]` or `DEC-NNN[i]=<evidencia>`, checked against what is owed. */
|
|
266
|
+
function parseDeclaration(item, outcome, listing, seen) {
|
|
267
|
+
const [reference, ...rest] = item.split("=");
|
|
268
|
+
const evidence = rest.join("=").trim();
|
|
269
|
+
const match = REFERENCE.exec((reference ?? "").trim());
|
|
270
|
+
if (match === null) {
|
|
271
|
+
return fail("SETTLE_DECLARATION_INVALID", `'${item}' no nombra una obligación: se escribe DEC-NNN[posición]${outcome === "settled" ? "=<evidencia>" : ""}`, `'aw settle list ${listing.plan}' enumera las obligaciones vigentes con su nota y su posición`);
|
|
272
|
+
}
|
|
273
|
+
const note = match[1];
|
|
274
|
+
const index = Number(match[2]);
|
|
275
|
+
const key = `${note}[${index}]`;
|
|
276
|
+
if (seen.has(key)) {
|
|
277
|
+
return fail("SETTLE_DECLARATION_INVALID", `${key} se declara dos veces`, "una obligación se salda una vez: decidí cuál de las dos lecturas vale");
|
|
278
|
+
}
|
|
279
|
+
const owed = [...listing.compensations, ...listing.handoffs];
|
|
280
|
+
if (!owed.some((obligation) => obligation.note === note && obligation.index === index)) {
|
|
281
|
+
return fail("SETTLE_OBLIGATION_UNKNOWN", `${key} no es una obligación vigente de '${listing.plan}'`, `'aw settle list ${listing.plan}' enumera las que sí lo son. Si un 'apply' anterior alcanzó a publicar parte de sus sucesores, esas obligaciones ya están saldadas: volvé a preparar con las que queden`);
|
|
282
|
+
}
|
|
283
|
+
if (outcome === "settled" && evidence.length === 0) {
|
|
284
|
+
return fail("SETTLE_DECLARATION_INVALID", `se declara cumplida ${key} sin decir qué lo prueba`, `escribí --settle '${key}=<la salida real de lo que lo prueba>': sin evidencia no es un saldo, es una afirmación`);
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
value: { note, index, outcome, ...(outcome === "settled" ? { evidence } : {}) },
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/** What each carrier's successor would say, derived and never authored. */
|
|
291
|
+
function plannedFor(chain, declarations, listing) {
|
|
292
|
+
const resolved = new Map();
|
|
293
|
+
for (const obligation of [...listing.compensations, ...listing.handoffs]) {
|
|
294
|
+
const perNote = resolved.get(obligation.note) ?? new Map();
|
|
295
|
+
perNote.set(obligation.index, obligation.kind);
|
|
296
|
+
resolved.set(obligation.note, perNote);
|
|
297
|
+
}
|
|
298
|
+
const out = [];
|
|
299
|
+
for (const carrierId of [...new Set(declarations.map((entry) => entry.note))]) {
|
|
300
|
+
const carrier = chain.find((note) => note.id === carrierId);
|
|
301
|
+
if (carrier === undefined) {
|
|
302
|
+
return fail("SETTLE_OBLIGATION_UNKNOWN", `${carrierId} no está en la cadena de '${listing.plan}'`, `'aw settle list ${listing.plan}' enumera las obligaciones vigentes con su nota`);
|
|
303
|
+
}
|
|
304
|
+
// Every obligation of this carrier whose class NOBODY declared needs a
|
|
305
|
+
// reading from the person, and it needs it here. The successor has to state
|
|
306
|
+
// a class for everything it carries forward — a note being minted may not
|
|
307
|
+
// leave one unclassed — so an obligation left unnamed would be stamped
|
|
308
|
+
// `declared` with the CLI's own inference and never be questioned again.
|
|
309
|
+
// That reading is a person's: F2 built a whole boundary for it.
|
|
310
|
+
const unread = unreadLegacy(carrier, declarations, listing);
|
|
311
|
+
if (unread.length > 0) {
|
|
312
|
+
return fail("SETTLE_DECLARATION_INVALID", `${carrierId} carga obligaciones cuya clase nadie declaró y que no declaraste: ${unread.join("; ")}`, "el sucesor tiene que decir la clase de todo lo que arrastra, así que la lectura de cada una es tuya: declarala con --settle '<ref>=<evidencia>' o con --handoff '<ref>'");
|
|
313
|
+
}
|
|
314
|
+
const execution = {
|
|
315
|
+
session: carrier.lineage.execution.session,
|
|
316
|
+
phase: carrier.lineage.execution.phase,
|
|
317
|
+
};
|
|
318
|
+
const derived = deriveSettlementNote(carrier, declarations, {
|
|
319
|
+
...execution,
|
|
320
|
+
date: new Date().toISOString().slice(0, 10),
|
|
321
|
+
resolved: resolved.get(carrierId) ?? new Map(),
|
|
322
|
+
});
|
|
323
|
+
if (!derived.ok)
|
|
324
|
+
return verbatim(derived.failures[0], "el saldo no se puede derivar");
|
|
325
|
+
if (derived.draft === null)
|
|
326
|
+
continue;
|
|
327
|
+
const evidenceOf = new Map(declarations
|
|
328
|
+
.filter((entry) => entry.note === carrierId && entry.evidence !== undefined)
|
|
329
|
+
.map((entry) => [carrier.obligations[entry.index]?.text ?? "", entry.evidence]));
|
|
330
|
+
out.push({
|
|
331
|
+
note: carrierId,
|
|
332
|
+
settled: derived.settled.map((text) => ({ text, evidence: evidenceOf.get(text) ?? "" })),
|
|
333
|
+
keeps: derived.draft.obligations.map((obligation) => ({
|
|
334
|
+
text: obligation.text,
|
|
335
|
+
kind: obligation.kind,
|
|
336
|
+
declared: obligation.declared,
|
|
337
|
+
})),
|
|
338
|
+
execution,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
if (out.length === 0) {
|
|
342
|
+
return fail("SETTLE_DECLARATION_INVALID", "ninguna declaración cambia la cadena: dejar todo pendiente no publica nada", "declará al menos una obligación cumplida con su evidencia o reconocida como traspaso");
|
|
343
|
+
}
|
|
344
|
+
return { value: out };
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Obligations of this carrier whose class nobody declared and nobody read.
|
|
348
|
+
*
|
|
349
|
+
* Only the ones this settlement would carry FORWARD matter: one being discharged
|
|
350
|
+
* leaves the chain, so its class stops being anybody's claim.
|
|
351
|
+
*/
|
|
352
|
+
function unreadLegacy(carrier, declarations, listing) {
|
|
353
|
+
const owed = [...listing.compensations, ...listing.handoffs];
|
|
354
|
+
const out = [];
|
|
355
|
+
for (const [index, obligation] of carrier.obligations.entries()) {
|
|
356
|
+
if (obligation.declared)
|
|
357
|
+
continue;
|
|
358
|
+
// Not in force any more: superseded reasoning already left it behind.
|
|
359
|
+
if (!owed.some((entry) => entry.note === carrier.id && entry.index === index))
|
|
360
|
+
continue;
|
|
361
|
+
const declared = declarations.find((entry) => entry.note === carrier.id && entry.index === index);
|
|
362
|
+
if (declared !== undefined && declared.outcome !== "pending")
|
|
363
|
+
continue;
|
|
364
|
+
out.push(`${carrier.id}[${index}] ${obligation.text}`);
|
|
365
|
+
}
|
|
366
|
+
return out;
|
|
367
|
+
}
|
|
368
|
+
function specSlug(path, number) {
|
|
369
|
+
const prefix = `${number}-spec-`;
|
|
370
|
+
const file = basename(path);
|
|
371
|
+
if (!file.startsWith(prefix) || !file.endsWith(".md"))
|
|
372
|
+
return null;
|
|
373
|
+
const slug = file.slice(prefix.length, -".md".length);
|
|
374
|
+
return slug.length > 0 ? slug : null;
|
|
375
|
+
}
|
|
376
|
+
/** The exact command that applies exactly this — flags and all, never a shape. */
|
|
377
|
+
function applyCommand(plan, declarations, digest) {
|
|
378
|
+
const flags = [
|
|
379
|
+
...declarations.settle.map((item) => `--settle ${quoted(item)}`),
|
|
380
|
+
...declarations.handoff.map((item) => `--handoff ${quoted(item)}`),
|
|
381
|
+
...declarations.pending.map((item) => `--pending ${quoted(item)}`),
|
|
382
|
+
];
|
|
383
|
+
return `aw settle apply ${plan} ${flags.join(" ")} --approval ${digest}`;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* One shell argument, quoted so that pasting it back yields the SAME string.
|
|
387
|
+
*
|
|
388
|
+
* Evidence is prose somebody typed and prose contains apostrophes. Wrapping it
|
|
389
|
+
* naively produced a command that re-split into a different declaration — and a
|
|
390
|
+
* different declaration that still matched the approval, which is the one thing
|
|
391
|
+
* the two-step exists to make impossible.
|
|
392
|
+
*/
|
|
393
|
+
function quoted(value) {
|
|
394
|
+
return `'${value.split("'").join(`'\\''`)}'`;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* A refusal from the chain or the composition, carried VERBATIM.
|
|
398
|
+
*
|
|
399
|
+
* Re-coding it would hide which guarantee stopped the settlement behind a word
|
|
400
|
+
* invented at this layer, and the action a person reads would stop matching what
|
|
401
|
+
* actually happened.
|
|
402
|
+
*/
|
|
403
|
+
function verbatim(failure, fallback) {
|
|
404
|
+
// A refusal always comes with at least one failure — every producer pushes
|
|
405
|
+
// before returning — so the fallback is the shape TypeScript needs for an
|
|
406
|
+
// index access, not a case anybody can reach.
|
|
407
|
+
return {
|
|
408
|
+
status: "failed",
|
|
409
|
+
failure: failure ?? {
|
|
410
|
+
code: "SETTLE_DECLARATION_INVALID",
|
|
411
|
+
message: fallback,
|
|
412
|
+
action: "corregí la cadena antes de saldar nada",
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/** The plan, the spec it derives from, and the relation that ties them. */
|
|
417
|
+
async function readDocuments(fs, root, planPath, planDir) {
|
|
418
|
+
let planText;
|
|
419
|
+
try {
|
|
420
|
+
planText = await fs.readText(join(root, planPath));
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return fail("SETTLE_PLAN_ABSENT", `'${planPath}' no se puede leer: no hay plan cuyas obligaciones saldar`, `verificá la ruta del plan bajo '${planDir}/' o su correlativo`);
|
|
424
|
+
}
|
|
425
|
+
const relation = parseSpecRelation(planText);
|
|
426
|
+
const specPath = parseDerivedFromPath(planText);
|
|
427
|
+
if (relation.status !== "declared" || specPath === null) {
|
|
428
|
+
return fail("SETTLE_PLAN_LINEAGE_UNDECLARED", `'${planPath}' no declara una única spec de origen: sin linaje no hay cadena de decisiones`, "abrí el plan con /w:plan-refine y declarale un único '> Derived from docs/specs/NNN-spec-…'; un plan sin spec registra sus decisiones en el DECISION.md de su sesión");
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
return {
|
|
432
|
+
planText,
|
|
433
|
+
specPath,
|
|
434
|
+
specText: await fs.readText(join(root, specPath)),
|
|
435
|
+
relation: { number: relation.number },
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
return fail("SETTLE_SPEC_UNREADABLE", `'${specPath}' no se puede leer: no hay contrato contra el que componer la cadena`, "restaurá la spec de origen del plan y volvé a leer las obligaciones");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
//# sourceMappingURL=settle-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settle-service.js","sourceRoot":"","sources":["../../src/application/settle-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,10 +23,37 @@ const REMOTE_LOCATOR = /(?:\b[A-Za-z][A-Za-z0-9+.-]{0,31}:\/\/[^\s<>()]+|\b[A-Za
|
|
|
23
23
|
// `remote-read` is the discriminant of RemoteContextSnapshot, not a prose term.
|
|
24
24
|
// Seeing that typed context in a closure clause is invalid by construction.
|
|
25
25
|
const REMOTE_CONTEXT_DISCRIMINANT = /\bkind\s*:\s*["'`]?remote-read\b/i;
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
26
|
+
// COMPATIBILITY PATH, NOT THE CRITERION.
|
|
27
|
+
//
|
|
28
|
+
// This is the term allowlist that judged closure evidence before the referent
|
|
29
|
+
// rule below existed. It is kept so that no plan already written changes
|
|
30
|
+
// verdict: the criterion is the UNION of the two, which is strictly more
|
|
31
|
+
// permissive than either, so there is no migration and no grace period.
|
|
32
|
+
//
|
|
33
|
+
// Its path branch is exactly why the rule had to change: it accepted a relative
|
|
34
|
+
// path only under `src/`, `tests/`, `fixtures/`, `docs/` or `scripts/` — the
|
|
35
|
+
// directories of THIS repo — so a plan validating over `migraciones/` or `db/`
|
|
36
|
+
// was rejected for naming its own, while describing a perfectly local check.
|
|
37
|
+
const LOCAL_PROOF_TERMS_COMPAT = /\b(?:checkout|checkoutproof|fixture|ephemeral|test(?:s)?|prueba(?:s)?|inspecci[oó]n|inspection|lint|typecheck|build|golden(?:s)?|diff)\b|\bnpm\s+(?:run\s+)?(?:test|lint|typecheck|build|pack)\b|(?:^|[\s`(])(?:\.?\/?(?:src|tests|fixtures|docs|scripts)\/)/i;
|
|
38
|
+
// THE CRITERION: a closing clause is local when it names a REFERENT the checkout
|
|
39
|
+
// can produce — never when it happens to use a word from a list. Two structural
|
|
40
|
+
// forms, both about the shape of the reference and neither about vocabulary:
|
|
41
|
+
//
|
|
42
|
+
// · an invocation written as inline code — `npm run test`, `psql -f db/seed.sql`;
|
|
43
|
+
// · a relative path of ANY shape — `migraciones/001_init.sql`, `db/seeds/`.
|
|
44
|
+
//
|
|
45
|
+
// A remote locator never reaches this side: `remoteSurfaceOf` rejects the clause
|
|
46
|
+
// first, which is what lets the positive rule stay ignorant of surfaces. The
|
|
47
|
+
// policy is pure and touches no disk, so it judges whether the clause POINTS at
|
|
48
|
+
// the checkout, never whether the file is there — that is the checkout proof's
|
|
49
|
+
// job at execution time.
|
|
50
|
+
const INLINE_CODE_SPAN = /`([^`\n]+)`/g;
|
|
51
|
+
// A path is RELATIVE by grammar: it starts at a delimiter, never after another
|
|
52
|
+
// separator, so `/etc/passwd` and `~/scripts/x.sh` — local to a machine but
|
|
53
|
+
// outside the checkout — are not referents while `migraciones/001.sql` is.
|
|
54
|
+
const RELATIVE_PATH = /(?:^|[\s`("'[<])((?:\.{1,2}\/)?[\w.@+-]+(?:\/[\w.@+-]+)*\/[\w.@+-]*)/g;
|
|
55
|
+
const FILE_NAME = /\.[A-Za-z0-9]{1,8}$/;
|
|
56
|
+
const PROGRAM_NAME = /^(?:\.{1,2}\/)?[A-Za-z_][\w.+-]*$/;
|
|
30
57
|
/**
|
|
31
58
|
* Reads the structural source declarations from a plan without interpreting its
|
|
32
59
|
* business prose. The source policy therefore has one seam for every caller:
|
|
@@ -183,16 +210,31 @@ export function validateSourceBoundedSemantics(text) {
|
|
|
183
210
|
continue;
|
|
184
211
|
}
|
|
185
212
|
if ((clause.kind === "phase-validation" || clause.kind === "plan-validation") &&
|
|
186
|
-
!
|
|
213
|
+
!namesCheckoutReferent(clause.text) &&
|
|
214
|
+
!LOCAL_PROOF_TERMS_COMPAT.test(clause.text)) {
|
|
187
215
|
failures.push({
|
|
188
216
|
code: "PLAN_SOURCE_LOCAL_PROOF_MISSING",
|
|
189
217
|
line: clause.line,
|
|
190
|
-
message: `${semanticClauseLabel(clause)} no nombra
|
|
218
|
+
message: `${semanticClauseLabel(clause)} no nombra ninguna comprobación observable en el checkout: nombrá el comando, el archivo o la ruta que la produce`,
|
|
191
219
|
});
|
|
192
220
|
}
|
|
193
221
|
}
|
|
194
222
|
return failures;
|
|
195
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* The closing clauses of a document, by kind and text — the gate's own reading.
|
|
226
|
+
*
|
|
227
|
+
* Exported so a guard that must refuse a change to the closure path uses the
|
|
228
|
+
* SAME extraction the gate judges with, instead of a second parser that could
|
|
229
|
+
* disagree about what a closing clause even is. Line numbers are deliberately
|
|
230
|
+
* dropped: they move with any edit above them, and an editorial fix three
|
|
231
|
+
* sections up is not a change to a clause.
|
|
232
|
+
*/
|
|
233
|
+
export function closingClausesOf(text) {
|
|
234
|
+
return sourceBoundedClauses(text)
|
|
235
|
+
.filter((clause) => clause.kind !== "task")
|
|
236
|
+
.map((clause) => ({ kind: clause.kind, text: clause.text }));
|
|
237
|
+
}
|
|
196
238
|
function sourceBoundedClauses(text) {
|
|
197
239
|
const clauses = [];
|
|
198
240
|
const markdown = scanMarkdown(text);
|
|
@@ -259,6 +301,45 @@ function sourceBoundedClauses(text) {
|
|
|
259
301
|
}
|
|
260
302
|
return clauses;
|
|
261
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Does the clause name something the checkout can produce?
|
|
306
|
+
*
|
|
307
|
+
* Two forms. A relative path is a referent when its last segment is a file name
|
|
308
|
+
* or it ends in a separator — which is what keeps `N/A` and `60/40` from reading
|
|
309
|
+
* as evidence while `migraciones/001.sql` and `db/seeds/` do. An inline-code
|
|
310
|
+
* span whose first of two or more tokens has the shape of a program is an
|
|
311
|
+
* invocation, so `make verificar-catalogo` accredits without naming any path.
|
|
312
|
+
*/
|
|
313
|
+
function namesCheckoutReferent(text) {
|
|
314
|
+
if (namesRelativePath(text))
|
|
315
|
+
return true;
|
|
316
|
+
for (const match of text.matchAll(INLINE_CODE_SPAN)) {
|
|
317
|
+
const tokens = (match[1] ?? "")
|
|
318
|
+
.trim()
|
|
319
|
+
.split(/\s+/)
|
|
320
|
+
.filter((token) => token.length > 0);
|
|
321
|
+
if (tokens.length >= 2 && PROGRAM_NAME.test(tokens[0] ?? ""))
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* One path predicate for the whole rule, inside code spans and in prose alike.
|
|
328
|
+
*
|
|
329
|
+
* Backticks are not part of a path's grammar, so scanning the clause once
|
|
330
|
+
* covers `` `migraciones/003.sql` `` and the same path written bare — and keeps
|
|
331
|
+
* a code span from accrediting `N/A` merely for carrying a slash.
|
|
332
|
+
*/
|
|
333
|
+
function namesRelativePath(text) {
|
|
334
|
+
for (const match of text.matchAll(RELATIVE_PATH)) {
|
|
335
|
+
const path = match[1] ?? "";
|
|
336
|
+
if (path.endsWith("/"))
|
|
337
|
+
return true;
|
|
338
|
+
if (FILE_NAME.test(path.slice(path.lastIndexOf("/") + 1)))
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
262
343
|
function remoteSurfaceOf(text) {
|
|
263
344
|
const locator = REMOTE_LOCATOR.exec(text)?.[0];
|
|
264
345
|
if (locator !== undefined)
|