@feigi/fleet-ctl 3.82.18 → 3.82.19
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/package.json
CHANGED
package/scripts/ledger.mjs
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
// every liveness count from this file alone, rather than from row text a
|
|
14
14
|
// controller typed by hand: `dispatch` writes a member's live token onto its
|
|
15
15
|
// row and appends it to `## Dispatched` with `brief=<hash>`, the brief it
|
|
16
|
-
// refuses to dispatch without
|
|
16
|
+
// refuses to dispatch without; when that brief's sidecar names an absolute
|
|
17
|
+
// scratch, it also clears the member's report file there, so a prior run's
|
|
18
|
+
// report is not read as this run's; `settle` rewrites that token to
|
|
17
19
|
// `<member>=<outcome>` in both places (an implementer's settle to `PR#M` also
|
|
18
20
|
// folds the PR's own `#M` row into its ticket's) — with `--from-report`, the
|
|
19
21
|
// outcome derived from the member's report file and checked against git and
|
|
@@ -46,7 +48,7 @@
|
|
|
46
48
|
|
|
47
49
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync, unlinkSync, linkSync } from "node:fs";
|
|
48
50
|
import { createHash } from "node:crypto";
|
|
49
|
-
import { dirname, resolve, join, basename } from "node:path";
|
|
51
|
+
import { dirname, resolve, join, basename, isAbsolute } from "node:path";
|
|
50
52
|
import { fileURLToPath } from "node:url";
|
|
51
53
|
import { spawnSync, execFileSync } from "node:child_process";
|
|
52
54
|
import { makeDie, isFlagLike, hasEqualsForm, isDigits, writeAll } from "./arg.mjs";
|
|
@@ -56,7 +58,7 @@ import { deriveRun, LedgerError, labelOffMember, HELD, CONFLICT_HOLD } from "./f
|
|
|
56
58
|
import { stateFileIn, readState, writeState, assessBeat, stallsAt } from "./fleet-state.mjs";
|
|
57
59
|
import { processSource, ancestry, controllerOf, judgeController, ProcUnreadable } from "./proc.mjs";
|
|
58
60
|
import { attemptLock, releaseLockFile, reapPathOf } from "./pid-lock.mjs";
|
|
59
|
-
import { readCheckRecordIn, readReportIn, reportsDir, reportFamily, defaultScratch } from "./report-files.mjs";
|
|
61
|
+
import { readCheckRecordIn, readReportIn, reportsDir, reportFamily, defaultScratch, reportPath } from "./report-files.mjs";
|
|
60
62
|
|
|
61
63
|
const NAME = "ledger";
|
|
62
64
|
// The plugin's own agent definitions — the directory tier-check.mjs reads
|
|
@@ -2032,7 +2034,12 @@ function runDispatch() {
|
|
|
2032
2034
|
|
|
2033
2035
|
// Last, so every refusal above still names its own cause first, and before
|
|
2034
2036
|
// anything is written.
|
|
2035
|
-
const brief = renderedBrief(member.name, memberRole(member.family));
|
|
2037
|
+
const { brief, scratch } = renderedBrief(member.name, memberRole(member.family));
|
|
2038
|
+
|
|
2039
|
+
// The report a prior run left for this member is that run's last claim.
|
|
2040
|
+
// Cleared here, after every refusal above, so settle --from-report and the
|
|
2041
|
+
// tick's SETTLE row cannot read it as this run's.
|
|
2042
|
+
clearReport(scratch, member.name);
|
|
2036
2043
|
|
|
2037
2044
|
let line = null;
|
|
2038
2045
|
const created = member.bound !== null && i === -1;
|
|
@@ -2059,9 +2066,11 @@ function runDispatch() {
|
|
|
2059
2066
|
// --member <name>` left it in the briefs directory beside the ledger: the
|
|
2060
2067
|
// sidecar `<name>.json` must exist, name `role` — the template of the
|
|
2061
2068
|
// member's family — and carry the brief's sha256, and the brief file beside
|
|
2062
|
-
// it, `<name>.md`, must exist and hash to it. `{path, sha256}
|
|
2063
|
-
// `path` that file, so the controller hands the `task`
|
|
2064
|
-
// the path printed
|
|
2069
|
+
// it, `<name>.md`, must exist and hash to it. `{brief: {path, sha256},
|
|
2070
|
+
// scratch}` comes back, `path` that file, so the controller hands the `task`
|
|
2071
|
+
// call its content from the path printed, and `scratch` the sidecar's
|
|
2072
|
+
// `args.scratch` when it is an absolute path, else null. Refused, nothing is
|
|
2073
|
+
// written.
|
|
2065
2074
|
function renderedBrief(name, role) {
|
|
2066
2075
|
const dir = resolve(dirname(file), BRIEFS);
|
|
2067
2076
|
const sidecar = join(dir, `${name}.json`);
|
|
@@ -2098,7 +2107,28 @@ function renderedBrief(name, role) {
|
|
|
2098
2107
|
if (actual !== s.sha256) {
|
|
2099
2108
|
die(`${path} hashes to ${actual}, but ${sidecar} carries ${s.sha256} — ${render}`);
|
|
2100
2109
|
}
|
|
2101
|
-
|
|
2110
|
+
const scratch = typeof s.args?.scratch === "string" && isAbsolute(s.args.scratch) ? s.args.scratch : null;
|
|
2111
|
+
return { brief: { path, sha256: s.sha256 }, scratch };
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
// Removes `name`'s report under `scratch`, the last run's claim about the
|
|
2115
|
+
// member, if one is there. A null `scratch` — the brief's sidecar named none —
|
|
2116
|
+
// clears nothing and says so, since the report's location is then unknown.
|
|
2117
|
+
function clearReport(scratch, name) {
|
|
2118
|
+
if (scratch === null) {
|
|
2119
|
+
console.error(`${NAME}: WARNING ${name}'s brief sidecar names no scratch, so its prior report was not cleared`);
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
const path = reportPath(scratch, name);
|
|
2123
|
+
try {
|
|
2124
|
+
unlinkSync(path);
|
|
2125
|
+
} catch (e) {
|
|
2126
|
+
// ENOTDIR: something other than a directory sits where `reports` would
|
|
2127
|
+
// be, so no report is there either — readReportIn and the tick's
|
|
2128
|
+
// readReports read it as absent too.
|
|
2129
|
+
if (e.code === "ENOENT" || e.code === "ENOTDIR") return;
|
|
2130
|
+
die(`cannot clear ${path}: ${e.message} — not dispatching ${name}`);
|
|
2131
|
+
}
|
|
2102
2132
|
}
|
|
2103
2133
|
|
|
2104
2134
|
// Whether `outcome` is one whose claim a member's report carries and `settle
|
|
@@ -375,7 +375,12 @@ the `render` command to run first, and refuses once the
|
|
|
375
375
|
run is draining: drain stops supply. It also refuses a row whose `tier=`
|
|
376
376
|
names no single definition — two different values, or one that is not a
|
|
377
377
|
definition suffix — or names one with no `agents/<definition>.agent.md`,
|
|
378
|
-
before the member is live; fix the row with `row` first.
|
|
378
|
+
before the member is live; fix the row with `row` first. Once every refusal
|
|
379
|
+
has passed, `dispatch` deletes the member's prior report,
|
|
380
|
+
`<scratch>/reports/<member>.json`, when its brief's sidecar names an absolute
|
|
381
|
+
`scratch`, so a prior run's report cannot settle this one. A sidecar naming
|
|
382
|
+
none clears nothing and says so on stderr; a report it cannot remove refuses
|
|
383
|
+
the dispatch.
|
|
379
384
|
|
|
380
385
|
**The prompt carries only what varies.** Everything shared — the
|
|
381
386
|
unattended-member block, the `edit`/`read` absolute-path rule, the
|