@tokenfactory/acc-runner 0.42.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -3
- package/dist/companion-run.d.ts.map +1 -1
- package/dist/companion-run.js +20 -0
- package/dist/companion-run.js.map +1 -1
- package/dist/config.d.ts +72 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +117 -3
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +13 -3
- package/dist/doctor.js.map +1 -1
- package/dist/engines/account-probe.d.ts +24 -0
- package/dist/engines/account-probe.d.ts.map +1 -1
- package/dist/engines/account-probe.js +18 -1
- package/dist/engines/account-probe.js.map +1 -1
- package/dist/engines/registry.d.ts +17 -6
- package/dist/engines/registry.d.ts.map +1 -1
- package/dist/engines/registry.js +38 -13
- package/dist/engines/registry.js.map +1 -1
- package/dist/git-auth/github-token-source.d.ts +54 -0
- package/dist/git-auth/github-token-source.d.ts.map +1 -0
- package/dist/git-auth/github-token-source.js +44 -0
- package/dist/git-auth/github-token-source.js.map +1 -0
- package/dist/git-auth/index.d.ts +4 -0
- package/dist/git-auth/index.d.ts.map +1 -1
- package/dist/git-auth/index.js +4 -0
- package/dist/git-auth/index.js.map +1 -1
- package/dist/git-auth/installation-token.d.ts +95 -0
- package/dist/git-auth/installation-token.d.ts.map +1 -0
- package/dist/git-auth/installation-token.js +192 -0
- package/dist/git-auth/installation-token.js.map +1 -0
- package/dist/local-repo/command.d.ts +28 -0
- package/dist/local-repo/command.d.ts.map +1 -0
- package/dist/local-repo/command.js +178 -0
- package/dist/local-repo/command.js.map +1 -0
- package/dist/local-repo/index.d.ts +119 -0
- package/dist/local-repo/index.d.ts.map +1 -0
- package/dist/local-repo/index.js +141 -0
- package/dist/local-repo/index.js.map +1 -0
- package/dist/machine-capabilities/index.d.ts +21 -0
- package/dist/machine-capabilities/index.d.ts.map +1 -0
- package/dist/machine-capabilities/index.js +21 -0
- package/dist/machine-capabilities/index.js.map +1 -0
- package/dist/machine-capabilities/probe.d.ts +61 -0
- package/dist/machine-capabilities/probe.d.ts.map +1 -0
- package/dist/machine-capabilities/probe.js +243 -0
- package/dist/machine-capabilities/probe.js.map +1 -0
- package/dist/machine-capabilities/redact.d.ts +42 -0
- package/dist/machine-capabilities/redact.d.ts.map +1 -0
- package/dist/machine-capabilities/redact.js +160 -0
- package/dist/machine-capabilities/redact.js.map +1 -0
- package/dist/machine-capabilities/report.d.ts +107 -0
- package/dist/machine-capabilities/report.d.ts.map +1 -0
- package/dist/machine-capabilities/report.js +211 -0
- package/dist/machine-capabilities/report.js.map +1 -0
- package/dist/machine-capabilities/types.d.ts +115 -0
- package/dist/machine-capabilities/types.d.ts.map +1 -0
- package/dist/machine-capabilities/types.js +11 -0
- package/dist/machine-capabilities/types.js.map +1 -0
- package/dist/mcp-spawn.d.ts +19 -0
- package/dist/mcp-spawn.d.ts.map +1 -1
- package/dist/mcp-spawn.js +52 -26
- package/dist/mcp-spawn.js.map +1 -1
- package/dist/migration-seq-guard.d.ts +78 -0
- package/dist/migration-seq-guard.d.ts.map +1 -0
- package/dist/migration-seq-guard.js +304 -0
- package/dist/migration-seq-guard.js.map +1 -0
- package/dist/node-version.d.ts +132 -0
- package/dist/node-version.d.ts.map +1 -0
- package/dist/node-version.js +318 -0
- package/dist/node-version.js.map +1 -0
- package/dist/prepr-gate.d.ts +120 -0
- package/dist/prepr-gate.d.ts.map +1 -1
- package/dist/prepr-gate.js +202 -3
- package/dist/prepr-gate.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +34 -0
- package/dist/program.js.map +1 -1
- package/dist/provider-auth.d.ts +51 -1
- package/dist/provider-auth.d.ts.map +1 -1
- package/dist/provider-auth.js +83 -2
- package/dist/provider-auth.js.map +1 -1
- package/dist/runtime/review-chunking.d.ts +101 -0
- package/dist/runtime/review-chunking.d.ts.map +1 -0
- package/dist/runtime/review-chunking.js +192 -0
- package/dist/runtime/review-chunking.js.map +1 -0
- package/dist/runtime/review-diff.d.ts +30 -0
- package/dist/runtime/review-diff.d.ts.map +1 -0
- package/dist/runtime/review-diff.js +59 -0
- package/dist/runtime/review-diff.js.map +1 -0
- package/dist/runtime/reviewer.d.ts +40 -19
- package/dist/runtime/reviewer.d.ts.map +1 -1
- package/dist/runtime/reviewer.js +283 -68
- package/dist/runtime/reviewer.js.map +1 -1
- package/dist/serve-scope/command.d.ts +12 -0
- package/dist/serve-scope/command.d.ts.map +1 -0
- package/dist/serve-scope/command.js +89 -0
- package/dist/serve-scope/command.js.map +1 -0
- package/dist/serve-scope/index.d.ts +130 -0
- package/dist/serve-scope/index.d.ts.map +1 -0
- package/dist/serve-scope/index.js +148 -0
- package/dist/serve-scope/index.js.map +1 -0
- package/dist/task-runner.d.ts +22 -2
- package/dist/task-runner.d.ts.map +1 -1
- package/dist/task-runner.js +142 -25
- package/dist/task-runner.js.map +1 -1
- package/dist/watch.d.ts +21 -0
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +109 -1
- package/dist/watch.js.map +1 -1
- package/package.json +1 -1
package/dist/mcp-spawn.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export declare const ACC_MCP_KEY = "acc";
|
|
2
|
+
/** Env var acc-mcp-server reads the per-turn delegation JWT from (see cli.ts). */
|
|
3
|
+
export declare const ACC_MCP_DELEGATION_TOKEN_ENV = "ACC_MCP_DELEGATION_TOKEN";
|
|
4
|
+
/** Env var acc-mcp-server (future-facing) reads the calling agent's id from. */
|
|
5
|
+
export declare const ACC_AGENT_ID_ENV = "ACC_AGENT_ID";
|
|
2
6
|
export interface McpSpawnOptions {
|
|
3
7
|
cwd: string;
|
|
4
8
|
taskId: string;
|
|
@@ -7,6 +11,21 @@ export interface McpSpawnOptions {
|
|
|
7
11
|
publicUrl: string;
|
|
8
12
|
supabaseUrl: string;
|
|
9
13
|
supabaseAnonKey: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional per-turn delegation JWT (FU-5), narrower than `accessToken`.
|
|
16
|
+
* Env-only — never written to argv. Blank/whitespace-only is treated as
|
|
17
|
+
* absent.
|
|
18
|
+
*/
|
|
19
|
+
delegationToken?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional id of the agent this session is acting for, used for
|
|
22
|
+
* attribution of mutating tool calls. Forwarded via env
|
|
23
|
+
* (`ACC_AGENT_ID`) AND `--agent-id` argv (acc-mcp-server's current CLI
|
|
24
|
+
* only reads argv for this one; the env copy is forward-compatible, per
|
|
25
|
+
* the same pattern already used for `ACC_TASK_ID`/`ACC_RUNNER_ID`).
|
|
26
|
+
* Blank/whitespace-only is treated as absent.
|
|
27
|
+
*/
|
|
28
|
+
agentId?: string;
|
|
10
29
|
}
|
|
11
30
|
export interface McpConfigCleanup {
|
|
12
31
|
/** Restore .mcp.json to its pre-spawn state (or delete if we created it). */
|
package/dist/mcp-spawn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-spawn.d.ts","sourceRoot":"","sources":["../src/mcp-spawn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp-spawn.d.ts","sourceRoot":"","sources":["../src/mcp-spawn.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,WAAW,QAAQ,CAAC;AAKjC,kFAAkF;AAClF,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAMD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUtE;AAmFD,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAClD;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,eAAe,EACrB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA4B3B"}
|
package/dist/mcp-spawn.js
CHANGED
|
@@ -12,6 +12,22 @@
|
|
|
12
12
|
* merging our entry under `mcpServers.acc`, and restoring the prior
|
|
13
13
|
* contents on cleanup. If our entry is the only one, we delete the
|
|
14
14
|
* file entirely.
|
|
15
|
+
*
|
|
16
|
+
* NS MCP-2: the acc-mcp-server subprocess's argv is visible for its whole
|
|
17
|
+
* lifetime to anything that can run `ps` on the host. The access token is a
|
|
18
|
+
* broad runner JWT — it MUST NOT appear there. It travels via env only
|
|
19
|
+
* (`ACC_MCP_ACCESS_TOKEN`); acc-mcp-server's `cli.ts` already falls back to
|
|
20
|
+
* that env var when `--access-token` is absent from argv, so dropping the
|
|
21
|
+
* argv copy is a pure hardening change, not a protocol break.
|
|
22
|
+
*
|
|
23
|
+
* When a caller has a narrower per-turn delegation token (FU-5) and/or a
|
|
24
|
+
* calling agent's id available, forwarding them lets acc-mcp-server (a) swap
|
|
25
|
+
* the delegation token in as the Supabase Bearer — scoping tool calls to the
|
|
26
|
+
* delegation's claims instead of the full runner JWT, and gating them at the
|
|
27
|
+
* MC-12 bus risk gate under that narrower identity — and (b) attribute the
|
|
28
|
+
* turn's mutating calls to the right `agent_id` instead of falling back to
|
|
29
|
+
* the task's current agent. Both are OPTIONAL and env-only: no caller is
|
|
30
|
+
* required to supply them today, and neither is ever written to argv.
|
|
15
31
|
*/
|
|
16
32
|
import { promises as fs } from "node:fs";
|
|
17
33
|
import path from "node:path";
|
|
@@ -20,6 +36,10 @@ export const ACC_MCP_KEY = "acc";
|
|
|
20
36
|
const MCP_CONFIG_FILENAME = ".mcp.json";
|
|
21
37
|
const ACC_MCP_PACKAGE = "@tokenfactory/acc-mcp-server";
|
|
22
38
|
const ACC_MCP_BIN = "acc-mcp-server";
|
|
39
|
+
/** Env var acc-mcp-server reads the per-turn delegation JWT from (see cli.ts). */
|
|
40
|
+
export const ACC_MCP_DELEGATION_TOKEN_ENV = "ACC_MCP_DELEGATION_TOKEN";
|
|
41
|
+
/** Env var acc-mcp-server (future-facing) reads the calling agent's id from. */
|
|
42
|
+
export const ACC_AGENT_ID_ENV = "ACC_AGENT_ID";
|
|
23
43
|
/**
|
|
24
44
|
* Locate a globally installed binary by name. Returns the absolute
|
|
25
45
|
* path when found, or null otherwise. Used to skip the per-task
|
|
@@ -43,12 +63,13 @@ export async function whichBinary(name) {
|
|
|
43
63
|
}
|
|
44
64
|
}
|
|
45
65
|
function buildEnvBlock(opts) {
|
|
46
|
-
|
|
66
|
+
const env = {
|
|
47
67
|
SUPABASE_URL: opts.supabaseUrl,
|
|
48
68
|
SUPABASE_ANON_KEY: opts.supabaseAnonKey,
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
69
|
+
// NS MCP-2: env-only. acc-mcp-server's cli.ts falls back to this var
|
|
70
|
+
// whenever `--access-token` is absent from argv, so the broad runner
|
|
71
|
+
// JWT never has to appear in argv (`ps`-visible for the subprocess's
|
|
72
|
+
// whole lifetime).
|
|
52
73
|
ACC_MCP_ACCESS_TOKEN: opts.accessToken,
|
|
53
74
|
ACC_PUBLIC_URL: opts.publicUrl,
|
|
54
75
|
// Task + runner IDs are CLI-passed today (cli > env > default at
|
|
@@ -59,39 +80,44 @@ function buildEnvBlock(opts) {
|
|
|
59
80
|
ACC_TASK_ID: opts.taskId,
|
|
60
81
|
ACC_RUNNER_ID: opts.runnerId,
|
|
61
82
|
};
|
|
83
|
+
// NS MCP-2: forwarded ONLY via env, never argv — mirrors the chat lane's
|
|
84
|
+
// ACC_MCP_DELEGATION_TOKEN_ENV convention (engines/claude-code-chat.ts) so
|
|
85
|
+
// acc-mcp-server swaps this narrower per-turn identity in as the Supabase
|
|
86
|
+
// Bearer in place of the broad access token.
|
|
87
|
+
const delegationToken = (opts.delegationToken ?? "").trim();
|
|
88
|
+
if (delegationToken)
|
|
89
|
+
env[ACC_MCP_DELEGATION_TOKEN_ENV] = delegationToken;
|
|
90
|
+
// NS MCP-2: forward-compatible env copy of the agent id also passed via
|
|
91
|
+
// --agent-id below, so mutating tool calls attribute to the right agent.
|
|
92
|
+
const agentId = (opts.agentId ?? "").trim();
|
|
93
|
+
if (agentId)
|
|
94
|
+
env[ACC_AGENT_ID_ENV] = agentId;
|
|
95
|
+
return env;
|
|
96
|
+
}
|
|
97
|
+
/** Non-secret coordinate flags shared by both the global-bin and npx spawn shapes. */
|
|
98
|
+
function coordinateArgs(opts) {
|
|
99
|
+
const args = ["--task-id", opts.taskId, "--runner-id", opts.runnerId, "--public-url", opts.publicUrl];
|
|
100
|
+
const agentId = (opts.agentId ?? "").trim();
|
|
101
|
+
if (agentId)
|
|
102
|
+
args.push("--agent-id", agentId);
|
|
103
|
+
return args;
|
|
62
104
|
}
|
|
63
105
|
async function buildEntry(opts, which) {
|
|
64
106
|
const globalBin = await which(ACC_MCP_BIN);
|
|
107
|
+
// NS MCP-2: neither the access token nor the delegation token is ever
|
|
108
|
+
// written to argv — both travel exclusively via buildEnvBlock()'s env
|
|
109
|
+
// block (ps shows only non-secret coordinates: task/runner/agent ids and
|
|
110
|
+
// the public URL).
|
|
65
111
|
if (globalBin) {
|
|
66
112
|
return {
|
|
67
113
|
command: globalBin,
|
|
68
|
-
args:
|
|
69
|
-
"--task-id",
|
|
70
|
-
opts.taskId,
|
|
71
|
-
"--runner-id",
|
|
72
|
-
opts.runnerId,
|
|
73
|
-
"--access-token",
|
|
74
|
-
opts.accessToken,
|
|
75
|
-
"--public-url",
|
|
76
|
-
opts.publicUrl,
|
|
77
|
-
],
|
|
114
|
+
args: coordinateArgs(opts),
|
|
78
115
|
env: buildEnvBlock(opts),
|
|
79
116
|
};
|
|
80
117
|
}
|
|
81
118
|
return {
|
|
82
119
|
command: "npx",
|
|
83
|
-
args: [
|
|
84
|
-
"-y",
|
|
85
|
-
ACC_MCP_PACKAGE,
|
|
86
|
-
"--task-id",
|
|
87
|
-
opts.taskId,
|
|
88
|
-
"--runner-id",
|
|
89
|
-
opts.runnerId,
|
|
90
|
-
"--access-token",
|
|
91
|
-
opts.accessToken,
|
|
92
|
-
"--public-url",
|
|
93
|
-
opts.publicUrl,
|
|
94
|
-
],
|
|
120
|
+
args: ["-y", ACC_MCP_PACKAGE, ...coordinateArgs(opts)],
|
|
95
121
|
env: buildEnvBlock(opts),
|
|
96
122
|
};
|
|
97
123
|
}
|
package/dist/mcp-spawn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-spawn.js","sourceRoot":"","sources":["../src/mcp-spawn.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mcp-spawn.js","sourceRoot":"","sources":["../src/mcp-spawn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** Kill switch. Set to `0`/`false` to skip the pre-push re-validation entirely. */
|
|
2
|
+
export declare const SEQ_GUARD_ENV = "ACC_MIGRATION_SEQ_GUARD";
|
|
3
|
+
/** Every reason the guard can decline to renumber, for the runner log. */
|
|
4
|
+
export type SeqGuardSkipReason = "disabled" | "no-base-ref" | "no-new-migrations" | "no-remote-seqs" | "seq-free" | "renumber-noop" | "renumber-failed";
|
|
5
|
+
export interface SeqGuardRenumber {
|
|
6
|
+
/** Repo-relative path the migration had before the guard ran. */
|
|
7
|
+
file: string;
|
|
8
|
+
/** Repo-relative path it now has. */
|
|
9
|
+
newFile: string;
|
|
10
|
+
/** Numeric seq before → after. */
|
|
11
|
+
fromSeq: number;
|
|
12
|
+
toSeq: number;
|
|
13
|
+
/** Tail of the renumber tool's own log (which refs it rewrote). */
|
|
14
|
+
output: string;
|
|
15
|
+
}
|
|
16
|
+
export interface SeqGuardResult {
|
|
17
|
+
/** True iff a migration was renumbered AND the rename was committed. */
|
|
18
|
+
renumbered: boolean;
|
|
19
|
+
/** Why nothing happened. Unset when `renumbered` is true. */
|
|
20
|
+
skipped?: SeqGuardSkipReason;
|
|
21
|
+
/** Human-readable one-liner for the runner log — always set. */
|
|
22
|
+
detail: string;
|
|
23
|
+
/** Highest seq seen on the freshly-fetched integration head (null if unread). */
|
|
24
|
+
remoteMaxSeq?: number | null;
|
|
25
|
+
/** The move, when one happened. */
|
|
26
|
+
move?: SeqGuardRenumber;
|
|
27
|
+
}
|
|
28
|
+
export interface SeqGuardOptions {
|
|
29
|
+
/** Integration branch this task will target, e.g. `acc/integration`. */
|
|
30
|
+
integrationBranch: string;
|
|
31
|
+
/** Merge-base ref the new-migration diff is taken against. */
|
|
32
|
+
baseRef?: string;
|
|
33
|
+
/** Remote to re-fetch. Defaults to `origin`. */
|
|
34
|
+
remote?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Live `acc.applied_migrations` seqs, when the caller can read them. Unioned
|
|
37
|
+
* with the fresh remote head so a migration applied out-of-band still counts
|
|
38
|
+
* as claimed. Omitted → the remote head alone is the baseline.
|
|
39
|
+
*/
|
|
40
|
+
appliedSeqs?: number[] | null;
|
|
41
|
+
}
|
|
42
|
+
export interface SeqGuardDeps {
|
|
43
|
+
env?: NodeJS.ProcessEnv;
|
|
44
|
+
/** `git fetch <remote> <branch>`. Rejects → treated as "no fresh head". */
|
|
45
|
+
fetchRef?: (workdir: string, remote: string, branch: string) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Migration paths present on the freshly-fetched head, repo-relative. Returns
|
|
48
|
+
* `null` when the ref could not be read (the guard then stands down).
|
|
49
|
+
*/
|
|
50
|
+
listRemoteMigrations?: (workdir: string, ref: string) => Promise<string[] | null>;
|
|
51
|
+
/** Migration files this branch ADDED vs `baseRef`, repo-relative. */
|
|
52
|
+
listAddedMigrations?: (workdir: string, baseRef?: string) => Promise<string[]>;
|
|
53
|
+
/** Run the renumber pass with an out-of-tree baseline roster. */
|
|
54
|
+
runRenumber?: (workdir: string, files: string[], baselineSeqs: number[]) => Promise<{
|
|
55
|
+
output: string;
|
|
56
|
+
}>;
|
|
57
|
+
/** True when the working tree has uncommitted changes (did the renumber act?). */
|
|
58
|
+
isDirty?: (workdir: string) => Promise<boolean>;
|
|
59
|
+
/** Commit the rename so the push carries it. */
|
|
60
|
+
commit?: (workdir: string, message: string) => Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The numeric sequence prefix of a migration path (`…/0315_acc_x.sql` → 315),
|
|
64
|
+
* or null when the filename does not carry one. Mirrors `parseSeq` in
|
|
65
|
+
* scripts/ci/migration-lint.mjs — the two must agree on what counts as a
|
|
66
|
+
* migration, so both accept `_` and `-` after the digits.
|
|
67
|
+
*/
|
|
68
|
+
export declare function migrationSeq(file: string): number | null;
|
|
69
|
+
/** Whether the guard is enabled. ON by default; `0`/`false`/`no` turns it off. */
|
|
70
|
+
export declare function seqGuardEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Re-validate this branch's NEW migration seq against a freshly-fetched
|
|
73
|
+
* integration head and auto-renumber it when a sibling has since taken the
|
|
74
|
+
* number. Returns what happened; NEVER throws (a crash inside the guard is
|
|
75
|
+
* reported as `renumber-failed` and the push proceeds).
|
|
76
|
+
*/
|
|
77
|
+
export declare function revalidateMigrationSeq(workdir: string, opts: SeqGuardOptions, deps?: SeqGuardDeps): Promise<SeqGuardResult>;
|
|
78
|
+
//# sourceMappingURL=migration-seq-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-seq-guard.d.ts","sourceRoot":"","sources":["../src/migration-seq-guard.ts"],"names":[],"mappings":"AAkDA,mFAAmF;AACnF,eAAO,MAAM,aAAa,4BAA4B,CAAC;AAIvD,0EAA0E;AAC1E,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,aAAa,GACb,mBAAmB,GACnB,gBAAgB,GAChB,UAAU,GACV,eAAe,GACf,iBAAiB,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;IACpB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mCAAmC;IACnC,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IAClF,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E,iEAAiE;IACjE,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,EACf,YAAY,EAAE,MAAM,EAAE,KACnB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjC,kFAAkF;IAClF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,gDAAgD;IAChD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxD;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAI7E;AAwGD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EACrB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CAgKzB"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MIG-SEQ-GUARD — re-validate a branch's migration sequence against a FRESHLY
|
|
3
|
+
* FETCHED integration head, immediately before push.
|
|
4
|
+
*
|
|
5
|
+
* The recurring failure it closes (0310 → 0314 → 0315, two collisions in 24h):
|
|
6
|
+
* an agent computes its next-free migration seq at worktree-FORK time — the max
|
|
7
|
+
* of `supabase/migrations/` in the fork snapshot plus the applied ledger. That
|
|
8
|
+
* number is correct when it is chosen and stale by the time the branch pushes,
|
|
9
|
+
* because a sibling migration merged into `acc/integration` in between and took
|
|
10
|
+
* it. `scripts/ci/migration-lint.mjs` catches the collision at PR time, but only
|
|
11
|
+
* after the whole run is spent: the task rework-loops for a rename it could have
|
|
12
|
+
* done itself. Two migration tasks dispatched concurrently hit it every time.
|
|
13
|
+
*
|
|
14
|
+
* MIGFIX-01 (prepr-gate.ts) already auto-renumbers, but it reads the SAME stale
|
|
15
|
+
* worktree snapshot, so it recomputes exactly the seq the sibling took. The fix
|
|
16
|
+
* is not a better computation — it is a fresher input. So right before push:
|
|
17
|
+
*
|
|
18
|
+
* 1. `git fetch <remote> <integration>` — a real network read, not the fork's
|
|
19
|
+
* remote-tracking ref.
|
|
20
|
+
* 2. Read the migration seqs present on that fresh head (`git ls-tree`), and
|
|
21
|
+
* union them with the live `acc.applied_migrations` roster when the caller
|
|
22
|
+
* has one.
|
|
23
|
+
* 3. If this branch's NEW migration no longer holds a free seq (its number is
|
|
24
|
+
* at or below that fresh baseline), hand the roster to
|
|
25
|
+
* `migration-lint.mjs --renumber --baseline-seqs …`, which already rewrites
|
|
26
|
+
* the filename, the `record_migration_applied` self-record, the verify
|
|
27
|
+
* RAISE messages and every sibling test that reads the file by path.
|
|
28
|
+
* 4. Commit the rename so the push carries it, and report the move so the
|
|
29
|
+
* caller can emit an event.
|
|
30
|
+
*
|
|
31
|
+
* FAIL-OPEN by construction. Every step that touches the network or git is
|
|
32
|
+
* best-effort: an unreachable remote, a missing ref, a renumber that changed
|
|
33
|
+
* nothing — each returns a `ran: false` result with a reason, and the push
|
|
34
|
+
* proceeds exactly as it does today. The guard may only ever turn a PR that CI
|
|
35
|
+
* would reject into one it accepts; it must never be the reason a push fails.
|
|
36
|
+
*
|
|
37
|
+
* Two deliberate non-behaviours:
|
|
38
|
+
* • It does NOT act on a forward GAP (a seq ABOVE the fresh baseline + 1).
|
|
39
|
+
* A gap is MIGFIX-01's job at fork time, and after a sibling merges, the
|
|
40
|
+
* local `supabase/migrations/` is legitimately behind the remote — closing
|
|
41
|
+
* "gaps" against a tree that is missing files would renumber healthy
|
|
42
|
+
* branches. Only a seq that is provably TAKEN is moved.
|
|
43
|
+
* • It commits, it never amends. A rework branch's history is already pushed;
|
|
44
|
+
* amending it would force a non-fast-forward push. Same posture as
|
|
45
|
+
* MIGFIX-01's `defaultCommitRenumbered`.
|
|
46
|
+
*/
|
|
47
|
+
import path from "node:path";
|
|
48
|
+
import { execa } from "execa";
|
|
49
|
+
import { buildEnv } from "./bin-resolve.js";
|
|
50
|
+
/** Kill switch. Set to `0`/`false` to skip the pre-push re-validation entirely. */
|
|
51
|
+
export const SEQ_GUARD_ENV = "ACC_MIGRATION_SEQ_GUARD";
|
|
52
|
+
const MIGRATIONS_DIR = "supabase/migrations";
|
|
53
|
+
/**
|
|
54
|
+
* The numeric sequence prefix of a migration path (`…/0315_acc_x.sql` → 315),
|
|
55
|
+
* or null when the filename does not carry one. Mirrors `parseSeq` in
|
|
56
|
+
* scripts/ci/migration-lint.mjs — the two must agree on what counts as a
|
|
57
|
+
* migration, so both accept `_` and `-` after the digits.
|
|
58
|
+
*/
|
|
59
|
+
export function migrationSeq(file) {
|
|
60
|
+
const base = String(file).split(/[\\/]/).pop() ?? "";
|
|
61
|
+
const m = /^(\d+)[_-].+\.sql$/i.exec(base);
|
|
62
|
+
if (!m)
|
|
63
|
+
return null;
|
|
64
|
+
const n = parseInt(m[1], 10);
|
|
65
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
66
|
+
}
|
|
67
|
+
/** Whether the guard is enabled. ON by default; `0`/`false`/`no` turns it off. */
|
|
68
|
+
export function seqGuardEnabled(env = process.env) {
|
|
69
|
+
const raw = env[SEQ_GUARD_ENV]?.trim().toLowerCase();
|
|
70
|
+
if (raw === undefined || raw === "")
|
|
71
|
+
return true;
|
|
72
|
+
return !(raw === "0" || raw === "false" || raw === "no" || raw === "off");
|
|
73
|
+
}
|
|
74
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
75
|
+
// Default I/O (every one is injectable; the unit suite never shells out)
|
|
76
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
77
|
+
async function defaultFetchRef(workdir, remote, branch) {
|
|
78
|
+
// A single-branch fetch, not `--all`: this runs on the push hot path and the
|
|
79
|
+
// only ref whose freshness matters is the integration head.
|
|
80
|
+
const res = await execa("git", ["fetch", "--quiet", remote, branch], {
|
|
81
|
+
cwd: workdir,
|
|
82
|
+
env: buildEnv(),
|
|
83
|
+
reject: false,
|
|
84
|
+
});
|
|
85
|
+
if (res.exitCode !== 0) {
|
|
86
|
+
throw new Error(`git fetch ${remote} ${branch} exited ${res.exitCode ?? "signal"}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function defaultListRemoteMigrations(workdir, ref) {
|
|
90
|
+
const res = await execa("git", ["ls-tree", "-r", "--name-only", ref, "--", MIGRATIONS_DIR], { cwd: workdir, env: buildEnv(), reject: false });
|
|
91
|
+
if (res.exitCode !== 0)
|
|
92
|
+
return null;
|
|
93
|
+
return (res.stdout ?? "")
|
|
94
|
+
.split("\n")
|
|
95
|
+
.map((s) => s.trim())
|
|
96
|
+
.filter((s) => s.toLowerCase().endsWith(".sql"));
|
|
97
|
+
}
|
|
98
|
+
async function defaultListAddedMigrations(workdir, baseRef) {
|
|
99
|
+
if (!baseRef)
|
|
100
|
+
return [];
|
|
101
|
+
// `--diff-filter=A` (added only): a MODIFIED published migration must never be
|
|
102
|
+
// renumbered — that is the forward-only violation the linter already rejects.
|
|
103
|
+
const res = await execa("git", ["diff", "--name-only", "--diff-filter=A", `${baseRef}...HEAD`, "--", MIGRATIONS_DIR], { cwd: workdir, env: buildEnv(), reject: false });
|
|
104
|
+
if (res.exitCode !== 0)
|
|
105
|
+
return [];
|
|
106
|
+
return (res.stdout ?? "")
|
|
107
|
+
.split("\n")
|
|
108
|
+
.map((s) => s.trim())
|
|
109
|
+
.filter((s) => s.toLowerCase().endsWith(".sql"));
|
|
110
|
+
}
|
|
111
|
+
async function defaultRunRenumber(workdir, files, baselineSeqs) {
|
|
112
|
+
const script = path.join(workdir, "scripts", "ci", "migration-lint.mjs");
|
|
113
|
+
const args = ["--renumber"];
|
|
114
|
+
if (baselineSeqs.length > 0)
|
|
115
|
+
args.push("--baseline-seqs", baselineSeqs.join(","));
|
|
116
|
+
// `process.execPath`, not a bare "node": the runner may be launched by
|
|
117
|
+
// launchd with a PATH that has no node at all, and a silently-unspawnable
|
|
118
|
+
// renumber reads exactly like a clean no-op (empty output, clean tree).
|
|
119
|
+
const res = await execa(process.execPath, [script, ...args, ...files], {
|
|
120
|
+
cwd: workdir,
|
|
121
|
+
env: buildEnv(),
|
|
122
|
+
reject: false,
|
|
123
|
+
});
|
|
124
|
+
// `reject: false` resolves with the failure rather than throwing, so a spawn
|
|
125
|
+
// error (no node on PATH) arrives as a result whose exit code is not 0 and
|
|
126
|
+
// whose explanation lives on `shortMessage` — present at runtime on the
|
|
127
|
+
// failure shape, absent from execa's success type.
|
|
128
|
+
const shortMessage = res.shortMessage;
|
|
129
|
+
const spawnFailure = res.exitCode === 0 ? "" : `\n[exit ${res.exitCode ?? "signal"}] ${shortMessage ?? ""}`;
|
|
130
|
+
return { output: `${res.stdout ?? ""}\n${res.stderr ?? ""}${spawnFailure}`.trim() };
|
|
131
|
+
}
|
|
132
|
+
async function defaultIsDirty(workdir) {
|
|
133
|
+
const res = await execa("git", ["status", "--porcelain"], {
|
|
134
|
+
cwd: workdir,
|
|
135
|
+
env: buildEnv(),
|
|
136
|
+
reject: false,
|
|
137
|
+
});
|
|
138
|
+
return (res.stdout ?? "").trim().length > 0;
|
|
139
|
+
}
|
|
140
|
+
async function defaultCommit(workdir, message) {
|
|
141
|
+
await execa("git", ["add", "-A"], { cwd: workdir, env: buildEnv(), reject: false });
|
|
142
|
+
await execa("git", ["commit", "-m", message], {
|
|
143
|
+
cwd: workdir,
|
|
144
|
+
env: buildEnv(),
|
|
145
|
+
reject: false,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
149
|
+
// The guard
|
|
150
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
151
|
+
const OUTPUT_TAIL = 2_000;
|
|
152
|
+
/**
|
|
153
|
+
* Re-validate this branch's NEW migration seq against a freshly-fetched
|
|
154
|
+
* integration head and auto-renumber it when a sibling has since taken the
|
|
155
|
+
* number. Returns what happened; NEVER throws (a crash inside the guard is
|
|
156
|
+
* reported as `renumber-failed` and the push proceeds).
|
|
157
|
+
*/
|
|
158
|
+
export async function revalidateMigrationSeq(workdir, opts, deps = {}) {
|
|
159
|
+
const env = deps.env ?? process.env;
|
|
160
|
+
if (!seqGuardEnabled(env)) {
|
|
161
|
+
return {
|
|
162
|
+
renumbered: false,
|
|
163
|
+
skipped: "disabled",
|
|
164
|
+
detail: `${SEQ_GUARD_ENV} disables the pre-push migration seq re-validation`,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (!opts.baseRef) {
|
|
168
|
+
return {
|
|
169
|
+
renumbered: false,
|
|
170
|
+
skipped: "no-base-ref",
|
|
171
|
+
detail: "no base ref — cannot tell which migrations this branch added",
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const remote = opts.remote ?? "origin";
|
|
175
|
+
const listAdded = deps.listAddedMigrations ?? defaultListAddedMigrations;
|
|
176
|
+
try {
|
|
177
|
+
// Cheapest check first: a task that adds no migration never fetches. This is
|
|
178
|
+
// the overwhelming majority of pushes, and the whole happy path stays a
|
|
179
|
+
// single `git diff`.
|
|
180
|
+
const added = (await listAdded(workdir, opts.baseRef)).filter((f) => migrationSeq(f) !== null);
|
|
181
|
+
if (added.length === 0) {
|
|
182
|
+
return {
|
|
183
|
+
renumbered: false,
|
|
184
|
+
skipped: "no-new-migrations",
|
|
185
|
+
detail: "branch adds no migration — seq re-validation not needed",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const fetchRef = deps.fetchRef ?? defaultFetchRef;
|
|
189
|
+
const listRemote = deps.listRemoteMigrations ?? defaultListRemoteMigrations;
|
|
190
|
+
// The fetch is the entire point: the fork-time remote-tracking ref is what
|
|
191
|
+
// produced the stale seq in the first place.
|
|
192
|
+
let fetched = true;
|
|
193
|
+
try {
|
|
194
|
+
await fetchRef(workdir, remote, opts.integrationBranch);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
fetched = false;
|
|
198
|
+
}
|
|
199
|
+
// Prefer FETCH_HEAD (what this fetch just wrote) over the remote-tracking
|
|
200
|
+
// ref, which a fetch refspec may not have updated. Fall back to the
|
|
201
|
+
// tracking ref so a failed fetch can still be checked against whatever the
|
|
202
|
+
// worktree already knows.
|
|
203
|
+
const refs = fetched
|
|
204
|
+
? ["FETCH_HEAD", `${remote}/${opts.integrationBranch}`]
|
|
205
|
+
: [`${remote}/${opts.integrationBranch}`];
|
|
206
|
+
let remoteFiles = null;
|
|
207
|
+
for (const ref of refs) {
|
|
208
|
+
remoteFiles = await listRemote(workdir, ref);
|
|
209
|
+
if (remoteFiles && remoteFiles.length > 0)
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
if (!remoteFiles || remoteFiles.length === 0) {
|
|
213
|
+
return {
|
|
214
|
+
renumbered: false,
|
|
215
|
+
skipped: "no-remote-seqs",
|
|
216
|
+
detail: `could not read ${MIGRATIONS_DIR} on a fresh ${remote}/${opts.integrationBranch} ` +
|
|
217
|
+
`(fetch ${fetched ? "ok" : "failed"}) — seq left as-is`,
|
|
218
|
+
remoteMaxSeq: null,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
// The baseline: everything claimed OUTSIDE this worktree. The remote head's
|
|
222
|
+
// seqs, plus the live ledger when the caller could read it (a migration can
|
|
223
|
+
// be applied before its file merges).
|
|
224
|
+
const claimed = new Set();
|
|
225
|
+
for (const f of remoteFiles) {
|
|
226
|
+
const n = migrationSeq(f);
|
|
227
|
+
if (n !== null)
|
|
228
|
+
claimed.add(n);
|
|
229
|
+
}
|
|
230
|
+
for (const n of opts.appliedSeqs ?? []) {
|
|
231
|
+
if (Number.isFinite(n) && n > 0)
|
|
232
|
+
claimed.add(Math.trunc(n));
|
|
233
|
+
}
|
|
234
|
+
const baselineSeqs = [...claimed].sort((a, b) => a - b);
|
|
235
|
+
const remoteMaxSeq = baselineSeqs.length > 0 ? baselineSeqs[baselineSeqs.length - 1] : null;
|
|
236
|
+
// Stale = at or below the fresh baseline: either the exact number a sibling
|
|
237
|
+
// took, or one behind it. A seq ABOVE the baseline is left alone (see the
|
|
238
|
+
// module header — a forward gap is MIGFIX-01's call, not the guard's).
|
|
239
|
+
const stale = added.filter((f) => {
|
|
240
|
+
const n = migrationSeq(f);
|
|
241
|
+
return n !== null && remoteMaxSeq !== null && n <= remoteMaxSeq;
|
|
242
|
+
});
|
|
243
|
+
if (stale.length === 0) {
|
|
244
|
+
return {
|
|
245
|
+
renumbered: false,
|
|
246
|
+
skipped: "seq-free",
|
|
247
|
+
detail: `migration seq still free on a fresh ${remote}/${opts.integrationBranch} ` +
|
|
248
|
+
`(head max ${remoteMaxSeq ?? "n/a"}) — pushing unchanged`,
|
|
249
|
+
remoteMaxSeq,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const runRenumber = deps.runRenumber ?? defaultRunRenumber;
|
|
253
|
+
const isDirty = deps.isDirty ?? defaultIsDirty;
|
|
254
|
+
const commit = deps.commit ?? defaultCommit;
|
|
255
|
+
const { output } = await runRenumber(workdir, stale, baselineSeqs);
|
|
256
|
+
if (!(await isDirty(workdir))) {
|
|
257
|
+
return {
|
|
258
|
+
renumbered: false,
|
|
259
|
+
skipped: "renumber-noop",
|
|
260
|
+
// Carry the tool's own log: "left unchanged" is either a genuine no-op
|
|
261
|
+
// or a renumber that could not run, and only the log tells them apart.
|
|
262
|
+
detail: `renumber left the worktree unchanged — seq kept: ${stale.join(", ")}; ` +
|
|
263
|
+
`tool said: ${output.slice(-500) || "(no output)"}`,
|
|
264
|
+
remoteMaxSeq,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
// `move` describes the FIRST stale file. A branch adding several colliding
|
|
268
|
+
// migrations at once is vanishingly rare, and the renumber tool chains them
|
|
269
|
+
// correctly anyway (each pass re-reads the directory, so the second lands
|
|
270
|
+
// above the first). The full tool log rides along in `move.output`, so the
|
|
271
|
+
// event is never lossy even then.
|
|
272
|
+
const first = stale[0];
|
|
273
|
+
const fromSeq = migrationSeq(first);
|
|
274
|
+
// The tool's own log names the move (`0315 → 0316`); prefer it, and fall
|
|
275
|
+
// back to the arithmetic the tool would have used so the event is never
|
|
276
|
+
// empty just because the log format shifts.
|
|
277
|
+
const moved = /(\d{2,})\s*→\s*(\d{2,})/.exec(output);
|
|
278
|
+
const toSeq = moved ? Number(moved[2]) : (remoteMaxSeq ?? fromSeq) + 1;
|
|
279
|
+
const newFile = path.join(path.dirname(first), path.basename(first).replace(/^\d+/, String(toSeq).padStart(4, "0")));
|
|
280
|
+
await commit(workdir, `chore(acc): re-validate migration seq against fresh ${opts.integrationBranch} (MIG-SEQ-GUARD)`);
|
|
281
|
+
return {
|
|
282
|
+
renumbered: true,
|
|
283
|
+
detail: `migration seq ${fromSeq} was taken on a fresh ${remote}/${opts.integrationBranch} ` +
|
|
284
|
+
`(head max ${remoteMaxSeq}) — auto-renumbered to ${toSeq} before push`,
|
|
285
|
+
remoteMaxSeq,
|
|
286
|
+
move: {
|
|
287
|
+
file: first,
|
|
288
|
+
newFile,
|
|
289
|
+
fromSeq,
|
|
290
|
+
toSeq,
|
|
291
|
+
output: output.slice(-OUTPUT_TAIL),
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
// Fail-open: the guard may only ever IMPROVE a push's odds.
|
|
297
|
+
return {
|
|
298
|
+
renumbered: false,
|
|
299
|
+
skipped: "renumber-failed",
|
|
300
|
+
detail: `seq re-validation crashed (push proceeds): ${err.message?.slice(0, 300)}`,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=migration-seq-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-seq-guard.js","sourceRoot":"","sources":["../src/migration-seq-guard.ts"],"names":[],"mappings":"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"}
|