@tacuchi/agent-workflow-cli 21.6.0 → 21.7.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.
- package/dist/application/artifacts-service.js +10 -0
- package/dist/application/artifacts-service.js.map +1 -1
- package/dist/application/capability/design-handler.js +532 -22
- package/dist/application/capability/design-handler.js.map +1 -1
- package/dist/application/capability/dispatcher.js +20 -6
- package/dist/application/capability/dispatcher.js.map +1 -1
- package/dist/application/capability/durable-effect.js +23 -157
- package/dist/application/capability/durable-effect.js.map +1 -1
- package/dist/application/checkpoint-service.js +49 -3
- package/dist/application/checkpoint-service.js.map +1 -1
- package/dist/application/checkpoint-write-service.js +5 -0
- package/dist/application/checkpoint-write-service.js.map +1 -1
- package/dist/application/design/design-content-gate-service.js +134 -0
- package/dist/application/design/design-content-gate-service.js.map +1 -0
- package/dist/application/design/design-gate-service.js +18 -0
- package/dist/application/design/design-gate-service.js.map +1 -1
- package/dist/application/design/design-index-service.js +2 -0
- package/dist/application/design/design-index-service.js.map +1 -1
- package/dist/application/design/design-publish-service.js +91 -19
- package/dist/application/design/design-publish-service.js.map +1 -1
- package/dist/application/design/design-resolver-service.js +18 -1
- package/dist/application/design/design-resolver-service.js.map +1 -1
- package/dist/application/design/design-simple-service.js +217 -0
- package/dist/application/design/design-simple-service.js.map +1 -0
- package/dist/application/flow/advance.js +96 -11
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/flow-service.js +12 -1
- package/dist/application/flow/flow-service.js.map +1 -1
- package/dist/application/flow/internal-actions.js +221 -0
- package/dist/application/flow/internal-actions.js.map +1 -0
- package/dist/application/flow/internal-drive.js +293 -0
- package/dist/application/flow/internal-drive.js.map +1 -0
- package/dist/application/flow/submit.js +242 -84
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/local-proposal.js +171 -0
- package/dist/application/local-proposal.js.map +1 -0
- package/dist/application/parsers/decisiones.js +13 -0
- package/dist/application/parsers/decisiones.js.map +1 -1
- package/dist/application/paths-service.js +11 -1
- package/dist/application/paths-service.js.map +1 -1
- package/dist/application/resume-service.js +22 -26
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/semantic-operation/protocol.js +14 -4
- package/dist/application/semantic-operation/protocol.js.map +1 -1
- package/dist/application/session-artifacts.js +53 -0
- package/dist/application/session-artifacts.js.map +1 -1
- package/dist/application/session-close-service.js +5 -0
- package/dist/application/session-close-service.js.map +1 -1
- package/dist/application/session-narrative.js +294 -0
- package/dist/application/session-narrative.js.map +1 -0
- package/dist/application/status-service.js +1 -0
- package/dist/application/status-service.js.map +1 -1
- package/dist/application/workline-index-service.js +2 -0
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/cli/commands/capability.js +1 -1
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/designs.js +29 -5
- package/dist/cli/commands/designs.js.map +1 -1
- package/dist/cli/commands/flow.js +14 -0
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/session-artifacts.js +55 -2
- package/dist/cli/commands/session-artifacts.js.map +1 -1
- package/dist/cli/parser.js +1 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/domain/design/capability.js +35 -4
- package/dist/domain/design/capability.js.map +1 -1
- package/dist/domain/design/direct.js.map +1 -1
- package/dist/domain/design/expansion.js +137 -0
- package/dist/domain/design/expansion.js.map +1 -0
- package/dist/domain/design/manifest.js +61 -8
- package/dist/domain/design/manifest.js.map +1 -1
- package/dist/domain/design/reference.js +57 -10
- package/dist/domain/design/reference.js.map +1 -1
- package/dist/domain/design/simple.js +164 -0
- package/dist/domain/design/simple.js.map +1 -0
- package/dist/domain/flow/answer.js +90 -12
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +266 -60
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/authorization.js +36 -15
- package/dist/domain/flow/authorization.js.map +1 -1
- package/dist/domain/flow/directive.js +10 -6
- package/dist/domain/flow/directive.js.map +1 -1
- package/dist/domain/flow/execution-result.js +72 -0
- package/dist/domain/flow/execution-result.js.map +1 -0
- package/dist/domain/flow/run-state.js +165 -13
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/host-verification.js +8 -8
- package/dist/domain/host-verification.js.map +1 -1
- package/dist/domain/proposal.js +91 -0
- package/dist/domain/proposal.js.map +1 -0
- package/dist/domain/session/narrative.js +126 -0
- package/dist/domain/session/narrative.js.map +1 -0
- package/package.json +1 -1
- package/skills/w/SKILL.md +1 -1
- package/skills/w/loops/CHASSIS.md +1 -1
- package/skills/w/loops/plan-new-loop/LOOP.md +5 -6
- package/skills/w/loops/plan-refine-loop/LOOP.md +7 -7
- package/skills/w/loops/spec-refine-loop/LOOP.md +6 -4
- package/skills/w/modules/DESIGN-REFERENCES.md +50 -56
- package/skills/w/roles/design/CONTRACT.md +73 -6
- package/skills/w/roles/design/ROLE.md +21 -3
- package/skills/w/schemas/design/design-manifest.v1.schema.json +4 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Workline operations this CLI runs for itself, and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* Every handler below calls a service that already exists — the same one the
|
|
5
|
+
* public command calls — so there is no second implementation of the board, of a
|
|
6
|
+
* session's artifacts or of a close that could answer differently from `aw status`,
|
|
7
|
+
* `aw session-artifacts` or `aw session-close`. What this module adds is the
|
|
8
|
+
* translation between an operation and the two things the flow contract needs back:
|
|
9
|
+
* the REAL output, so the verdict has something to judge, and whether that output
|
|
10
|
+
* satisfies what the transition demanded, so nothing is credited on a reading that
|
|
11
|
+
* came back empty.
|
|
12
|
+
*
|
|
13
|
+
* Three properties hold by construction and the tests pin all three:
|
|
14
|
+
*
|
|
15
|
+
* - **No process leaves.** Nothing here spawns, runs a command, resolves a binary
|
|
16
|
+
* or reaches a model. The `ProcessPort` is not a dependency, which is stronger
|
|
17
|
+
* than a rule about not using it.
|
|
18
|
+
* - **No arbitrary invocation.** The row's `program` and `args` are never read; the
|
|
19
|
+
* handler is chosen by the declared operation and its parameters travel in the
|
|
20
|
+
* declaration. A row could name `rm -rf` in its invocation and this file would
|
|
21
|
+
* still only project a board.
|
|
22
|
+
* - **The verdict is the output's, not the caller's.** `ok` is computed from what
|
|
23
|
+
* the service returned. A read that resolved nothing is `ok: false` with its
|
|
24
|
+
* reason, and the boundary stays standing.
|
|
25
|
+
*/
|
|
26
|
+
import { runArtifactsCommand } from "../artifacts-service.js";
|
|
27
|
+
import { applyLocalProposal } from "../local-proposal.js";
|
|
28
|
+
import { parseMdSectionBilingual } from "../markdown.js";
|
|
29
|
+
import { resolveWorkspaceRoot } from "../paths-service.js";
|
|
30
|
+
import { readSessionArtifacts } from "../release-data/artifacts.js";
|
|
31
|
+
import { canonicalJson } from "../semantic-operation/protocol.js";
|
|
32
|
+
import { runSessionClose } from "../session-close-service.js";
|
|
33
|
+
import { runStatusCommand } from "../status-service.js";
|
|
34
|
+
export function internalActionExecutor(deps) {
|
|
35
|
+
return async (plan, run) => {
|
|
36
|
+
switch (plan.operation) {
|
|
37
|
+
case "workspace.board":
|
|
38
|
+
return board(deps);
|
|
39
|
+
case "session.artifacts":
|
|
40
|
+
return artifacts(deps, run, plan.dump ?? null);
|
|
41
|
+
case "session.close":
|
|
42
|
+
return close(deps, run);
|
|
43
|
+
case "proposal.publish":
|
|
44
|
+
return publish(deps, run);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Write the run's approved proposal — all of it, or none of it.
|
|
50
|
+
*
|
|
51
|
+
* It goes through the SAME `applyLocalProposal` the capability's `apply` stage
|
|
52
|
+
* uses, so the approval seal, the compare-and-swap and the all-or-nothing
|
|
53
|
+
* publication are one implementation and not two that could disagree about when a
|
|
54
|
+
* write is legitimate. The approval it hands over is the proposal's own seal:
|
|
55
|
+
* reaching this row at all means `authorizeTransition` found a grant given over
|
|
56
|
+
* exactly that seal, and a grant over anything else never gets here.
|
|
57
|
+
*/
|
|
58
|
+
async function publish(deps, run) {
|
|
59
|
+
const proposal = run.proposal;
|
|
60
|
+
if (proposal === null) {
|
|
61
|
+
return refusal("proposal.publish", "la corrida no tiene ninguna propuesta sellada que publicar", canonicalJson({ proposal: null }));
|
|
62
|
+
}
|
|
63
|
+
const root = await resolveWorkspaceRoot(deps.fs, deps.env, deps.paths);
|
|
64
|
+
const applied = await applyLocalProposal(deps.fs, deps.paths, {
|
|
65
|
+
root,
|
|
66
|
+
proposal,
|
|
67
|
+
approval: { digest: proposal.digest, granted: proposal.requires_approval },
|
|
68
|
+
selfAuthorized: proposal.effects.filter((effect) => !proposal.requires_approval.includes(effect)),
|
|
69
|
+
});
|
|
70
|
+
if (!applied.ok) {
|
|
71
|
+
return refusal("proposal.publish", `${applied.failure.message} — ${applied.failure.action}`, canonicalJson({ failure: applied.failure, applied: applied.applied }));
|
|
72
|
+
}
|
|
73
|
+
const result = applied.result;
|
|
74
|
+
const destinations = proposal.artifacts.map((a) => a.path);
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
summary: result.already_applied
|
|
78
|
+
? `la propuesta ya estaba aplicada: ${destinations.join(", ")} sin cambios`
|
|
79
|
+
: `publicado: ${result.written.join(", ")}`,
|
|
80
|
+
output: canonicalJson({ ...result, digest: proposal.digest, destinations }),
|
|
81
|
+
// Only what really landed. A re-entry that found the bytes already there
|
|
82
|
+
// credits the same classes — the effect IS applied — and the summary is what
|
|
83
|
+
// distinguishes "now" from "already", which is the honest split.
|
|
84
|
+
effects: [...result.applied],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function board(deps) {
|
|
88
|
+
const data = await runStatusCommand(deps.fs, deps.env, deps.paths, { git: deps.git });
|
|
89
|
+
const counts = data.counts;
|
|
90
|
+
return {
|
|
91
|
+
ok: true,
|
|
92
|
+
summary: `tablero: ${counts.specs} specs, ${counts.plans} planes, ${counts.sessions_active} sesiones activas, ${counts.pending} pendientes`,
|
|
93
|
+
output: canonicalJson(data),
|
|
94
|
+
effects: ["read_only"],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The session's artifacts: the presence report always, plus the content of the
|
|
99
|
+
* kinds the transition needs.
|
|
100
|
+
*
|
|
101
|
+
* Both halves are read even when a dump is requested, because they answer
|
|
102
|
+
* different questions and the transitions demand both: the report says the
|
|
103
|
+
* session exists as an artifact and how many success criteria it carries; the dump
|
|
104
|
+
* says the specific artifacts have content. A dump alone would pass a session
|
|
105
|
+
* whose criteria were never seeded.
|
|
106
|
+
*/
|
|
107
|
+
async function artifacts(deps, run, dump) {
|
|
108
|
+
// The presence report, without the narrative: this operation checks that the
|
|
109
|
+
// artifacts are THERE, and projecting the session's whole reading to answer
|
|
110
|
+
// that would be work nobody asked for on every advance.
|
|
111
|
+
const report = await runArtifactsCommand(deps.fs, deps.env, deps.paths, {
|
|
112
|
+
code: run.code,
|
|
113
|
+
noNarrative: true,
|
|
114
|
+
});
|
|
115
|
+
if ("sessionError" in report) {
|
|
116
|
+
return refusal("session.artifacts", `no se pudo resolver la sesión '${run.code}'`, canonicalJson(report));
|
|
117
|
+
}
|
|
118
|
+
if (report.artifacts.session === null) {
|
|
119
|
+
return refusal("session.artifacts", `la sesión '${report.session}' no tiene su SESSION.md`, canonicalJson(report));
|
|
120
|
+
}
|
|
121
|
+
if (dump === null) {
|
|
122
|
+
return {
|
|
123
|
+
ok: true,
|
|
124
|
+
summary: `sesión ${report.session}: SESSION.md presente, ${report.artifacts.session.criterios_count} criterios, ${report.artifacts.decisiones_count} decisiones`,
|
|
125
|
+
output: canonicalJson(report),
|
|
126
|
+
effects: SEEDED_EFFECTS,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const dumped = await readSessionArtifacts(deps.fs, deps.paths, run.code, [...dump], deps.runtime);
|
|
130
|
+
const output = canonicalJson({ report, dump: dumped });
|
|
131
|
+
if (dumped.error !== undefined) {
|
|
132
|
+
return refusal("session.artifacts", String(dumped.hint ?? dumped.error), output);
|
|
133
|
+
}
|
|
134
|
+
const empty = dump.filter((kind) => !hasContent(dumped[kind]));
|
|
135
|
+
if (empty.length > 0) {
|
|
136
|
+
return refusal("session.artifacts", `sin contenido: ${empty.join(", ")}`, output);
|
|
137
|
+
}
|
|
138
|
+
// `objetivo` is the artifact that carries the success criteria, so demanding it
|
|
139
|
+
// is demanding them: a SESSION.md with a criteria heading and nothing under it
|
|
140
|
+
// is exactly the seed this row exists to make checkable. The count is not enough
|
|
141
|
+
// — `session-create` seeds an empty `- [ ]`, and a criterion with no text is the
|
|
142
|
+
// template, not a done-condition anybody could falsify.
|
|
143
|
+
if (dump.includes("objetivo") && !hasWrittenCriteria(dumped.objetivo)) {
|
|
144
|
+
return refusal("session.artifacts", "el SESSION.md no declara ningún criterio de éxito escrito", output);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
ok: true,
|
|
148
|
+
summary: `sesión ${report.session}: ${dump.join(", ")} con contenido, ${report.artifacts.session.criterios_count} criterios`,
|
|
149
|
+
output,
|
|
150
|
+
effects: SEEDED_EFFECTS,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* What a satisfied artifact reading really attests.
|
|
155
|
+
*
|
|
156
|
+
* `local_additive` travels with the success path and only with it, and that is not
|
|
157
|
+
* the executor crediting itself with a write. The rows this operation serves stand
|
|
158
|
+
* for a SEEDING — the session, its objective, its criteria, its CHECKPOINT, its
|
|
159
|
+
* `SCRIPTS.sql` — and the artifact being there is the effect, materially, however
|
|
160
|
+
* it got there. Observing it is a stronger claim than the external contract ever
|
|
161
|
+
* had, where whoever answered simply asserted the class. On the refusal path the
|
|
162
|
+
* list is empty, so a reading that found nothing credits nothing.
|
|
163
|
+
*/
|
|
164
|
+
const SEEDED_EFFECTS = ["read_only", "local_additive"];
|
|
165
|
+
/**
|
|
166
|
+
* Whether a dumped artifact really came back with something in it.
|
|
167
|
+
*
|
|
168
|
+
* `scripts` is a LIST and every other kind is a record with `content`, so the two
|
|
169
|
+
* shapes are checked as what they are. Treating a missing artifact, an unreadable
|
|
170
|
+
* one and an empty one alike is deliberate: all three mean the transition's
|
|
171
|
+
* evidence is not there, and the row's own recovery says what to do about it.
|
|
172
|
+
*/
|
|
173
|
+
/** A criterion with something written after its box. An empty one is the template. */
|
|
174
|
+
const WRITTEN_CRITERION = /^[ \t]*[-*][ \t]+\[[ xX]?\][ \t]*\S/m;
|
|
175
|
+
/**
|
|
176
|
+
* Whether the dumped SESSION really declares a done-condition.
|
|
177
|
+
*
|
|
178
|
+
* Scoped to the criteria section through the SAME parser the artifacts report
|
|
179
|
+
* uses, and not to the whole document: a checkbox under `Origin` or inside a code
|
|
180
|
+
* fence is not a success criterion, and a check that counted those would pass the
|
|
181
|
+
* one session it exists to catch.
|
|
182
|
+
*/
|
|
183
|
+
function hasWrittenCriteria(value) {
|
|
184
|
+
if (value === null || typeof value !== "object")
|
|
185
|
+
return false;
|
|
186
|
+
const content = value.content;
|
|
187
|
+
if (typeof content !== "string")
|
|
188
|
+
return false;
|
|
189
|
+
const section = parseMdSectionBilingual(content, "Success criteria") ??
|
|
190
|
+
parseMdSectionBilingual(content, "Criterios de aceptación");
|
|
191
|
+
return section !== undefined && WRITTEN_CRITERION.test(section);
|
|
192
|
+
}
|
|
193
|
+
function hasContent(value) {
|
|
194
|
+
if (Array.isArray(value))
|
|
195
|
+
return value.length > 0;
|
|
196
|
+
if (value === null || typeof value !== "object")
|
|
197
|
+
return false;
|
|
198
|
+
const content = value.content;
|
|
199
|
+
return typeof content === "string" && content.trim().length > 0;
|
|
200
|
+
}
|
|
201
|
+
async function close(deps, run) {
|
|
202
|
+
const result = await runSessionClose(deps.fs, deps.paths, { code: run.code });
|
|
203
|
+
if (!("sessionClose" in result)) {
|
|
204
|
+
const why = "sessionError" in result ? canonicalJson(result.sessionError) : result.error;
|
|
205
|
+
return refusal("session.close", `la sesión no cerró: ${why}`, canonicalJson(result));
|
|
206
|
+
}
|
|
207
|
+
const closed = result.sessionClose;
|
|
208
|
+
const pending = closed.pending_integration ?? [];
|
|
209
|
+
return {
|
|
210
|
+
ok: closed.closed,
|
|
211
|
+
summary: `sesión ${closed.folder} cerrada${closed.history === undefined ? " (sin fila de HISTORY)" : ` · HISTORY ${closed.history.action}`}${pending.length > 0 ? ` · ${pending.length} unidad(es) sin integrar` : ""}`,
|
|
212
|
+
output: canonicalJson(result),
|
|
213
|
+
// Closing ensures the CHECKPOINT exists and rewrites the session's marker plus
|
|
214
|
+
// its HISTORY row: additive and overwriting, both real.
|
|
215
|
+
effects: closed.closed ? ["local_additive", "mutate_overwrite"] : [],
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function refusal(operation, message, output) {
|
|
219
|
+
return { ok: false, summary: `${operation}: ${message}`, output, effects: [] };
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=internal-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-actions.js","sourceRoot":"","sources":["../../../src/application/flow/internal-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One invocation also EXHAUSTS every internal action it may run, not only every
|
|
3
|
+
* decision it may take.
|
|
4
|
+
*
|
|
5
|
+
* The walk in `advance` stops at any delegated step because deciding and executing
|
|
6
|
+
* are different acts. That is still true — what changed is who executes: an action
|
|
7
|
+
* the registry classifies `internal` is a Workline operation this process can
|
|
8
|
+
* materialize, so handing it back as work would be the CLI asking somebody to run
|
|
9
|
+
* `aw` for it. This driver closes that gap and nothing else: it runs the operation,
|
|
10
|
+
* judges the real output with the SAME verdict an external result faces, applies
|
|
11
|
+
* the transition and keeps going until a boundary that genuinely is not the CLI's.
|
|
12
|
+
*
|
|
13
|
+
* **Three writes, in this order, and the order is the contract.**
|
|
14
|
+
*
|
|
15
|
+
* 1. The intent — `pending_action.attempted` — is persisted BEFORE the operation
|
|
16
|
+
* runs. A process that dies during a close would otherwise come back with no
|
|
17
|
+
* way to tell "never started" from "already closed", and the two need different
|
|
18
|
+
* answers.
|
|
19
|
+
* 2. The operation runs with NO lock held. Holding the run's lock across an
|
|
20
|
+
* effect that takes its own would be the deadlock this design avoids by making
|
|
21
|
+
* the two moments separate writes rather than one long one.
|
|
22
|
+
* 3. The result is judged and applied under the lock again, compare-and-swap on
|
|
23
|
+
* the digest step 1 produced. A state that moved in between belongs to another
|
|
24
|
+
* invocation, and the answer is to re-advance — never to overwrite it.
|
|
25
|
+
*
|
|
26
|
+
* Re-entry follows from the same three: `attempted` with an idempotent operation
|
|
27
|
+
* is re-run and confirmed — that is what "recoverable without reopening the
|
|
28
|
+
* session" means, since closing an already closed session is the close itself
|
|
29
|
+
* saying so. `attempted` with a non-idempotent one stops at its boundary with the
|
|
30
|
+
* row's own recovery: applying it twice is the one failure nobody can undo.
|
|
31
|
+
*/
|
|
32
|
+
import { internalActionOf, journeyOfFlow, } from "../../domain/flow/authority.js";
|
|
33
|
+
import { stepOf } from "../../domain/flow/directive.js";
|
|
34
|
+
import { executionVerdict } from "../../domain/flow/execution-result.js";
|
|
35
|
+
import { applyTransition, withActionAttempted, withBoundary, withEvent, withPendingAction, withProposal, } from "../../domain/flow/run-state.js";
|
|
36
|
+
import { semanticDigest } from "../semantic-operation/protocol.js";
|
|
37
|
+
import { sessionNumericCode } from "../session-resolver.js";
|
|
38
|
+
import { advanceFlowRun, directiveFor, effectsOfTransition, resolveBoundary } from "./advance.js";
|
|
39
|
+
import { applyUnderLock } from "./run-state-service.js";
|
|
40
|
+
/**
|
|
41
|
+
* How many internal actions one invocation may chain.
|
|
42
|
+
*
|
|
43
|
+
* A journey has a fixed length, so the walk cannot really loop — but the driver
|
|
44
|
+
* re-resolves the boundary from persisted state on every turn, and a bound is what
|
|
45
|
+
* keeps a defect in that resolution from becoming an invocation that never
|
|
46
|
+
* returns. Twice the longest journey, so the cap can only ever be a bug's ceiling
|
|
47
|
+
* and never a real run's.
|
|
48
|
+
*/
|
|
49
|
+
const MAX_INTERNAL_STEPS = 64;
|
|
50
|
+
/**
|
|
51
|
+
* Run every internal action standing between here and the next real boundary.
|
|
52
|
+
*
|
|
53
|
+
* `executor` absent means this caller has no way to materialize anything — a
|
|
54
|
+
* lightweight context, a test that only exercises the walk — and then an internal
|
|
55
|
+
* action behaves exactly like an external one: the boundary is emitted with its
|
|
56
|
+
* invocation, which is what the caller would have had to run anyway. That is a
|
|
57
|
+
* degradation of the MECHANISM, never of the contract: nothing is credited, and
|
|
58
|
+
* the directive says what is pending.
|
|
59
|
+
*/
|
|
60
|
+
export async function driveInternalActions(fs, location, executor, from) {
|
|
61
|
+
if (executor === undefined)
|
|
62
|
+
return from;
|
|
63
|
+
let current = from;
|
|
64
|
+
for (let step = 0; step < MAX_INTERNAL_STEPS; step += 1) {
|
|
65
|
+
const pending = nextInternal(current.state);
|
|
66
|
+
if (pending === null)
|
|
67
|
+
return current;
|
|
68
|
+
const marked = await markAttempted(fs, location, current);
|
|
69
|
+
if (!marked.ok)
|
|
70
|
+
return marked;
|
|
71
|
+
current = marked;
|
|
72
|
+
const outcome = await run(executor, pending, current.state);
|
|
73
|
+
const settled = await settle(fs, location, current, pending, outcome);
|
|
74
|
+
if (!settled.ok)
|
|
75
|
+
return settled;
|
|
76
|
+
current = settled.run;
|
|
77
|
+
if (!settled.advanced)
|
|
78
|
+
return current;
|
|
79
|
+
}
|
|
80
|
+
return current;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The operation, with a thrown error turned into a refusal.
|
|
84
|
+
*
|
|
85
|
+
* A service that throws — an unreadable workspace, a lock nobody released — must
|
|
86
|
+
* not take the whole invocation down with a stack trace: the run is standing on a
|
|
87
|
+
* boundary, and what the person needs is that boundary back with a cause and the
|
|
88
|
+
* row's recovery. Fail-closed here means "nothing is credited AND the run is still
|
|
89
|
+
* answerable", not "the process dies before writing anything".
|
|
90
|
+
*/
|
|
91
|
+
async function run(executor, pending, state) {
|
|
92
|
+
const coordinates = {
|
|
93
|
+
session: state.session,
|
|
94
|
+
code: sessionNumericCode(state.session) ?? state.session,
|
|
95
|
+
proposal: state.proposal,
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
return await executor(pending.plan, coordinates);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const why = error instanceof Error ? error.message : String(error);
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
summary: `${pending.plan.operation}: la operación interna falló (${why})`,
|
|
105
|
+
output: "",
|
|
106
|
+
effects: [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The internal action this run is standing on, or `null` for anything else.
|
|
112
|
+
*
|
|
113
|
+
* Derived from the persisted state and the registry only — never from what the
|
|
114
|
+
* previous turn believed — so a run resumed by another process reaches exactly the
|
|
115
|
+
* same conclusion as the one that left it there.
|
|
116
|
+
*/
|
|
117
|
+
function nextInternal(state) {
|
|
118
|
+
const journey = journeyOfFlow(state.flow);
|
|
119
|
+
const resolved = resolveBoundary(state, journey);
|
|
120
|
+
if (resolved.kind !== "execution" || resolved.stopped === null || resolved.action === null) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
const plan = internalActionOf(resolved.stopped);
|
|
124
|
+
if (plan === null)
|
|
125
|
+
return null;
|
|
126
|
+
// A non-idempotent operation already begun is the one case that must NOT run
|
|
127
|
+
// again. It cannot happen today — every internal row is idempotent — and it is
|
|
128
|
+
// checked anyway, because the day a row is not, the failure would be silent and
|
|
129
|
+
// unrepeatable.
|
|
130
|
+
if (state.pending_action?.attempted === true && !resolved.action.idempotent)
|
|
131
|
+
return null;
|
|
132
|
+
return { decision: resolved.stopped, action: resolved.action, plan };
|
|
133
|
+
}
|
|
134
|
+
/** Persist "we are about to run this", CAS on the state the caller reasoned over. */
|
|
135
|
+
async function markAttempted(fs, location, current) {
|
|
136
|
+
if (current.state.pending_action?.attempted === true)
|
|
137
|
+
return current;
|
|
138
|
+
const marked = await applyUnderLock(fs, location, (live) => {
|
|
139
|
+
if (live === null)
|
|
140
|
+
return { ok: false, failure: RUN_VANISHED };
|
|
141
|
+
return { ok: true, state: withActionAttempted(live), value: null };
|
|
142
|
+
}, { expectDigest: current.state.digest });
|
|
143
|
+
if (!marked.ok)
|
|
144
|
+
return marked;
|
|
145
|
+
return { ok: true, state: marked.state, value: current.value };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Judge the outcome and either apply the transition or keep the boundary.
|
|
149
|
+
*
|
|
150
|
+
* `advanced: false` is what stops the driver: a refusal has already produced the
|
|
151
|
+
* directive the caller needs — the same boundary, with the real cause and the
|
|
152
|
+
* row's recovery — and running the next turn would re-run an operation whose
|
|
153
|
+
* output was just refused.
|
|
154
|
+
*/
|
|
155
|
+
async function settle(fs, location, current, pending, outcome) {
|
|
156
|
+
const applied = await applyUnderLock(fs, location, (live) => {
|
|
157
|
+
if (live === null)
|
|
158
|
+
return { ok: false, failure: RUN_VANISHED };
|
|
159
|
+
return accept(live, pending, outcome);
|
|
160
|
+
}, { expectDigest: current.state.digest });
|
|
161
|
+
if (!applied.ok)
|
|
162
|
+
return applied;
|
|
163
|
+
return {
|
|
164
|
+
ok: true,
|
|
165
|
+
run: { ok: true, state: applied.state, value: applied.value.directive },
|
|
166
|
+
advanced: applied.value.advanced,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function accept(state, pending, outcome) {
|
|
170
|
+
const journey = journeyOfFlow(state.flow);
|
|
171
|
+
// What the row declares is the CEILING; what a sealed proposal really does is
|
|
172
|
+
// the effect. Judging the publication against the ceiling would refuse a
|
|
173
|
+
// proposal that only creates files on a row that also permits overwriting.
|
|
174
|
+
const declared = effectsOfTransition(state, pending.decision);
|
|
175
|
+
const verdict = executionVerdict(resultOf(pending, outcome), pending.action, declared);
|
|
176
|
+
const outputDigest = semanticDigest({ output: outcome.output });
|
|
177
|
+
if (verdict !== null) {
|
|
178
|
+
const failure = {
|
|
179
|
+
kind: "failed",
|
|
180
|
+
transition: pending.decision.id,
|
|
181
|
+
operation: pending.plan.operation,
|
|
182
|
+
code: verdict.detail.code,
|
|
183
|
+
// What the operation really found, not the contract's restatement of it:
|
|
184
|
+
// the trace is where "which precondition was missing" has to survive.
|
|
185
|
+
message: outcome.summary,
|
|
186
|
+
recovery: verdict.detail.action,
|
|
187
|
+
};
|
|
188
|
+
// Re-running `aw flow advance` over a boundary nobody has fixed yet reaches
|
|
189
|
+
// exactly this point again, and appending the identical event every time would
|
|
190
|
+
// turn the trace into a retry counter. The same failure, still standing, is one
|
|
191
|
+
// fact — the attempt history is where "how many times" belongs.
|
|
192
|
+
const failed = repeats(state, failure) ? state : withEvent(state, failure);
|
|
193
|
+
const resolved = resolveBoundary(failed, journey);
|
|
194
|
+
const built = directiveFor(failed, resolved, [], {
|
|
195
|
+
...(verdict.detail.outcome === undefined ? {} : { outcome: verdict.detail.outcome }),
|
|
196
|
+
nextAction: `${outcome.summary} — ${verdict.detail.action}`,
|
|
197
|
+
});
|
|
198
|
+
if (!built.ok)
|
|
199
|
+
return { ok: false, failure: built.failure };
|
|
200
|
+
return {
|
|
201
|
+
ok: true,
|
|
202
|
+
state: failed,
|
|
203
|
+
value: {
|
|
204
|
+
directive: {
|
|
205
|
+
...built.directive,
|
|
206
|
+
// The verdict's own code, exactly as an external result would get: an
|
|
207
|
+
// internal execution that reported a private vocabulary would make the
|
|
208
|
+
// same refusal readable one way from one producer and another way from
|
|
209
|
+
// the other. The material cause travels as the message.
|
|
210
|
+
error: resolved.error ?? {
|
|
211
|
+
code: verdict.detail.code,
|
|
212
|
+
message: `${verdict.message}: ${outcome.summary}`,
|
|
213
|
+
action: verdict.detail.action,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
advanced: false,
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
let next = withEvent(state, {
|
|
221
|
+
kind: "executed",
|
|
222
|
+
transition: pending.decision.id,
|
|
223
|
+
operation: pending.plan.operation,
|
|
224
|
+
summary: outcome.summary,
|
|
225
|
+
output_digest: outputDigest,
|
|
226
|
+
effects: [...outcome.effects],
|
|
227
|
+
evidence: [...pending.action.evidence],
|
|
228
|
+
});
|
|
229
|
+
next = applyTransition(next, pending.decision.id, declared);
|
|
230
|
+
// A published proposal is spent. Leaving it seated would keep a preview of
|
|
231
|
+
// bytes that are already on disk standing in front of the next boundary, and the
|
|
232
|
+
// grant given over its seal would outlive the thing it was given for.
|
|
233
|
+
if (pending.plan.operation === "proposal.publish")
|
|
234
|
+
next = withProposal(next, null);
|
|
235
|
+
// The pending action is cleared explicitly rather than left for the next
|
|
236
|
+
// `withPendingAction` to overwrite: between applying and re-advancing the state
|
|
237
|
+
// is persisted, and a state that still named an action nobody is waiting on
|
|
238
|
+
// would tell whoever resumes to run it again.
|
|
239
|
+
next = withPendingAction(next, null);
|
|
240
|
+
next = withBoundary(next, journey[next.applied.length]?.id ?? null);
|
|
241
|
+
const advanced = advanceFlowRun({ state: next, journey, applied: [stepOf(pending.decision)] });
|
|
242
|
+
if (!advanced.ok)
|
|
243
|
+
return { ok: false, failure: advanced.failure };
|
|
244
|
+
return {
|
|
245
|
+
ok: true,
|
|
246
|
+
state: advanced.state,
|
|
247
|
+
value: { directive: advanced.directive, advanced: true },
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** Whether the trace's last event is this same failure, unchanged. */
|
|
251
|
+
function repeats(state, failure) {
|
|
252
|
+
const last = state.events.at(-1);
|
|
253
|
+
if (last === undefined || last.kind !== "failed")
|
|
254
|
+
return false;
|
|
255
|
+
return (last.transition === failure.transition &&
|
|
256
|
+
last.code === failure.code &&
|
|
257
|
+
last.message === failure.message);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* The outcome, expressed in the result protocol an external executor would send.
|
|
261
|
+
*
|
|
262
|
+
* Built rather than shortcut on purpose: the verdict must not be able to tell an
|
|
263
|
+
* internal result from an external one, so the internal path assembles the same
|
|
264
|
+
* fields — the invocation the row declared, the demanded evidence with the REAL
|
|
265
|
+
* output as its detail, and the effects the operation actually applied.
|
|
266
|
+
*/
|
|
267
|
+
function resultOf(pending, outcome) {
|
|
268
|
+
return {
|
|
269
|
+
// The INVOCATION completed — the service returned, and everything it had is in
|
|
270
|
+
// `output`. What may be missing is the evidence the transition demanded, and
|
|
271
|
+
// saying that with `outcome: failed` would report a broken tool where the real
|
|
272
|
+
// fact is an artifact that is not there. The validations below are what refuse.
|
|
273
|
+
outcome: "completed",
|
|
274
|
+
invocation: pending.action.invocation,
|
|
275
|
+
output: { value: null, reference: null, completeness: "complete" },
|
|
276
|
+
validations: pending.action.evidence.map((id) => ({
|
|
277
|
+
id,
|
|
278
|
+
passed: outcome.ok,
|
|
279
|
+
detail: outcome.ok ? outcome.output : outcome.summary,
|
|
280
|
+
})),
|
|
281
|
+
effects: {
|
|
282
|
+
planned: [...outcome.effects],
|
|
283
|
+
approved: [...outcome.effects],
|
|
284
|
+
applied: [...outcome.effects],
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const RUN_VANISHED = {
|
|
289
|
+
code: "FLOW_RUN_ABSENT",
|
|
290
|
+
message: "el estado de corrida desapareció mientras se ejecutaba su acción interna",
|
|
291
|
+
action: "re-adoptá la sesión con 'aw flow advance --flow <flow> --adopt' antes de seguir",
|
|
292
|
+
};
|
|
293
|
+
//# sourceMappingURL=internal-drive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-drive.js","sourceRoot":"","sources":["../../../src/application/flow/internal-drive.ts"],"names":[],"mappings":"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"}
|