@groundnuty/macf-core 0.2.48 → 0.2.49
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/fleet-driver.d.ts +93 -9
- package/dist/fleet-driver.d.ts.map +1 -1
- package/dist/fleet-driver.js.map +1 -1
- package/dist/fleet-upgrade.d.ts +163 -51
- package/dist/fleet-upgrade.d.ts.map +1 -1
- package/dist/fleet-upgrade.js +217 -76
- package/dist/fleet-upgrade.js.map +1 -1
- package/package.json +1 -1
package/dist/fleet-driver.d.ts
CHANGED
|
@@ -101,8 +101,12 @@ export interface FleetDriver {
|
|
|
101
101
|
/**
|
|
102
102
|
* The pre-flight config-dirty predicate (macf#722 Fix B) — `true` when the
|
|
103
103
|
* agent's workspace has UNCOMMITTED changes on the roll's touched-config
|
|
104
|
-
* surface (
|
|
105
|
-
*
|
|
104
|
+
* surface (the macf#725 UNION: the macf-update overwrite set ∪ the
|
|
105
|
+
* operator-evolution files — `claude.sh`, `.claude/rules/**`,
|
|
106
|
+
* `.claude/scripts/**`, `.claude/settings.json`, the managed
|
|
107
|
+
* `.claude/.macf/env.*` + `host-prelude.sh`, `CLAUDE.md`, `env.local.*` —
|
|
108
|
+
* see `ROLL_TOUCHED_CONFIG_PATTERNS` in `fleet-upgrade.ts`, narrowed off a
|
|
109
|
+
* `.claude/**` wildcard by DR-040 Decision 6 / macf#698). VM: `git status`
|
|
106
110
|
* in the agent's workspace, filtered to that path set. A DEAD/absent agent
|
|
107
111
|
* reads `false` (nothing to check; reconcile will launch it). Kept as a
|
|
108
112
|
* boolean convenience alongside `listDirtyConfig` below — `rollFleet`'s
|
|
@@ -113,18 +117,59 @@ export interface FleetDriver {
|
|
|
113
117
|
readonly isConfigDirty: (agent: string) => Promise<boolean>;
|
|
114
118
|
/**
|
|
115
119
|
* The pre-flight config-dirty gate's LIST form (macf#725 — transactional
|
|
116
|
-
* object-with-message revision
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* boolean, so the roll can OBJECT with a specific, actionable list instead
|
|
120
|
-
* of a bare skip — a dirty agent is SKIPPED before any mutation (never
|
|
121
|
-
* upgraded/restarted); `macf update` / restart-self would otherwise clobber
|
|
122
|
-
* or stash operator-authored config underneath it. Empty array == clean
|
|
120
|
+
* object-with-message revision). Same predicate surface as `isConfigDirty`
|
|
121
|
+
* (`ROLL_TOUCHED_CONFIG_PATTERNS`, tracked-only), but returns the actual
|
|
122
|
+
* uncommitted paths rather than a boolean. Empty array == clean
|
|
123
123
|
* (equivalent to `isConfigDirty` reading `false`). VM: `git status
|
|
124
124
|
* --porcelain` in the agent's workspace, filtered to that path set, one
|
|
125
125
|
* path per line.
|
|
126
|
+
*
|
|
127
|
+
* **Superseded as `rollFleet`'s pre-flight call site by `classifyDirtyConfig`
|
|
128
|
+
* below (DR-040 Decision 3 / macf#698 R1)** — the roll no longer treats
|
|
129
|
+
* every dirty file as an OBJECT-worthy delta; it tiers them first. This
|
|
130
|
+
* verb remains on the interface (still used internally by
|
|
131
|
+
* `classifyDirtyConfig`'s real implementation, and by other callers that
|
|
132
|
+
* only need the raw uncommitted-path list without tier classification).
|
|
126
133
|
*/
|
|
127
134
|
readonly listDirtyConfig: (agent: string) => Promise<readonly string[]>;
|
|
135
|
+
/**
|
|
136
|
+
* The pre-flight config-dirty gate's TIERED form (DR-040 Decision 3 /
|
|
137
|
+
* macf#698 R1 — this is what `rollFleet` actually calls now). Splits
|
|
138
|
+
* `listDirtyConfig`'s raw uncommitted-path list into two tiers by
|
|
139
|
+
* comparing each file's CURRENT (dirty) content against what `macf
|
|
140
|
+
* update` would write for it right now (the canonical-compute primitive,
|
|
141
|
+
* `packages/macf/src/cli/fleet/canonical-compute.ts`):
|
|
142
|
+
*
|
|
143
|
+
* - `alreadyCanonical` — the file's content already IS the canonical
|
|
144
|
+
* regen (the common case: a stale-branch workspace whose "dirty" files
|
|
145
|
+
* are exactly what a fresh `macf update` would produce — both code-agent
|
|
146
|
+
* AND science hit only this tier on the v0.2.48 roll). Safe to commit
|
|
147
|
+
* as-is; NEVER a genuine conflict.
|
|
148
|
+
* - `genuineDelta` — a real local difference from canonical. Still
|
|
149
|
+
* requires the OBJECT-and-halt treatment `listDirtyConfig`'s callers
|
|
150
|
+
* used to apply to the WHOLE dirty list.
|
|
151
|
+
*
|
|
152
|
+
* Both arrays are empty when the agent has no dirty config surface at all
|
|
153
|
+
* (mirrors `listDirtyConfig`'s empty-array-== -clean contract). VM: reuses
|
|
154
|
+
* `listDirtyConfig` for the raw list, then classifies each path via
|
|
155
|
+
* `classifyDirtyFile`.
|
|
156
|
+
*/
|
|
157
|
+
readonly classifyDirtyConfig: (agent: string) => Promise<{
|
|
158
|
+
readonly alreadyCanonical: readonly string[];
|
|
159
|
+
readonly genuineDelta: readonly string[];
|
|
160
|
+
}>;
|
|
161
|
+
/**
|
|
162
|
+
* Commit exactly `files` in the agent's workspace (DR-040 Decision 3 /
|
|
163
|
+
* macf#698 R1) — the auto-resolve half of the tier-first gate. Called ONLY
|
|
164
|
+
* with `classifyDirtyConfig`'s `alreadyCanonical` subset: those files are,
|
|
165
|
+
* by construction, deterministic canonical content (not an arbitrary
|
|
166
|
+
* commit), so committing them clears the false config-dirty signal
|
|
167
|
+
* without any agent/operator involvement. A no-op when `files` is empty.
|
|
168
|
+
* VM: `git add -- <files>` + `git commit` in the agent's workspace (a
|
|
169
|
+
* no-op commit, i.e. nothing actually staged after `add`, is tolerated —
|
|
170
|
+
* never throws on "nothing to commit").
|
|
171
|
+
*/
|
|
172
|
+
readonly autoResolveCanonical: (agent: string, files: readonly string[]) => Promise<void>;
|
|
128
173
|
/**
|
|
129
174
|
* Read the agent's current pane content for stall-signature matching
|
|
130
175
|
* (`macf fleet resume`, DR-037 / macf#686). VM: a single `tmux capture-pane`
|
|
@@ -178,6 +223,45 @@ export interface FleetDriver {
|
|
|
178
223
|
* on a diagnostic-only read).
|
|
179
224
|
*/
|
|
180
225
|
readonly listModifiedFiles: (agent: string) => Promise<readonly string[]>;
|
|
226
|
+
/**
|
|
227
|
+
* SET the maintenance lock for `agent` (DR-040 Decision 4,
|
|
228
|
+
* macf-devops-toolkit#158/#159 — the canonical "upgrade ≠ outage" contract).
|
|
229
|
+
* Create/overwrite (atomic write; `started_at`/`heartbeat_at` both = now).
|
|
230
|
+
* `rollFleet` calls this at the TOP of its per-agent transaction, BEFORE
|
|
231
|
+
* `upgrade`/`restart` touch the agent's process, so a watchdog sweep racing
|
|
232
|
+
* the very first SIGTERM already reads "planned maintenance," never
|
|
233
|
+
* "unplanned outage." VM: a lock FILE under
|
|
234
|
+
* `$MACF_MAINT_LOCK_DIR/<agent>.lock` (same-directory tempfile + `rename`,
|
|
235
|
+
* atomic); K8s (future): a pod annotation / ConfigMap patch — same
|
|
236
|
+
* four-verb contract, different storage (the MAINTENANCE-LOCK.md
|
|
237
|
+
* decision/driver split).
|
|
238
|
+
*/
|
|
239
|
+
readonly acquireLock: (agent: string, targetVersion: string) => Promise<void>;
|
|
240
|
+
/**
|
|
241
|
+
* RELEASE the maintenance lock for `agent` (idempotent — a no-op if none
|
|
242
|
+
* exists). `rollFleet` calls this ONLY on a confirmed clean GREEN roll — a
|
|
243
|
+
* HALTed roll deliberately LEAVES the lock in place (DR-040 Decision 3:
|
|
244
|
+
* the stale heartbeat is the crash-safety backstop, not an immediate
|
|
245
|
+
* release — see macf-devops-toolkit#158's "release ONLY on confirmed clean
|
|
246
|
+
* success"). Releasing on failure would hand a possibly-broken, mid-
|
|
247
|
+
* transition agent straight back to the watchdog's healing ladder the
|
|
248
|
+
* instant the roll fails — exactly the uncoordinated intervention the
|
|
249
|
+
* transactional halt exists to avoid.
|
|
250
|
+
*/
|
|
251
|
+
readonly releaseLock: (agent: string) => Promise<void>;
|
|
252
|
+
/**
|
|
253
|
+
* Start a BACKGROUND heartbeat loop refreshing `agent`'s maintenance lock —
|
|
254
|
+
* decoupled from `rollFleet`'s foreground awaits, because `upgrade` /
|
|
255
|
+
* `restart` / `verifyGreen` can each individually take a while and the
|
|
256
|
+
* heartbeat must not stall behind whichever step is currently running.
|
|
257
|
+
* Returns a synchronous STOP handle the caller invokes exactly once, on
|
|
258
|
+
* EITHER terminal branch (green or halt) — never both, and never omitted.
|
|
259
|
+
* VM: a bounded interval (period well under `MAINT_LOCK_TTL`), itself
|
|
260
|
+
* dead-man's-switch-bounded by `MAINT_LOCK_HEARTBEAT_MAX_S` so an orphaned
|
|
261
|
+
* loop (e.g. its parent process killed before the stop handle ever runs)
|
|
262
|
+
* cannot refresh the lock forever.
|
|
263
|
+
*/
|
|
264
|
+
readonly startHeartbeat: (agent: string) => () => void;
|
|
181
265
|
}
|
|
182
266
|
/**
|
|
183
267
|
* A fleet-driver operation failed against a resolvable target — most commonly an
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-driver.d.ts","sourceRoot":"","sources":["../src/fleet-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1C;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;IAE9D;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAErD
|
|
1
|
+
{"version":3,"file":"fleet-driver.d.ts","sourceRoot":"","sources":["../src/fleet-driver.ts"],"names":[],"mappings":"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"}
|
package/dist/fleet-driver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-driver.js","sourceRoot":"","sources":["../src/fleet-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"fleet-driver.js","sourceRoot":"","sources":["../src/fleet-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA4PxC;;;;;GAKG;AACH,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
|
package/dist/fleet-upgrade.d.ts
CHANGED
|
@@ -73,49 +73,115 @@ export interface AgentRollResult {
|
|
|
73
73
|
/** Set only when `outcome === 'halted'` — see `HaltReason`. */
|
|
74
74
|
readonly reason?: HaltReason;
|
|
75
75
|
readonly detail?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Files auto-resolved (committed as already-canonical) during this
|
|
78
|
+
* agent's pre-flight, if any (DR-040 Decision 3 / macf#698 R1). Orthogonal
|
|
79
|
+
* to `outcome` — auto-resolve happens BEFORE the outcome is decided, so it
|
|
80
|
+
* can co-occur with ANY outcome: e.g. all dirty files were already-canonical
|
|
81
|
+
* → committed, roll proceeds → `outcome: 'upgraded'` WITH this field set; or
|
|
82
|
+
* some were already-canonical (committed) and some were genuine-delta →
|
|
83
|
+
* `outcome: 'config-dirty-skipped'` (message scoped to the genuine-delta
|
|
84
|
+
* subset only) WITH this field set. Absent when nothing was auto-resolved.
|
|
85
|
+
*/
|
|
86
|
+
readonly autoResolvedFiles?: readonly string[];
|
|
76
87
|
}
|
|
77
88
|
/**
|
|
78
|
-
* The roll's
|
|
79
|
-
* macf#
|
|
80
|
-
*
|
|
89
|
+
* The roll's MEANINGFUL config surface (macf#722 Fix B / macf#725 UNION,
|
|
90
|
+
* narrowed by DR-040 Decision 6 / macf#698). The path globs that BOTH
|
|
91
|
+
* consumers of this constant key on:
|
|
92
|
+
*
|
|
93
|
+
* 1. **The dirty-CHECK gate** — `rollFleet`'s pre-flight config-dirty
|
|
94
|
+
* gate (`isConfigDirty` / `listDirtyConfig` in `vm-driver.ts`) +
|
|
95
|
+
* `restart-self`'s standalone stash-refusal guard
|
|
96
|
+
* (`hasUncommittedConfigChanges`). `git status --porcelain -- <pattern>`
|
|
97
|
+
* → non-empty ⇒ OBJECT / refuse. Narrowing here narrows what OBJECTS.
|
|
98
|
+
* 2. **The `excludeConfigSurface` stash** — `restart-self`'s roll-path
|
|
99
|
+
* relaunch (`git stash push -- . ':!<pattern>'` per entry) stashes
|
|
100
|
+
* everything EXCEPT this pattern, so the roll's own `macf update`
|
|
101
|
+
* regeneration stays uncommitted for the relaunched agent to see. A
|
|
102
|
+
* path DROPPED from the pattern is therefore no longer excluded → it
|
|
103
|
+
* gets STASHED on relaunch. For a TRACKED operator-evolution file
|
|
104
|
+
* (`CLAUDE.md`), that means the agent comes back with it reverted to
|
|
105
|
+
* HEAD and the edits buried in a stash = silent pre-reconcile loss.
|
|
106
|
+
*
|
|
107
|
+
* Because of use #2, this is a **UNION, not the overwrite-set alone**
|
|
108
|
+
* (macf#725): (a) the files `macf update` OVERWRITES ∪ (b) the
|
|
109
|
+
* operator-evolution files that must NOT be silently stashed on relaunch.
|
|
110
|
+
* The `.claude/**` wildcard was the ONLY bug — it swept in runtime logs
|
|
111
|
+
* (`.claude/audit.log`) + agent scratch that `macf update` never writes,
|
|
112
|
+
* producing false CONFIG-DIRTY objections. This revision replaces ONLY that
|
|
113
|
+
* wildcard with the specific managed paths; the union's meaningful members
|
|
114
|
+
* are preserved.
|
|
115
|
+
*
|
|
116
|
+
* **(a) The exact set `macf update` OVERWRITES** — verified directly against
|
|
117
|
+
* the CLI source (`update.ts` + `env-files-update.ts` + `rules.ts` +
|
|
118
|
+
* `claude-sh.ts` + `host-prelude.ts` + `settings-writer.ts`):
|
|
81
119
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* `macf update`
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* `
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
120
|
+
* - `claude.sh` — `writeClaudeSh` (unconditional for a macf-managed workspace;
|
|
121
|
+
* preserved only when hand-authored/header-less, in which case it's never
|
|
122
|
+
* legitimately dirty from `macf update`'s perspective anyway — harmless to
|
|
123
|
+
* include unconditionally, same reasoning as the prior revision).
|
|
124
|
+
* - `.claude/rules/**` — `copyCanonicalRules` (universal `.claude/rules/*.md`)
|
|
125
|
+
* + `fetchProjectRules` (project-tier `.claude/rules/project/*.md`); both
|
|
126
|
+
* land under this one glob.
|
|
127
|
+
* - `.claude/scripts/**` — `copyCanonicalScripts`. Still the exact overwrite
|
|
128
|
+
* set as of DR-039 phase 2 (macf#749, hook SCRIPT FILES moved to
|
|
129
|
+
* `plugin/scripts/`): `macf update` still writes a `.claude/scripts/`
|
|
130
|
+
* compat copy for hand-wired substrate hooks + non-plugin-init'd
|
|
131
|
+
* workspaces (see `rules.ts` `copyCanonicalScripts` doc comment). Drop this
|
|
132
|
+
* entry once that compat copy is retired.
|
|
133
|
+
* - `.claude/settings.json` — `installGhTokenHook` / `installPluginSkillPermissions`
|
|
134
|
+
* / `installSandboxFdAllowRead` / `installSandboxExcludedCommands` (all
|
|
135
|
+
* merge-preserving writers targeting this one file). Deliberately EXCLUDES
|
|
136
|
+
* `.claude/settings.local.json` — `macf update` only ever READS it (for the
|
|
137
|
+
* getters' merged-view), never writes it (+ it's gitignored → never dirty
|
|
138
|
+
* in the first place → no stash risk).
|
|
139
|
+
* - `.claude/.macf/env._helpers` / `env.identity` / `env.github` / `env.certs`
|
|
140
|
+
* / `env.registry` — the 5 `MANAGED_ENV_FILES` (`env-files-update.ts`),
|
|
141
|
+
* regenerated unconditionally + warn-on-hand-edit. Deliberately EXCLUDES the
|
|
142
|
+
* 2 `OPERATOR_ENV_FILES` (`env.telemetry`, `env.tmux` — bootstrap-write-if-
|
|
143
|
+
* absent, else preserved unconditionally).
|
|
144
|
+
* - `.claude/.macf/host-prelude.sh` — `writeHostPrelude`, "macf-managed +
|
|
145
|
+
* RE-DETECTED (never preserve-existing)" per its own doc comment
|
|
146
|
+
* (`host-prelude.ts`). Genuinely overwritten every `macf update` run; ADDED
|
|
147
|
+
* here (the prior `.claude/**` wildcard caught it incidentally — narrowing
|
|
148
|
+
* the wildcard away would have silently dropped coverage for this file
|
|
149
|
+
* without this explicit addition).
|
|
92
150
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* project-tier), `CLAUDE.md` (operator workbench doc), `claude.sh` (the
|
|
96
|
-
* launcher — operator-preserved when hand-authored/header-less, and harmless
|
|
97
|
-
* to include even when macf-managed since a macf-managed copy is never
|
|
98
|
-
* legitimately "dirty" outside an in-flight `macf update`), and `env.local.*`
|
|
99
|
-
* (the operator-custom env extension slot — see
|
|
100
|
-
* `design/decisions/DR-029-substrate-config-via-init-and-reintegrate.md`
|
|
101
|
-
* Amendment table). Deliberately excludes macf-managed/regenerated files
|
|
102
|
-
* (`env.*` canonical seven, `host-prelude.sh`) that are ONLY ever touched by
|
|
103
|
-
* `macf update` itself and never by an operator — dirtiness there pre-flight
|
|
104
|
-
* would still be a genuine conflict (someone hand-edited a regenerated file),
|
|
105
|
-
* so those ARE covered by `.claude/**`/`.macf/*` where they live; the excluded
|
|
106
|
-
* class is narrower than "everything macf update touches."
|
|
151
|
+
* **(b) The operator-evolution surface that must NOT be silently stashed**
|
|
152
|
+
* (macf#725 union half — kept, NOT dropped, per the use-#2 reasoning above):
|
|
107
153
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
154
|
+
* - `CLAUDE.md` — TRACKED operator/workbench doc. `macf update` never writes
|
|
155
|
+
* it (no write path in any CLI command), so it's NOT an overwrite-set
|
|
156
|
+
* member — but it IS a meaningful operator-evolution file: a dirty
|
|
157
|
+
* `CLAUDE.md` legitimately warrants a gate objection (unlike `audit.log`,
|
|
158
|
+
* it's real work, not runtime noise), and it MUST stay in the pattern so
|
|
159
|
+
* `excludeConfigSurface` leaves it uncommitted rather than stashing the
|
|
160
|
+
* operator's edits away on relaunch (verified TRACKED → live stash-loss
|
|
161
|
+
* hazard if dropped).
|
|
162
|
+
* - `env.local.*` — the operator-custom env-extension slot (bare pathspec,
|
|
163
|
+
* preserved verbatim from the prior union). Untracked in practice (so no
|
|
164
|
+
* live stash risk today), but kept for union fidelity + zero-cost safety as
|
|
165
|
+
* a genuine operator-surface member.
|
|
166
|
+
*
|
|
167
|
+
* **Motivating incident** (devops review, PR #748 / macf#698): the prior
|
|
168
|
+
* `.claude/**` wildcard matched `.claude/audit.log` — a runtime log a custom
|
|
169
|
+
* `ConfigChange` hook appends to (hence perpetually git-dirty on that
|
|
170
|
+
* workspace) that `macf update` never writes — and **blocked devops's
|
|
171
|
+
* v0.2.48 fleet upgrade** with a false CONFIG-DIRTY objection on 2026-07-02.
|
|
172
|
+
* Untracking `audit.log` itself (the `.gitignore` force-include +
|
|
173
|
+
* `git rm --cached`) is a separate, devops-owned LOCAL workspace cleanup —
|
|
174
|
+
* out of scope here; this pattern-narrowing is the FRAMEWORK-side fix so no
|
|
175
|
+
* future non-canonical `.claude/` file (runtime logs, agent scratch, custom-
|
|
176
|
+
* hook output) can trip the gate at all, regardless of gitignore state on any
|
|
177
|
+
* given workspace.
|
|
178
|
+
*
|
|
179
|
+
* Both gate consumers already pathspec-filter their `git status --porcelain`
|
|
180
|
+
* calls by this exact array (as does the stash), so this revision narrows
|
|
181
|
+
* ALL consumers' behavior identically; no separate no-pathspec fix was needed
|
|
182
|
+
* at any call site.
|
|
117
183
|
*/
|
|
118
|
-
export declare const ROLL_TOUCHED_CONFIG_PATTERNS: readonly [".claude/**", "
|
|
184
|
+
export declare const ROLL_TOUCHED_CONFIG_PATTERNS: readonly ["claude.sh", ".claude/rules/**", ".claude/scripts/**", ".claude/settings.json", ".claude/.macf/env._helpers", ".claude/.macf/env.identity", ".claude/.macf/env.github", ".claude/.macf/env.certs", ".claude/.macf/env.registry", ".claude/.macf/host-prelude.sh", "CLAUDE.md", "env.local.*"];
|
|
119
185
|
/** The result of rolling ONE fleet (the EXECUTE path). */
|
|
120
186
|
export interface FleetRollResult {
|
|
121
187
|
readonly results: readonly AgentRollResult[];
|
|
@@ -125,8 +191,21 @@ export interface FleetRollResult {
|
|
|
125
191
|
readonly upgraded: number;
|
|
126
192
|
/** Count of agents skipped because they were busy. */
|
|
127
193
|
readonly busySkipped: number;
|
|
128
|
-
/**
|
|
194
|
+
/**
|
|
195
|
+
* Count of agents skipped because their config surface still had a
|
|
196
|
+
* GENUINE-DELTA file after tiering (macf#722 Fix B; scope narrowed to
|
|
197
|
+
* genuine-delta-only by DR-040 Decision 3 / macf#698 R1 — an agent whose
|
|
198
|
+
* ENTIRE dirty set was already-canonical is auto-resolved instead and does
|
|
199
|
+
* NOT count here).
|
|
200
|
+
*/
|
|
129
201
|
readonly configDirtySkipped: number;
|
|
202
|
+
/**
|
|
203
|
+
* Count of agents that had ≥1 dirty file auto-resolved (committed as
|
|
204
|
+
* already-canonical) this roll (DR-040 Decision 3 / macf#698 R1). Same
|
|
205
|
+
* per-agent-count style as the other counters; see each result's
|
|
206
|
+
* `autoResolvedFiles` for the file-level detail.
|
|
207
|
+
*/
|
|
208
|
+
readonly configAutoResolved: number;
|
|
130
209
|
}
|
|
131
210
|
/** Progress events for CLI rendering (the RESULT objects are what tests assert on). */
|
|
132
211
|
export type UpgradeEvent = {
|
|
@@ -145,11 +224,28 @@ export type UpgradeEvent = {
|
|
|
145
224
|
readonly to: string;
|
|
146
225
|
}
|
|
147
226
|
/**
|
|
148
|
-
* The pre-flight
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
227
|
+
* The pre-flight AUTO-RESOLVE (DR-040 Decision 3 / macf#698 R1) — `files`
|
|
228
|
+
* were dirty but their content already equalled canonical, so they were
|
|
229
|
+
* committed automatically; no agent/operator involvement. Fired BEFORE the
|
|
230
|
+
* genuine-delta OBJECT check (if any) + before the busy-gate / transaction,
|
|
231
|
+
* for the SAME agent this iteration — an agent can see BOTH this event AND
|
|
232
|
+
* a subsequent `config-dirty-skip` (for the remaining genuine-delta files)
|
|
233
|
+
* in the same roll.
|
|
234
|
+
*/
|
|
235
|
+
| {
|
|
236
|
+
readonly kind: 'config-auto-resolved';
|
|
237
|
+
readonly agent: string;
|
|
238
|
+
readonly files: readonly string[];
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* The pre-flight OBJECT (macf#725; scope narrowed to GENUINE-DELTA files
|
|
242
|
+
* only by DR-040 Decision 3 / macf#698 R1 — already-canonical files were
|
|
243
|
+
* auto-resolved above and are never part of this list). `files` is the
|
|
244
|
+
* exact genuine-delta uncommitted-path list; `message` is the
|
|
245
|
+
* ready-to-forward, agent-directed text (inspect + commit / delete /
|
|
246
|
+
* gitignore, then re-run). Fired INSTEAD of any mutation — nothing on this
|
|
247
|
+
* agent's genuine-delta files was touched (though the already-canonical
|
|
248
|
+
* subset, if any, WAS committed by the preceding `config-auto-resolved`).
|
|
153
249
|
*/
|
|
154
250
|
| {
|
|
155
251
|
readonly kind: 'config-dirty-skip';
|
|
@@ -250,14 +346,15 @@ export declare function buildConfigDirtyMessage(agent: string, files: readonly s
|
|
|
250
346
|
export declare function buildModifiedFilesMessage(agent: string, files: readonly string[]): string;
|
|
251
347
|
/**
|
|
252
348
|
* Roll ONE fleet: for every `behind` plan (in order) run the PRE-FLIGHT gates
|
|
253
|
-
* (config-dirty, then busy) → upgrade → restart → verify-green
|
|
254
|
-
* the roll on the first agent whose post-restart state isn't
|
|
255
|
-
* Non-`behind` plans are ignored (planned skips).
|
|
256
|
-
* skipped + reported and NEVER a halt (they were
|
|
257
|
-
* is always safe) — config-dirty is checked
|
|
258
|
-
* agent may still become idle later
|
|
259
|
-
*
|
|
260
|
-
*
|
|
349
|
+
* (config-dirty tier-first, then busy) → upgrade → restart → verify-green
|
|
350
|
+
* cycle, HALTING the roll on the first agent whose post-restart state isn't
|
|
351
|
+
* confirmed-green. Non-`behind` plans are ignored (planned skips).
|
|
352
|
+
* Pre-flight-gated agents are skipped + reported and NEVER a halt (they were
|
|
353
|
+
* never mutated, so continuing is always safe) — config-dirty is checked
|
|
354
|
+
* first because a busy-but-clean agent may still become idle later
|
|
355
|
+
* (`--wait`), whereas a dirty (genuine-delta) agent is skip-only regardless.
|
|
356
|
+
* With `wait`, a busy agent is re-polled for idle first. The verb order +
|
|
357
|
+
* HALT semantics mirror `fleet/upgrade.sh`'s `roll_one`.
|
|
261
358
|
*
|
|
262
359
|
* **Transactional + OBJECT-with-message revision (macf#725).** The pre-flight
|
|
263
360
|
* config-dirty gate is the ONLY decision point that inspects PRE-upgrade
|
|
@@ -272,6 +369,21 @@ export declare function buildModifiedFilesMessage(agent: string, files: readonly
|
|
|
272
369
|
* silent-skip + separately-force-stashed-restart shape, which could dirty the
|
|
273
370
|
* workspace via `upgrade` and then have `restart-self`'s OWN guard refuse —
|
|
274
371
|
* aborting mid-transaction with the workspace already mutated.
|
|
372
|
+
*
|
|
373
|
+
* **Tier-first auto-resolve (DR-040 Decision 3 / macf#698 R1).** Before
|
|
374
|
+
* deciding OBJECT-or-proceed, `deps.driver.classifyDirtyConfig` splits the
|
|
375
|
+
* dirty set into `alreadyCanonical` (content already equals what `macf
|
|
376
|
+
* update` would write — the common case: a stale-branch workspace, both
|
|
377
|
+
* code-agent AND science hit ONLY this tier on the v0.2.48 roll) and
|
|
378
|
+
* `genuineDelta` (a real local difference). `alreadyCanonical` files are
|
|
379
|
+
* committed automatically via `autoResolveCanonical` — no agent/operator
|
|
380
|
+
* involvement, no OBJECT — clearing the false config-dirty signal. Only a
|
|
381
|
+
* non-empty `genuineDelta` still triggers the OBJECT-and-skip path, and its
|
|
382
|
+
* message + `onEvent` payload are scoped to the genuine-delta files ONLY
|
|
383
|
+
* (the auto-resolved noise is never re-surfaced as something to inspect).
|
|
384
|
+
* When `genuineDelta` is empty (either the whole dirty set was
|
|
385
|
+
* already-canonical, or there was nothing dirty at all), the roll falls
|
|
386
|
+
* through into the transaction exactly as the clean case always has.
|
|
275
387
|
*/
|
|
276
388
|
export declare function rollFleet(plans: readonly AgentUpgradePlan[], opts: RollFleetOptions, deps: RollFleetDeps): Promise<FleetRollResult>;
|
|
277
389
|
/** Options for the multi-fleet orchestrator. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-upgrade.d.ts","sourceRoot":"","sources":["../src/fleet-upgrade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fleet-upgrade.d.ts","sourceRoot":"","sources":["../src/fleet-upgrade.ts"],"names":[],"mappings":"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"}
|
package/dist/fleet-upgrade.js
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* or a future K8s package). It NEVER touches `/proc`, tmux, `capture-pane`, or
|
|
9
9
|
* kubectl — it drives entirely off the injected `FleetDriver` verbs
|
|
10
10
|
* (`probe`/`discoverWorkspaces`/`isBusy`/`listDirtyConfig`/`upgrade`/`restart`/
|
|
11
|
-
* `listModifiedFiles`) plus an
|
|
12
|
-
* sequencer rolls a VM tmux fleet, a
|
|
13
|
-
* by swapping only the driver.
|
|
11
|
+
* `listModifiedFiles`/`acquireLock`/`startHeartbeat`/`releaseLock`) plus an
|
|
12
|
+
* injected `verifyGreen` runner, so the SAME sequencer rolls a VM tmux fleet, a
|
|
13
|
+
* macOS host, and a far-future K8s deployment by swapping only the driver.
|
|
14
14
|
*
|
|
15
15
|
* The state machine (per fleet, one agent at a time):
|
|
16
16
|
*
|
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
* Fix B: rather than silently stashing operator dirt, the roll
|
|
25
25
|
* OBJECTS and does NOTHING until the agent resolves it)
|
|
26
26
|
* busy-gate (driver.isBusy → busy ⇒ SKIP+REPORT, or `--wait` for idle)
|
|
27
|
+
* → driver.acquireLock(agent, target) // DR-040 Decision 4 (macf#752):
|
|
28
|
+
* SET the maintenance lock BEFORE anything touches the agent, so a
|
|
29
|
+
* watchdog sweep racing the restart reads "planned maintenance,"
|
|
30
|
+
* never "unplanned outage." driver.startHeartbeat(agent) then
|
|
31
|
+
* keeps it fresh across the whole transaction below (background,
|
|
32
|
+
* decoupled from these awaits); its stop-handle fires exactly
|
|
33
|
+
* once, on whichever terminal branch is reached.
|
|
27
34
|
* → driver.upgrade(agent) // dirties the managed config surface —
|
|
28
35
|
* // this is EXPECTED, not a fault
|
|
29
36
|
* → driver.restart(agent, { leaveConfigUncommitted: true })
|
|
@@ -35,25 +42,35 @@
|
|
|
35
42
|
* each poll, over a relaunch-aware grace budget (`--verify-timeout`)
|
|
36
43
|
* → green on TARGET ⇒ driver.listModifiedFiles(agent) → emit an
|
|
37
44
|
* agent-directed "review + commit what macf update regenerated"
|
|
38
|
-
* message + list
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
45
|
+
* message + list; stopHeartbeat() + driver.releaseLock(agent)
|
|
46
|
+
* (DR-040 Decision 3 — release ONLY on confirmed clean success);
|
|
47
|
+
* THEN next agent (`upgraded`)
|
|
48
|
+
* → confirmed back on the OLD (pre-upgrade) version ⇒ stopHeartbeat()
|
|
49
|
+
* WITHOUT releasing the lock, then HALT the roll, reason
|
|
50
|
+
* `bad-release` (a crash-loop / stuck-old-process release stalls
|
|
51
|
+
* at agent 1 and CANNOT brick the fleet)
|
|
42
52
|
* → past-grace still NOT confirmed green (down / unreachable /
|
|
43
|
-
* some other unknown version) ⇒
|
|
53
|
+
* some other unknown version) ⇒ stopHeartbeat() WITHOUT
|
|
54
|
+
* releasing the lock, then HALT the roll, reason
|
|
44
55
|
* `relaunch-unconfirmed` — this is NOT a continue: "not yet
|
|
45
56
|
* green" cannot distinguish a slow-but-fine relaunch from a
|
|
46
57
|
* release that crashes on startup (which never shows the old
|
|
47
58
|
* version either), so continuing past an unconfirmed agent
|
|
48
59
|
* would risk cascading a crash-on-start release across the
|
|
49
|
-
* fleet (macf#722 Fix A)
|
|
60
|
+
* fleet (macf#722 Fix A). Both HALT paths deliberately LEAVE the
|
|
61
|
+
* lock in place (DR-040 Decision 3) — it self-clears once its
|
|
62
|
+
* heartbeat goes stale (`MAINT_LOCK_TTL`), giving the operator a
|
|
63
|
+
* bounded grace window before the watchdog resumes automatic
|
|
64
|
+
* action on a possibly-broken, mid-transition agent.
|
|
50
65
|
*
|
|
51
66
|
* Multi-fleet (`--fleet a,b,c`) rolls fleet-by-fleet: each fleet's roll must
|
|
52
67
|
* finish without a HALT before the next fleet starts (a bad release in fleet-1
|
|
53
68
|
* stops fleet-2 from ever being touched).
|
|
54
69
|
*
|
|
55
70
|
* DRY-RUN is the default at the command boundary: `execute: false` computes +
|
|
56
|
-
* reports the PLAN (probe + classify) and performs NO driver mutations
|
|
71
|
+
* reports the PLAN (probe + classify) and performs NO driver mutations —
|
|
72
|
+
* `rollFleet` (and therefore the maintenance lock) is never even called on
|
|
73
|
+
* that path; `upgradeFleets` only invokes it when `execute: true`.
|
|
57
74
|
*
|
|
58
75
|
* **Reconcile is MANUAL this iteration (macf#725).** The config-dirty OBJECT
|
|
59
76
|
* path surfaces the dirt via `onEvent` + a non-mutating skip; it does NOT
|
|
@@ -63,50 +80,116 @@
|
|
|
63
80
|
*/
|
|
64
81
|
import { compareSemver } from './semver.js';
|
|
65
82
|
/**
|
|
66
|
-
* The roll's
|
|
67
|
-
* macf#
|
|
68
|
-
*
|
|
83
|
+
* The roll's MEANINGFUL config surface (macf#722 Fix B / macf#725 UNION,
|
|
84
|
+
* narrowed by DR-040 Decision 6 / macf#698). The path globs that BOTH
|
|
85
|
+
* consumers of this constant key on:
|
|
69
86
|
*
|
|
70
|
-
* **
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
87
|
+
* 1. **The dirty-CHECK gate** — `rollFleet`'s pre-flight config-dirty
|
|
88
|
+
* gate (`isConfigDirty` / `listDirtyConfig` in `vm-driver.ts`) +
|
|
89
|
+
* `restart-self`'s standalone stash-refusal guard
|
|
90
|
+
* (`hasUncommittedConfigChanges`). `git status --porcelain -- <pattern>`
|
|
91
|
+
* → non-empty ⇒ OBJECT / refuse. Narrowing here narrows what OBJECTS.
|
|
92
|
+
* 2. **The `excludeConfigSurface` stash** — `restart-self`'s roll-path
|
|
93
|
+
* relaunch (`git stash push -- . ':!<pattern>'` per entry) stashes
|
|
94
|
+
* everything EXCEPT this pattern, so the roll's own `macf update`
|
|
95
|
+
* regeneration stays uncommitted for the relaunched agent to see. A
|
|
96
|
+
* path DROPPED from the pattern is therefore no longer excluded → it
|
|
97
|
+
* gets STASHED on relaunch. For a TRACKED operator-evolution file
|
|
98
|
+
* (`CLAUDE.md`), that means the agent comes back with it reverted to
|
|
99
|
+
* HEAD and the edits buried in a stash = silent pre-reconcile loss.
|
|
80
100
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* Amendment table). Deliberately excludes macf-managed/regenerated files
|
|
90
|
-
* (`env.*` canonical seven, `host-prelude.sh`) that are ONLY ever touched by
|
|
91
|
-
* `macf update` itself and never by an operator — dirtiness there pre-flight
|
|
92
|
-
* would still be a genuine conflict (someone hand-edited a regenerated file),
|
|
93
|
-
* so those ARE covered by `.claude/**`/`.macf/*` where they live; the excluded
|
|
94
|
-
* class is narrower than "everything macf update touches."
|
|
101
|
+
* Because of use #2, this is a **UNION, not the overwrite-set alone**
|
|
102
|
+
* (macf#725): (a) the files `macf update` OVERWRITES ∪ (b) the
|
|
103
|
+
* operator-evolution files that must NOT be silently stashed on relaunch.
|
|
104
|
+
* The `.claude/**` wildcard was the ONLY bug — it swept in runtime logs
|
|
105
|
+
* (`.claude/audit.log`) + agent scratch that `macf update` never writes,
|
|
106
|
+
* producing false CONFIG-DIRTY objections. This revision replaces ONLY that
|
|
107
|
+
* wildcard with the specific managed paths; the union's meaningful members
|
|
108
|
+
* are preserved.
|
|
95
109
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* `claude.
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
110
|
+
* **(a) The exact set `macf update` OVERWRITES** — verified directly against
|
|
111
|
+
* the CLI source (`update.ts` + `env-files-update.ts` + `rules.ts` +
|
|
112
|
+
* `claude-sh.ts` + `host-prelude.ts` + `settings-writer.ts`):
|
|
113
|
+
*
|
|
114
|
+
* - `claude.sh` — `writeClaudeSh` (unconditional for a macf-managed workspace;
|
|
115
|
+
* preserved only when hand-authored/header-less, in which case it's never
|
|
116
|
+
* legitimately dirty from `macf update`'s perspective anyway — harmless to
|
|
117
|
+
* include unconditionally, same reasoning as the prior revision).
|
|
118
|
+
* - `.claude/rules/**` — `copyCanonicalRules` (universal `.claude/rules/*.md`)
|
|
119
|
+
* + `fetchProjectRules` (project-tier `.claude/rules/project/*.md`); both
|
|
120
|
+
* land under this one glob.
|
|
121
|
+
* - `.claude/scripts/**` — `copyCanonicalScripts`. Still the exact overwrite
|
|
122
|
+
* set as of DR-039 phase 2 (macf#749, hook SCRIPT FILES moved to
|
|
123
|
+
* `plugin/scripts/`): `macf update` still writes a `.claude/scripts/`
|
|
124
|
+
* compat copy for hand-wired substrate hooks + non-plugin-init'd
|
|
125
|
+
* workspaces (see `rules.ts` `copyCanonicalScripts` doc comment). Drop this
|
|
126
|
+
* entry once that compat copy is retired.
|
|
127
|
+
* - `.claude/settings.json` — `installGhTokenHook` / `installPluginSkillPermissions`
|
|
128
|
+
* / `installSandboxFdAllowRead` / `installSandboxExcludedCommands` (all
|
|
129
|
+
* merge-preserving writers targeting this one file). Deliberately EXCLUDES
|
|
130
|
+
* `.claude/settings.local.json` — `macf update` only ever READS it (for the
|
|
131
|
+
* getters' merged-view), never writes it (+ it's gitignored → never dirty
|
|
132
|
+
* in the first place → no stash risk).
|
|
133
|
+
* - `.claude/.macf/env._helpers` / `env.identity` / `env.github` / `env.certs`
|
|
134
|
+
* / `env.registry` — the 5 `MANAGED_ENV_FILES` (`env-files-update.ts`),
|
|
135
|
+
* regenerated unconditionally + warn-on-hand-edit. Deliberately EXCLUDES the
|
|
136
|
+
* 2 `OPERATOR_ENV_FILES` (`env.telemetry`, `env.tmux` — bootstrap-write-if-
|
|
137
|
+
* absent, else preserved unconditionally).
|
|
138
|
+
* - `.claude/.macf/host-prelude.sh` — `writeHostPrelude`, "macf-managed +
|
|
139
|
+
* RE-DETECTED (never preserve-existing)" per its own doc comment
|
|
140
|
+
* (`host-prelude.ts`). Genuinely overwritten every `macf update` run; ADDED
|
|
141
|
+
* here (the prior `.claude/**` wildcard caught it incidentally — narrowing
|
|
142
|
+
* the wildcard away would have silently dropped coverage for this file
|
|
143
|
+
* without this explicit addition).
|
|
144
|
+
*
|
|
145
|
+
* **(b) The operator-evolution surface that must NOT be silently stashed**
|
|
146
|
+
* (macf#725 union half — kept, NOT dropped, per the use-#2 reasoning above):
|
|
147
|
+
*
|
|
148
|
+
* - `CLAUDE.md` — TRACKED operator/workbench doc. `macf update` never writes
|
|
149
|
+
* it (no write path in any CLI command), so it's NOT an overwrite-set
|
|
150
|
+
* member — but it IS a meaningful operator-evolution file: a dirty
|
|
151
|
+
* `CLAUDE.md` legitimately warrants a gate objection (unlike `audit.log`,
|
|
152
|
+
* it's real work, not runtime noise), and it MUST stay in the pattern so
|
|
153
|
+
* `excludeConfigSurface` leaves it uncommitted rather than stashing the
|
|
154
|
+
* operator's edits away on relaunch (verified TRACKED → live stash-loss
|
|
155
|
+
* hazard if dropped).
|
|
156
|
+
* - `env.local.*` — the operator-custom env-extension slot (bare pathspec,
|
|
157
|
+
* preserved verbatim from the prior union). Untracked in practice (so no
|
|
158
|
+
* live stash risk today), but kept for union fidelity + zero-cost safety as
|
|
159
|
+
* a genuine operator-surface member.
|
|
160
|
+
*
|
|
161
|
+
* **Motivating incident** (devops review, PR #748 / macf#698): the prior
|
|
162
|
+
* `.claude/**` wildcard matched `.claude/audit.log` — a runtime log a custom
|
|
163
|
+
* `ConfigChange` hook appends to (hence perpetually git-dirty on that
|
|
164
|
+
* workspace) that `macf update` never writes — and **blocked devops's
|
|
165
|
+
* v0.2.48 fleet upgrade** with a false CONFIG-DIRTY objection on 2026-07-02.
|
|
166
|
+
* Untracking `audit.log` itself (the `.gitignore` force-include +
|
|
167
|
+
* `git rm --cached`) is a separate, devops-owned LOCAL workspace cleanup —
|
|
168
|
+
* out of scope here; this pattern-narrowing is the FRAMEWORK-side fix so no
|
|
169
|
+
* future non-canonical `.claude/` file (runtime logs, agent scratch, custom-
|
|
170
|
+
* hook output) can trip the gate at all, regardless of gitignore state on any
|
|
171
|
+
* given workspace.
|
|
172
|
+
*
|
|
173
|
+
* Both gate consumers already pathspec-filter their `git status --porcelain`
|
|
174
|
+
* calls by this exact array (as does the stash), so this revision narrows
|
|
175
|
+
* ALL consumers' behavior identically; no separate no-pathspec fix was needed
|
|
176
|
+
* at any call site.
|
|
105
177
|
*/
|
|
106
178
|
export const ROLL_TOUCHED_CONFIG_PATTERNS = [
|
|
107
|
-
|
|
108
|
-
'CLAUDE.md',
|
|
179
|
+
// (a) the exact set `macf update` OVERWRITES:
|
|
109
180
|
'claude.sh',
|
|
181
|
+
'.claude/rules/**',
|
|
182
|
+
'.claude/scripts/**',
|
|
183
|
+
'.claude/settings.json',
|
|
184
|
+
'.claude/.macf/env._helpers',
|
|
185
|
+
'.claude/.macf/env.identity',
|
|
186
|
+
'.claude/.macf/env.github',
|
|
187
|
+
'.claude/.macf/env.certs',
|
|
188
|
+
'.claude/.macf/env.registry',
|
|
189
|
+
'.claude/.macf/host-prelude.sh',
|
|
190
|
+
// (b) operator-evolution files that must NOT be silently stashed on relaunch
|
|
191
|
+
// (macf#725 union half — `excludeConfigSurface` leaves these uncommitted):
|
|
192
|
+
'CLAUDE.md',
|
|
110
193
|
'env.local.*',
|
|
111
194
|
];
|
|
112
195
|
/**
|
|
@@ -203,14 +286,15 @@ export function buildModifiedFilesMessage(agent, files) {
|
|
|
203
286
|
}
|
|
204
287
|
/**
|
|
205
288
|
* Roll ONE fleet: for every `behind` plan (in order) run the PRE-FLIGHT gates
|
|
206
|
-
* (config-dirty, then busy) → upgrade → restart → verify-green
|
|
207
|
-
* the roll on the first agent whose post-restart state isn't
|
|
208
|
-
* Non-`behind` plans are ignored (planned skips).
|
|
209
|
-
* skipped + reported and NEVER a halt (they were
|
|
210
|
-
* is always safe) — config-dirty is checked
|
|
211
|
-
* agent may still become idle later
|
|
212
|
-
*
|
|
213
|
-
*
|
|
289
|
+
* (config-dirty tier-first, then busy) → upgrade → restart → verify-green
|
|
290
|
+
* cycle, HALTING the roll on the first agent whose post-restart state isn't
|
|
291
|
+
* confirmed-green. Non-`behind` plans are ignored (planned skips).
|
|
292
|
+
* Pre-flight-gated agents are skipped + reported and NEVER a halt (they were
|
|
293
|
+
* never mutated, so continuing is always safe) — config-dirty is checked
|
|
294
|
+
* first because a busy-but-clean agent may still become idle later
|
|
295
|
+
* (`--wait`), whereas a dirty (genuine-delta) agent is skip-only regardless.
|
|
296
|
+
* With `wait`, a busy agent is re-polled for idle first. The verb order +
|
|
297
|
+
* HALT semantics mirror `fleet/upgrade.sh`'s `roll_one`.
|
|
214
298
|
*
|
|
215
299
|
* **Transactional + OBJECT-with-message revision (macf#725).** The pre-flight
|
|
216
300
|
* config-dirty gate is the ONLY decision point that inspects PRE-upgrade
|
|
@@ -225,41 +309,65 @@ export function buildModifiedFilesMessage(agent, files) {
|
|
|
225
309
|
* silent-skip + separately-force-stashed-restart shape, which could dirty the
|
|
226
310
|
* workspace via `upgrade` and then have `restart-self`'s OWN guard refuse —
|
|
227
311
|
* aborting mid-transaction with the workspace already mutated.
|
|
312
|
+
*
|
|
313
|
+
* **Tier-first auto-resolve (DR-040 Decision 3 / macf#698 R1).** Before
|
|
314
|
+
* deciding OBJECT-or-proceed, `deps.driver.classifyDirtyConfig` splits the
|
|
315
|
+
* dirty set into `alreadyCanonical` (content already equals what `macf
|
|
316
|
+
* update` would write — the common case: a stale-branch workspace, both
|
|
317
|
+
* code-agent AND science hit ONLY this tier on the v0.2.48 roll) and
|
|
318
|
+
* `genuineDelta` (a real local difference). `alreadyCanonical` files are
|
|
319
|
+
* committed automatically via `autoResolveCanonical` — no agent/operator
|
|
320
|
+
* involvement, no OBJECT — clearing the false config-dirty signal. Only a
|
|
321
|
+
* non-empty `genuineDelta` still triggers the OBJECT-and-skip path, and its
|
|
322
|
+
* message + `onEvent` payload are scoped to the genuine-delta files ONLY
|
|
323
|
+
* (the auto-resolved noise is never re-surfaced as something to inspect).
|
|
324
|
+
* When `genuineDelta` is empty (either the whole dirty set was
|
|
325
|
+
* already-canonical, or there was nothing dirty at all), the roll falls
|
|
326
|
+
* through into the transaction exactly as the clean case always has.
|
|
228
327
|
*/
|
|
229
328
|
export async function rollFleet(plans, opts, deps) {
|
|
230
329
|
const results = [];
|
|
231
330
|
let upgraded = 0;
|
|
232
331
|
let busySkipped = 0;
|
|
233
332
|
let configDirtySkipped = 0;
|
|
333
|
+
let configAutoResolved = 0;
|
|
234
334
|
for (const plan of plans) {
|
|
235
335
|
if (plan.disposition !== 'behind')
|
|
236
336
|
continue;
|
|
237
337
|
const agent = plan.agent;
|
|
238
|
-
// PRE-FLIGHT config-dirty gate
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
// `leaveConfigUncommitted` below +
|
|
242
|
-
// Consequently, the NEXT roll's pre-flight
|
|
243
|
-
// still-uncommitted regen
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
// (zero inter-roll friction, but trades away the agent's review-visibility
|
|
249
|
-
// of what changed) — is a DEFERRED future option, the operator's call.
|
|
338
|
+
// PRE-FLIGHT config-dirty gate — tier-first (DR-040 Decision 3 /
|
|
339
|
+
// macf#698 R1). By-design inter-roll STEADY-STATE (macf#725): a clean
|
|
340
|
+
// roll LEAVES `macf update`'s regeneration uncommitted (so the relaunched
|
|
341
|
+
// agent reviews it — see `restart`'s `leaveConfigUncommitted` below +
|
|
342
|
+
// `buildModifiedFilesMessage`). Consequently, the NEXT roll's pre-flight
|
|
343
|
+
// will re-classify that still-uncommitted regen — almost always as
|
|
344
|
+
// ALREADY-CANONICAL (it IS what `macf update` just wrote) and therefore
|
|
345
|
+
// auto-resolved here rather than objected on. This is the steady-state
|
|
346
|
+
// this tier exists to smooth over.
|
|
347
|
+
let autoResolvedFiles;
|
|
250
348
|
if (!opts.force) {
|
|
251
|
-
const
|
|
252
|
-
if (
|
|
349
|
+
const { alreadyCanonical, genuineDelta } = await deps.driver.classifyDirtyConfig(agent);
|
|
350
|
+
if (alreadyCanonical.length > 0) {
|
|
351
|
+
await deps.driver.autoResolveCanonical(agent, alreadyCanonical);
|
|
352
|
+
configAutoResolved += 1;
|
|
353
|
+
autoResolvedFiles = alreadyCanonical;
|
|
354
|
+
deps.onEvent?.({ kind: 'config-auto-resolved', agent, files: alreadyCanonical });
|
|
355
|
+
}
|
|
356
|
+
if (genuineDelta.length > 0) {
|
|
253
357
|
configDirtySkipped += 1;
|
|
254
|
-
const message = buildConfigDirtyMessage(agent,
|
|
358
|
+
const message = buildConfigDirtyMessage(agent, genuineDelta);
|
|
255
359
|
results.push({
|
|
256
360
|
agent,
|
|
257
361
|
outcome: 'config-dirty-skipped',
|
|
258
362
|
detail: message,
|
|
363
|
+
...(autoResolvedFiles ? { autoResolvedFiles } : {}),
|
|
259
364
|
});
|
|
260
|
-
deps.onEvent?.({ kind: 'config-dirty-skip', agent, files:
|
|
365
|
+
deps.onEvent?.({ kind: 'config-dirty-skip', agent, files: genuineDelta, message });
|
|
261
366
|
continue;
|
|
262
367
|
}
|
|
368
|
+
// genuineDelta is empty (nothing dirty at all, or everything dirty WAS
|
|
369
|
+
// already-canonical and is now committed) — fall through into the
|
|
370
|
+
// transaction below exactly as the always-clean case does.
|
|
263
371
|
}
|
|
264
372
|
let busy = await deps.driver.isBusy(agent);
|
|
265
373
|
let waited = false;
|
|
@@ -269,12 +377,26 @@ export async function rollFleet(plans, opts, deps) {
|
|
|
269
377
|
}
|
|
270
378
|
if (busy) {
|
|
271
379
|
busySkipped += 1;
|
|
272
|
-
results.push({
|
|
380
|
+
results.push({
|
|
381
|
+
agent,
|
|
382
|
+
outcome: 'busy-skipped',
|
|
383
|
+
detail: waited ? 'still busy after --wait' : 'busy',
|
|
384
|
+
...(autoResolvedFiles ? { autoResolvedFiles } : {}),
|
|
385
|
+
});
|
|
273
386
|
deps.onEvent?.({ kind: 'busy-skip', agent, waited });
|
|
274
387
|
continue;
|
|
275
388
|
}
|
|
276
389
|
// --- ENTERING THE TRANSACTION: upgrade + restart run together, always. ---
|
|
277
390
|
deps.onEvent?.({ kind: 'roll-start', agent, from: plan.runningVersion, to: opts.targetVersion });
|
|
391
|
+
// DR-040 Decision 4 (macf-devops-toolkit#158/#159, macf#752) — SET the
|
|
392
|
+
// maintenance lock BEFORE anything touches the agent's process, so a
|
|
393
|
+
// watchdog sweep racing the very first SIGTERM already reads "planned
|
|
394
|
+
// maintenance," never "unplanned outage." The background heartbeat keeps
|
|
395
|
+
// the lock fresh across the WHOLE transaction below (upgrade → restart →
|
|
396
|
+
// verify-green can each individually take a while); `stopHeartbeat` is
|
|
397
|
+
// invoked exactly once, on whichever terminal branch is reached.
|
|
398
|
+
await deps.driver.acquireLock(agent, opts.targetVersion);
|
|
399
|
+
const stopHeartbeat = deps.driver.startHeartbeat(agent);
|
|
278
400
|
await deps.driver.upgrade(agent);
|
|
279
401
|
// The pre-flight gate above (clean, or explicitly `--force`-bypassed) is
|
|
280
402
|
// the only thing that decided whether to enter this transaction. Once
|
|
@@ -292,8 +414,17 @@ export async function rollFleet(plans, opts, deps) {
|
|
|
292
414
|
upgraded += 1;
|
|
293
415
|
const modifiedFiles = await deps.driver.listModifiedFiles(agent);
|
|
294
416
|
const message = buildModifiedFilesMessage(agent, modifiedFiles);
|
|
295
|
-
results.push({
|
|
417
|
+
results.push({
|
|
418
|
+
agent,
|
|
419
|
+
outcome: 'upgraded',
|
|
420
|
+
detail: message,
|
|
421
|
+
...(autoResolvedFiles ? { autoResolvedFiles } : {}),
|
|
422
|
+
});
|
|
296
423
|
deps.onEvent?.({ kind: 'upgraded', agent, version: green.version, modifiedFiles, message });
|
|
424
|
+
// Clean GREEN is the ONLY release path (DR-040 Decision 3) — hand the
|
|
425
|
+
// agent back to normal watchdog reconciliation immediately.
|
|
426
|
+
stopHeartbeat();
|
|
427
|
+
await deps.driver.releaseLock(agent);
|
|
297
428
|
continue;
|
|
298
429
|
}
|
|
299
430
|
const reason = classifyHalt(green, plan.runningVersion);
|
|
@@ -302,11 +433,21 @@ export async function rollFleet(plans, opts, deps) {
|
|
|
302
433
|
outcome: 'halted',
|
|
303
434
|
reason,
|
|
304
435
|
detail: `${reason}: verify-green ${green.reason} (last=${green.lastVersion ?? 'down'})`,
|
|
436
|
+
...(autoResolvedFiles ? { autoResolvedFiles } : {}),
|
|
305
437
|
});
|
|
306
438
|
deps.onEvent?.({ kind: 'halt', agent, reason, lastVersion: green.lastVersion });
|
|
307
|
-
|
|
439
|
+
// HALT deliberately LEAVES the lock in place (DR-040 Decision 3): a
|
|
440
|
+
// possibly-broken, mid-transition agent must NOT be handed straight back
|
|
441
|
+
// to the watchdog's Tier-1/2/3 healing ladder the instant the roll fails
|
|
442
|
+
// — that is exactly the uncoordinated, racing intervention the
|
|
443
|
+
// transactional halt exists to avoid. Only the background heartbeat is
|
|
444
|
+
// stopped here; the lock self-clears once its heartbeat goes stale
|
|
445
|
+
// (MAINT_LOCK_TTL), giving the operator a bounded grace window to
|
|
446
|
+
// inspect the halted roll before the watchdog resumes automatic action.
|
|
447
|
+
stopHeartbeat();
|
|
448
|
+
return { results, halted: true, upgraded, busySkipped, configDirtySkipped, configAutoResolved };
|
|
308
449
|
}
|
|
309
|
-
return { results, halted: false, upgraded, busySkipped, configDirtySkipped };
|
|
450
|
+
return { results, halted: false, upgraded, busySkipped, configDirtySkipped, configAutoResolved };
|
|
310
451
|
}
|
|
311
452
|
/**
|
|
312
453
|
* Orchestrate a rolling upgrade across the ORDERED `fleets` (PROJECT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-upgrade.js","sourceRoot":"","sources":["../src/fleet-upgrade.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fleet-upgrade.js","sourceRoot":"","sources":["../src/fleet-upgrade.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groundnuty/macf-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.49",
|
|
4
4
|
"description": "Shared internals consumed by the MACF CLI and channel-server packages. Not intended for direct external use — will be marked deprecated-internal on first npm publish per DR-022 Amendment A.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|