@tacuchi/agent-workflow-cli 21.11.0 → 21.13.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/dist/application/checkpoint/markdown.js +38 -2
- package/dist/application/checkpoint/markdown.js.map +1 -1
- package/dist/application/checkpoint-service.js +10 -3
- package/dist/application/checkpoint-service.js.map +1 -1
- package/dist/application/checkpoint-write-service.js +52 -27
- package/dist/application/checkpoint-write-service.js.map +1 -1
- package/dist/application/flow/advance.js +132 -18
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/flow-service.js +100 -2
- package/dist/application/flow/flow-service.js.map +1 -1
- package/dist/application/flow/internal-drive.js +16 -13
- package/dist/application/flow/internal-drive.js.map +1 -1
- package/dist/application/flow/run-state-service.js +236 -5
- package/dist/application/flow/run-state-service.js.map +1 -1
- package/dist/application/flow/submit.js +90 -35
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/history-table.js +253 -56
- package/dist/application/history-table.js.map +1 -1
- package/dist/application/history-update-service.js +85 -14
- package/dist/application/history-update-service.js.map +1 -1
- package/dist/application/lifecycle-target.js +2 -2
- package/dist/application/lifecycle-target.js.map +1 -1
- package/dist/application/paths-service.js +17 -0
- package/dist/application/paths-service.js.map +1 -1
- package/dist/application/resume-service.js +2 -9
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/session-close-service.js +13 -2
- package/dist/application/session-close-service.js.map +1 -1
- package/dist/application/session-create-service.js +4 -25
- package/dist/application/session-create-service.js.map +1 -1
- package/dist/application/session-narrative.js +7 -3
- package/dist/application/session-narrative.js.map +1 -1
- package/dist/application/session-resolver.js +124 -17
- package/dist/application/session-resolver.js.map +1 -1
- package/dist/application/session-resume-service.js +7 -0
- package/dist/application/session-resume-service.js.map +1 -1
- package/dist/application/sessions-service.js +7 -6
- package/dist/application/sessions-service.js.map +1 -1
- package/dist/cli/commands/checkpoint-write.js +1 -0
- package/dist/cli/commands/checkpoint-write.js.map +1 -1
- package/dist/cli/commands/flow.js +52 -5
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/history-update.js +25 -4
- package/dist/cli/commands/history-update.js.map +1 -1
- package/dist/cli/commands/index.js +4 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/session-close.js +12 -0
- package/dist/cli/commands/session-close.js.map +1 -1
- package/dist/cli/help-groups.js +4 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/parser.js +5 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/domain/capability/effects.js +13 -0
- package/dist/domain/capability/effects.js.map +1 -1
- package/dist/domain/flow/answer.js +105 -0
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +4 -0
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/run-state.js +215 -11
- package/dist/domain/flow/run-state.js.map +1 -1
- package/package.json +1 -1
- package/skills/w/loops/CHASSIS.md +5 -7
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* which state, one write.
|
|
7
7
|
*/
|
|
8
8
|
import { journeyOfFlow } from "../../domain/flow/authority.js";
|
|
9
|
-
import { newRunState } from "../../domain/flow/run-state.js";
|
|
9
|
+
import { MAX_BOUNDARY_ATTEMPTS, attemptsAt, checkAgainstJourney, grantAttempts, newRunState, recoveryBlockedAt, } from "../../domain/flow/run-state.js";
|
|
10
10
|
import { WORKLINE_FLOWS } from "../capability/compose.js";
|
|
11
11
|
import { recordFlowAdoption } from "../session-custody-recorder.js";
|
|
12
12
|
import { resolveSessionTarget } from "../session-resolver.js";
|
|
13
|
-
import { advanceFlowRun } from "./advance.js";
|
|
13
|
+
import { advanceFlowRun, directiveFor, resolveBoundary } from "./advance.js";
|
|
14
14
|
import { driveInternalActions } from "./internal-drive.js";
|
|
15
15
|
import { applyUnderLock, locateRun } from "./run-state-service.js";
|
|
16
16
|
export async function advanceFlow(fs, paths, input) {
|
|
@@ -58,6 +58,104 @@ export async function advanceFlow(fs, paths, input) {
|
|
|
58
58
|
return { ok: false, failure: driven.failure };
|
|
59
59
|
return { ok: true, directive: driven.value };
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Give a boundary that ran out of attempts a way back to being answerable.
|
|
63
|
+
*
|
|
64
|
+
* The only supported exit from an exhausted boundary, and it exists because the
|
|
65
|
+
* alternative in the field was surgery on `.flow-run.json` — which the seal
|
|
66
|
+
* refuses when you edit it and ACCEPTS when you restore an older copy, so the
|
|
67
|
+
* only manual "fix" that worked was also the one that rolled the run back.
|
|
68
|
+
*
|
|
69
|
+
* What it does is deliberately narrow: it forgives the attempts spent at the
|
|
70
|
+
* boundary in force and nothing else. The cursor, the effect ledger, the
|
|
71
|
+
* authorizations, the seated proposal, the trace and every document and artifact
|
|
72
|
+
* of the session are untouched — recovering is not restarting, and a run that
|
|
73
|
+
* came back with its applied transitions rolled back would be a worse outcome
|
|
74
|
+
* than the block it replaces.
|
|
75
|
+
*/
|
|
76
|
+
export async function recoverFlowBoundary(fs, paths, input) {
|
|
77
|
+
const resolution = await resolveSessionTarget(fs, paths, {
|
|
78
|
+
...(input.code !== undefined ? { code: input.code } : {}),
|
|
79
|
+
...(input.contextId !== undefined ? { contextId: input.contextId } : {}),
|
|
80
|
+
allowClosed: false,
|
|
81
|
+
bind: true,
|
|
82
|
+
});
|
|
83
|
+
if (resolution.outcome !== "resolved")
|
|
84
|
+
return { ok: false, session: resolution };
|
|
85
|
+
const location = locateRun(paths, resolution.session.folder);
|
|
86
|
+
const applied = await applyUnderLock(fs, location, (current) => {
|
|
87
|
+
if (current === null) {
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
failure: {
|
|
91
|
+
code: "FLOW_RUN_ABSENT",
|
|
92
|
+
message: "no hay corrida que recuperar en esta sesión",
|
|
93
|
+
action: "adoptala primero con 'aw flow advance --flow <flow> --adopt'",
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return recover(current, input.transition ?? null);
|
|
98
|
+
});
|
|
99
|
+
if (!applied.ok)
|
|
100
|
+
return { ok: false, failure: applied.failure };
|
|
101
|
+
return { ok: true, directive: applied.value };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The recovery decision, pure over the state read under the lock.
|
|
105
|
+
*
|
|
106
|
+
* Two refusals and one grant. It does NOT advance afterwards: returning
|
|
107
|
+
* answerability is the whole operation, and walking on from here would mean a
|
|
108
|
+
* command whose job is to unblock could also apply transitions — including,
|
|
109
|
+
* where the boundary is a delegated one, re-running the very action that failed.
|
|
110
|
+
*/
|
|
111
|
+
function recover(state, named) {
|
|
112
|
+
const journey = journeyOfFlow(state.flow);
|
|
113
|
+
const incoherent = checkAgainstJourney(state, journey);
|
|
114
|
+
if (incoherent !== null)
|
|
115
|
+
return { ok: false, failure: incoherent };
|
|
116
|
+
const stopped = resolveBoundary(state, journey).stopped;
|
|
117
|
+
if (stopped === null) {
|
|
118
|
+
return refuse("FLOW_RECOVERY_NOT_NEEDED", "el recorrido ya terminó: no hay ninguna frontera trabada", "no queda trabajo pendiente en este recorrido");
|
|
119
|
+
}
|
|
120
|
+
if (named !== null && named !== stopped.id) {
|
|
121
|
+
return refuse("FLOW_RECOVERY_OTHER_BOUNDARY", `la corrida está detenida en '${stopped.id}' y se pidió recuperar '${named}'`, `se recupera la frontera vigente: volvé a invocar sin --transition, o con --transition ${stopped.id}`);
|
|
122
|
+
}
|
|
123
|
+
const spent = attemptsAt(state, stopped.id);
|
|
124
|
+
if (spent < MAX_BOUNDARY_ATTEMPTS) {
|
|
125
|
+
return refuse("FLOW_RECOVERY_NOT_NEEDED", `'${stopped.id}' gastó ${spent} de ${MAX_BOUNDARY_ATTEMPTS} intentos: todavía se contesta`, "respondé la frontera vigente con 'aw flow submit': recuperar no es una forma de saltearla");
|
|
126
|
+
}
|
|
127
|
+
// The guard, and it reads the material trace rather than the effect ledger: the
|
|
128
|
+
// ledger is run-wide and cannot say WHICH boundary applied what. Handing back an
|
|
129
|
+
// answerable boundary whose action already reached the world would invite a
|
|
130
|
+
// second answer on top of a half-applied one — and no attempt is worth that.
|
|
131
|
+
const blocked = recoveryBlockedAt(state, stopped.id);
|
|
132
|
+
if (blocked !== null)
|
|
133
|
+
return refuseRecovery(stopped.id, blocked);
|
|
134
|
+
const recovered = grantAttempts(state, stopped.id, spent);
|
|
135
|
+
const built = directiveFor(recovered, resolveBoundary(recovered, journey), []);
|
|
136
|
+
if (!built.ok)
|
|
137
|
+
return { ok: false, failure: built.failure };
|
|
138
|
+
return { ok: true, state: built.state, value: built.directive };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The two ways a boundary refuses to be handed back, said as what to do next.
|
|
142
|
+
*
|
|
143
|
+
* They are not the same dead end and must not read as one. A boundary that
|
|
144
|
+
* APPLIED something is over: the run has to be repaired outside itself, because
|
|
145
|
+
* a second answer would land on top of an effect that already happened. A
|
|
146
|
+
* boundary whose action was begun and never reported back is the opposite — the
|
|
147
|
+
* missing thing is the verdict, and running the advance produces it.
|
|
148
|
+
*/
|
|
149
|
+
function refuseRecovery(transition, blocked) {
|
|
150
|
+
if (blocked.reason === "unverified") {
|
|
151
|
+
return refuse("FLOW_RECOVERY_EXECUTION_UNVERIFIED", `'${transition}' dejó anotado que su acción se iba a ejecutar y nunca registró en qué terminó: nadie puede decir si tocó el mundo`, "no se devuelven intentos sobre una ejecución sin veredicto: corré 'aw flow advance' para que la acción vuelva a correr y deje su resultado, y recuperá después si hace falta");
|
|
152
|
+
}
|
|
153
|
+
const moved = blocked.event;
|
|
154
|
+
return refuse("FLOW_RECOVERY_EFFECTS_APPLIED", `'${transition}' ya ejerció efectos en esta corrida (${moved.operation}): no se devuelven intentos sobre algo que ya ocurrió`, `el estado queda igual: seguí la recuperación que declara la acción de la fila, o llevá el gap a '## Open questions' — ${moved.kind === "failed" ? moved.recovery : "revisá la traza de la corrida"}`);
|
|
155
|
+
}
|
|
156
|
+
function refuse(code, message, action) {
|
|
157
|
+
return { ok: false, failure: { code, message, action } };
|
|
158
|
+
}
|
|
61
159
|
/**
|
|
62
160
|
* The state a legacy session gets when it is adopted.
|
|
63
161
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-service.js","sourceRoot":"","sources":["../../../src/application/flow/flow-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,
|
|
1
|
+
{"version":3,"file":"flow-service.js","sourceRoot":"","sources":["../../../src/application/flow/flow-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
import { internalActionOf, journeyOfFlow, } from "../../domain/flow/authority.js";
|
|
33
33
|
import { stepOf } from "../../domain/flow/directive.js";
|
|
34
34
|
import { executionVerdict } from "../../domain/flow/execution-result.js";
|
|
35
|
-
import { applyTransition, withActionAttempted, withBoundary, withEvent, withPendingAction, withProposal, } from "../../domain/flow/run-state.js";
|
|
35
|
+
import { applyTransition, restatesLastEvent, withActionAttempted, withAttempt, withBoundary, withEvent, withPendingAction, withProposal, } from "../../domain/flow/run-state.js";
|
|
36
36
|
import { semanticDigest } from "../semantic-operation/protocol.js";
|
|
37
37
|
import { sessionNumericCode } from "../session-resolver.js";
|
|
38
|
-
import { advanceFlowRun, directiveFor, effectsOfTransition, resolveBoundary } from "./advance.js";
|
|
38
|
+
import { advanceFlowRun, directiveFor, effectsOfTransition, failedExecutionAttempt, resolveBoundary, } from "./advance.js";
|
|
39
39
|
import { applyUnderLock } from "./run-state-service.js";
|
|
40
40
|
/**
|
|
41
41
|
* How many internal actions one invocation may chain.
|
|
@@ -185,12 +185,24 @@ function accept(state, pending, outcome) {
|
|
|
185
185
|
// the trace is where "which precondition was missing" has to survive.
|
|
186
186
|
message: outcome.summary,
|
|
187
187
|
recovery: verdict.detail.action,
|
|
188
|
+
// What it applied ANYWAY. A failed operation that got partway is the case
|
|
189
|
+
// where handing the boundary back as answerable would put a second answer
|
|
190
|
+
// on top of a half-applied effect, and this is the only record of it.
|
|
191
|
+
effects: [...outcome.effects],
|
|
188
192
|
};
|
|
189
193
|
// Re-running `aw flow advance` over a boundary nobody has fixed yet reaches
|
|
190
194
|
// exactly this point again, and appending the identical event every time would
|
|
191
195
|
// turn the trace into a retry counter. The same failure, still standing, is one
|
|
192
|
-
// fact — the attempt history is where "how many times" belongs
|
|
193
|
-
|
|
196
|
+
// fact — the attempt history is where "how many times" belongs, and that is
|
|
197
|
+
// charged right below, every time, precisely because the event is not.
|
|
198
|
+
const traced = restatesLastEvent(state, failure) ? state : withEvent(state, failure);
|
|
199
|
+
// The try the cap counts: the action RAN and came back refused. Charged here
|
|
200
|
+
// rather than on the way into the next advance, so somebody who fixes the
|
|
201
|
+
// cause gets the run that would have worked instead of a degradation.
|
|
202
|
+
const failed = withAttempt(traced, failedExecutionAttempt(traced, pending.decision, {
|
|
203
|
+
code: verdict.detail.code,
|
|
204
|
+
message: outcome.summary,
|
|
205
|
+
}));
|
|
194
206
|
const resolved = resolveBoundary(failed, journey);
|
|
195
207
|
const built = directiveFor(failed, resolved, [], {
|
|
196
208
|
...(verdict.detail.outcome === undefined ? {} : { outcome: verdict.detail.outcome }),
|
|
@@ -248,15 +260,6 @@ function accept(state, pending, outcome) {
|
|
|
248
260
|
value: { directive: advanced.directive, advanced: true },
|
|
249
261
|
};
|
|
250
262
|
}
|
|
251
|
-
/** Whether the trace's last event is this same failure, unchanged. */
|
|
252
|
-
function repeats(state, failure) {
|
|
253
|
-
const last = state.events.at(-1);
|
|
254
|
-
if (last === undefined || last.kind !== "failed")
|
|
255
|
-
return false;
|
|
256
|
-
return (last.transition === failure.transition &&
|
|
257
|
-
last.code === failure.code &&
|
|
258
|
-
last.message === failure.message);
|
|
259
|
-
}
|
|
260
263
|
/**
|
|
261
264
|
* The outcome, expressed in the result protocol an external executor would send.
|
|
262
265
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal-drive.js","sourceRoot":"","sources":["../../../src/application/flow/internal-drive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,EAIL,gBAAgB,EAChB,aAAa,GACd,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAGL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,YAAY,GACb,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,
|
|
1
|
+
{"version":3,"file":"internal-drive.js","sourceRoot":"","sources":["../../../src/application/flow/internal-drive.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,15 +12,45 @@
|
|
|
12
12
|
* before the single write happens, so a failure halfway through leaves the
|
|
13
13
|
* previous state exactly as it was rather than a half-applied one.
|
|
14
14
|
*/
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
import { FLOW_RUN_STATE_FILE, parseRunState, serializeRunState, } from "../../domain/flow/run-state.js";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { FLOW_RUN_STATE_FILE, atCurrentVersion, parseRunState, serializeRunState, withAttemptCounters, } from "../../domain/flow/run-state.js";
|
|
17
17
|
import { LockBusyError, acquireLock } from "../lock-service.js";
|
|
18
|
+
import { semanticDigest } from "../semantic-operation/protocol.js";
|
|
19
|
+
/**
|
|
20
|
+
* The attempt counter: outside the run state's seal, and outside its FOLDER.
|
|
21
|
+
*
|
|
22
|
+
* Two evasions, and the file's location answers the second one. The seal proved
|
|
23
|
+
* it detects an edit and does not detect a restore: copying an earlier
|
|
24
|
+
* `.flow-run.json` back over the current one is accepted — the file is
|
|
25
|
+
* internally consistent, because it really was written by this CLI — and it
|
|
26
|
+
* takes the attempt ledger back with it. So the count lives in a second file
|
|
27
|
+
* that only ever grows. But while that file sat NEXT to the state, inside the
|
|
28
|
+
* session folder, a `cp -r` of the folder carried both away and back, and
|
|
29
|
+
* deleting it reset the cap: the counter defended against restoring a file and
|
|
30
|
+
* fell to restoring the directory that contained it, which is the same move one
|
|
31
|
+
* level up.
|
|
32
|
+
*
|
|
33
|
+
* Now it is workspace runtime — `.<ns>/sessions/.flow-attempts/<folder>.json`,
|
|
34
|
+
* keyed by the session it counts, dot-prefixed so the session listing skips it
|
|
35
|
+
* and already inside the gitignore the CLI manages. Restoring a session folder
|
|
36
|
+
* cannot lower it, deleting the folder cannot delete it, and a recovery does not
|
|
37
|
+
* delete it either: it records how many attempts were given back. See
|
|
38
|
+
* `attemptsAt`.
|
|
39
|
+
*
|
|
40
|
+
* One file per run rather than one registry for the workspace, because two runs
|
|
41
|
+
* advance concurrently under two DIFFERENT locks: a shared registry would need a
|
|
42
|
+
* lock of its own, and losing that race would silently drop a run's floor —
|
|
43
|
+
* rebuilding the very hole the file exists to close.
|
|
44
|
+
*/
|
|
45
|
+
const COUNTER_VERSION = 2;
|
|
46
|
+
const NO_COUNTERS = { attempts: {}, granted: {} };
|
|
18
47
|
export function locateRun(paths, session) {
|
|
19
48
|
const dir = join(paths.cwdSessionsDir(), session);
|
|
20
49
|
return {
|
|
21
50
|
session,
|
|
22
51
|
dir,
|
|
23
52
|
statePath: join(dir, FLOW_RUN_STATE_FILE),
|
|
53
|
+
countersPath: paths.cwdFlowAttemptsFile(session),
|
|
24
54
|
lockPath: join(dir, `${FLOW_RUN_STATE_FILE}.lock`),
|
|
25
55
|
};
|
|
26
56
|
}
|
|
@@ -43,7 +73,187 @@ export async function readRun(fs, location) {
|
|
|
43
73
|
},
|
|
44
74
|
};
|
|
45
75
|
}
|
|
46
|
-
|
|
76
|
+
const parsed = parseRunState(await fs.readText(location.statePath));
|
|
77
|
+
if (!parsed.ok)
|
|
78
|
+
return parsed;
|
|
79
|
+
// Reconciled on the way OUT, never on the way in: whoever restored an older
|
|
80
|
+
// state has already handed it to us, and raising the floor here is what makes
|
|
81
|
+
// the restore worthless. Every reader goes through this function, so no surface
|
|
82
|
+
// of the CLI can see a run with attempts the counter says were already spent.
|
|
83
|
+
const counters = await readCounters(fs, location);
|
|
84
|
+
if (!counters.ok)
|
|
85
|
+
return counters;
|
|
86
|
+
const rolledBack = checkAgainstSealedFloor(parsed.state, counters.value);
|
|
87
|
+
if (rolledBack !== null)
|
|
88
|
+
return { ok: false, failure: rolledBack };
|
|
89
|
+
return {
|
|
90
|
+
ok: true,
|
|
91
|
+
state: withAttemptCounters(atCurrentVersion(parsed.state), {
|
|
92
|
+
floor: counters.value.attempts,
|
|
93
|
+
grants: counters.value.granted,
|
|
94
|
+
}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether the counter came back BEHIND the floor the state itself carries sealed.
|
|
99
|
+
*
|
|
100
|
+
* The write order is the counter first and the state second, so the counter is
|
|
101
|
+
* never behind: a process that dies between the two leaves it AHEAD, which costs
|
|
102
|
+
* an attempt nobody spent, and that is the only one of the two errors that is
|
|
103
|
+
* safe to make. The reverse cannot happen by running this CLI. It happens when
|
|
104
|
+
* the counter file is deleted, truncated or replaced by an older copy while the
|
|
105
|
+
* state stays — surgery on the accounting, and the only evidence of it that
|
|
106
|
+
* survives inside the seal.
|
|
107
|
+
*
|
|
108
|
+
* Refused rather than rebuilt. Rebuilding from the state is precisely what the
|
|
109
|
+
* counter exists to not do: the state is the file a restore rolls back, and
|
|
110
|
+
* seeding the floor from it would hand the evader the reset they came for while
|
|
111
|
+
* calling it a repair.
|
|
112
|
+
*/
|
|
113
|
+
function checkAgainstSealedFloor(state, counters) {
|
|
114
|
+
const behind = (sealed, live) => Object.entries(sealed ?? {}).find(([transition, count]) => count > (live[transition] ?? 0));
|
|
115
|
+
const lost = behind(state.attempt_floor, counters.attempts) ??
|
|
116
|
+
behind(state.attempt_grants, counters.granted);
|
|
117
|
+
if (lost === undefined)
|
|
118
|
+
return null;
|
|
119
|
+
return {
|
|
120
|
+
code: "FLOW_RUN_COUNTER_ROLLED_BACK",
|
|
121
|
+
message: `el contador de intentos quedó detrás del estado sellado: '${lost[0]}' declara ${lost[1]} y el contador no los tiene`,
|
|
122
|
+
action: "el contador se borró o se restauró una copia anterior: restaurá el archivo de intentos de la corrida, o descartá la corrida entera y re-adoptá la sesión con 'aw flow advance --flow <flow> --adopt' — no se reconstruye desde el estado, que es justo lo que una restauración rebobina",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The counter as it stands, or the conservative reading when there is none.
|
|
127
|
+
*
|
|
128
|
+
* An ABSENT file is the normal state of every run that started before the counter
|
|
129
|
+
* existed, and of every run that has not spent an attempt yet: it reads as "no
|
|
130
|
+
* floor beyond the ledger", the run keeps walking, and the next write seeds the
|
|
131
|
+
* file from the ledger it already has. Absence is not a hole — a state that DID
|
|
132
|
+
* spend attempts carries their floor inside its own seal, so an absent counter
|
|
133
|
+
* under such a state is caught by {@link checkAgainstSealedFloor} rather than
|
|
134
|
+
* read as zero.
|
|
135
|
+
*
|
|
136
|
+
* Everything else is refused with a cause, and the checks are the state file's
|
|
137
|
+
* own, in the same order: shape, then version, then the SEAL, then coherence.
|
|
138
|
+
* This file is read fail-closed for exactly the reason the state is — it was the
|
|
139
|
+
* surface added to resist manipulation, and while it was the only unsealed file
|
|
140
|
+
* of the run it was also the easiest one to manipulate: writing `granted: 99`
|
|
141
|
+
* into it turned the cap off for good.
|
|
142
|
+
*/
|
|
143
|
+
async function readCounters(fs, location) {
|
|
144
|
+
if (!(await fs.exists(location.countersPath)))
|
|
145
|
+
return { ok: true, value: NO_COUNTERS };
|
|
146
|
+
const refuse = (why) => ({
|
|
147
|
+
ok: false,
|
|
148
|
+
failure: {
|
|
149
|
+
code: "FLOW_RUN_COUNTER_INVALID",
|
|
150
|
+
message: `el contador de intentos de la corrida ${why}`,
|
|
151
|
+
action: "no se avanza con una contabilidad de intentos ilegible ni con una que fue editada fuera del CLI: restaurá el archivo, o descartá la corrida entera y re-adoptá la sesión con 'aw flow advance --flow <flow> --adopt'",
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
let parsed;
|
|
155
|
+
try {
|
|
156
|
+
parsed = JSON.parse(await fs.readText(location.countersPath));
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return refuse("no es JSON válido");
|
|
160
|
+
}
|
|
161
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
162
|
+
return refuse("no es un objeto JSON");
|
|
163
|
+
}
|
|
164
|
+
const record = parsed;
|
|
165
|
+
if (record.version !== COUNTER_VERSION) {
|
|
166
|
+
return refuse(`declara una versión que este CLI no lee: ${String(record.version)}`);
|
|
167
|
+
}
|
|
168
|
+
const attempts = readCounterMap(record.attempts);
|
|
169
|
+
const granted = readCounterMap(record.granted);
|
|
170
|
+
if (attempts === null || granted === null)
|
|
171
|
+
return refuse("no es un contador por transición");
|
|
172
|
+
const value = { attempts, granted };
|
|
173
|
+
if (record.digest !== counterDigest(location.session, value)) {
|
|
174
|
+
return refuse("no coincide con su propio sello");
|
|
175
|
+
}
|
|
176
|
+
// A grant is what a recovery forgave, and forgiving more than was ever spent
|
|
177
|
+
// is not a state this CLI can produce: `raiseCounters` only ever copies the
|
|
178
|
+
// grants the state recorded, and a recovery grants exactly what it found
|
|
179
|
+
// spent. A file that says otherwise is asking for a cap that never fires.
|
|
180
|
+
const forgiven = Object.entries(granted).find(([id, count]) => count > (attempts[id] ?? 0));
|
|
181
|
+
if (forgiven !== undefined) {
|
|
182
|
+
return refuse(`perdona ${forgiven[1]} intentos de '${forgiven[0]}' y solo registra ${attempts[forgiven[0]] ?? 0}`);
|
|
183
|
+
}
|
|
184
|
+
return { ok: true, value };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The counter's seal — the same canonicalization the rest of the protocol uses.
|
|
188
|
+
*
|
|
189
|
+
* The SESSION is inside it, and not as decoration: the file lives in a shared
|
|
190
|
+
* runtime folder keyed by folder name, so sealing the key is what makes one run's
|
|
191
|
+
* counter unusable as another's.
|
|
192
|
+
*/
|
|
193
|
+
function counterDigest(session, counters) {
|
|
194
|
+
return semanticDigest({ version: COUNTER_VERSION, session, ...counters });
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Raise the counter to what this state knows, and hand the state back reconciled.
|
|
198
|
+
*
|
|
199
|
+
* Monotone by construction on both halves: the attempts seen can only go up —
|
|
200
|
+
* `Math.max` against what the file already said — and the grants a recovery
|
|
201
|
+
* recorded come from the state, which only ever adds to them. A state written
|
|
202
|
+
* from a restored ledger therefore raises nothing and gets the live floor back.
|
|
203
|
+
*/
|
|
204
|
+
async function raiseCounters(fs, location, state) {
|
|
205
|
+
const current = await readCounters(fs, location);
|
|
206
|
+
if (!current.ok)
|
|
207
|
+
return current;
|
|
208
|
+
const spent = new Map();
|
|
209
|
+
for (const attempt of state.attempts) {
|
|
210
|
+
spent.set(attempt.transition, (spent.get(attempt.transition) ?? 0) + 1);
|
|
211
|
+
}
|
|
212
|
+
const attempts = { ...current.value.attempts };
|
|
213
|
+
for (const [transition, count] of spent) {
|
|
214
|
+
attempts[transition] = Math.max(attempts[transition] ?? 0, count);
|
|
215
|
+
}
|
|
216
|
+
const granted = { ...current.value.granted };
|
|
217
|
+
for (const [transition, forgiven] of Object.entries(state.attempt_grants ?? {})) {
|
|
218
|
+
granted[transition] = Math.max(granted[transition] ?? 0, forgiven);
|
|
219
|
+
}
|
|
220
|
+
const next = { attempts, granted };
|
|
221
|
+
if (changed(current.value, next))
|
|
222
|
+
await writeCounters(fs, location, next);
|
|
223
|
+
return { ok: true, state: withAttemptCounters(state, { floor: attempts, grants: granted }) };
|
|
224
|
+
}
|
|
225
|
+
async function writeCounters(fs, location, counters) {
|
|
226
|
+
await fs.mkdirp(dirname(location.countersPath));
|
|
227
|
+
await fs.writeText(location.countersPath, `${JSON.stringify({
|
|
228
|
+
version: COUNTER_VERSION,
|
|
229
|
+
session: location.session,
|
|
230
|
+
...counters,
|
|
231
|
+
digest: counterDigest(location.session, counters),
|
|
232
|
+
}, null, 2)}\n`);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Start the counter over for a run that is being created.
|
|
236
|
+
*
|
|
237
|
+
* The file goes rather than being zeroed, so an adopted run is byte-identical to
|
|
238
|
+
* one that never had a counter: the next attempt seeds it again from the ledger.
|
|
239
|
+
*/
|
|
240
|
+
async function resetCounters(fs, location, state) {
|
|
241
|
+
await fs.remove(location.countersPath);
|
|
242
|
+
return { ok: true, state: withAttemptCounters(state, { floor: {}, grants: {} }) };
|
|
243
|
+
}
|
|
244
|
+
function changed(before, after) {
|
|
245
|
+
return (JSON.stringify(before.attempts) !== JSON.stringify(after.attempts) ||
|
|
246
|
+
JSON.stringify(before.granted) !== JSON.stringify(after.granted));
|
|
247
|
+
}
|
|
248
|
+
function readCounterMap(value) {
|
|
249
|
+
if (value === undefined)
|
|
250
|
+
return {};
|
|
251
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
252
|
+
return null;
|
|
253
|
+
const entries = Object.entries(value);
|
|
254
|
+
if (!entries.every(([, count]) => Number.isInteger(count) && count >= 0))
|
|
255
|
+
return null;
|
|
256
|
+
return Object.fromEntries(entries);
|
|
47
257
|
}
|
|
48
258
|
/**
|
|
49
259
|
* Run one mutation under the run's lock and persist its result.
|
|
@@ -95,10 +305,31 @@ export async function applyUnderLock(fs, location, mutate, options = {}) {
|
|
|
95
305
|
return result;
|
|
96
306
|
if (result.persist === false)
|
|
97
307
|
return result;
|
|
308
|
+
// The counter first, the state second, and the order is the contract. If the
|
|
309
|
+
// process dies between them the counter is AHEAD of the ledger, which costs
|
|
310
|
+
// an attempt nobody spent; the other order would leave it BEHIND, which is an
|
|
311
|
+
// attempt somebody spent and can spend again. Only one of those two errors is
|
|
312
|
+
// safe to make.
|
|
313
|
+
//
|
|
314
|
+
// An ADOPTION is the one case that starts the counter over, and it is not a
|
|
315
|
+
// loophole in the monotonicity: a state that was absent means this run is
|
|
316
|
+
// being created now, and the only way to get there deliberately is to throw
|
|
317
|
+
// the previous run away whole — every applied transition with it. What the
|
|
318
|
+
// counter defends against is keeping the position and losing the attempts;
|
|
319
|
+
// paying for a reset with the entire run is not that trade. Keeping the old
|
|
320
|
+
// count would be worse than useless: re-adopting after a corrupt state — the
|
|
321
|
+
// repair this CLI prints — would come back pre-exhausted at its first gate.
|
|
322
|
+
const raised = state === null
|
|
323
|
+
? await resetCounters(fs, location, result.state)
|
|
324
|
+
: await raiseCounters(fs, location, result.state);
|
|
325
|
+
if (!raised.ok)
|
|
326
|
+
return raised;
|
|
98
327
|
// One write, after the next state is complete and sealed: nothing partial
|
|
99
328
|
// can be observed because nothing partial is ever written.
|
|
100
|
-
await fs.writeText(location.statePath, serializeRunState(
|
|
101
|
-
|
|
329
|
+
await fs.writeText(location.statePath, serializeRunState(raised.state));
|
|
330
|
+
// The reconciled state is what the caller gets back, because the digest it
|
|
331
|
+
// holds is the one the next compare-and-swap will be judged against.
|
|
332
|
+
return { ...result, state: raised.state };
|
|
102
333
|
}
|
|
103
334
|
finally {
|
|
104
335
|
await lock.release();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-state-service.js","sourceRoot":"","sources":["../../../src/application/flow/run-state-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"run-state-service.js","sourceRoot":"","sources":["../../../src/application/flow/run-state-service.ts"],"names":[],"mappings":"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"}
|