@tokenfactory/acc-runner 0.44.0 → 0.44.2
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 +43 -1
- package/dist/bin-resolve.d.ts +39 -3
- package/dist/bin-resolve.d.ts.map +1 -1
- package/dist/bin-resolve.js +176 -12
- package/dist/bin-resolve.js.map +1 -1
- package/dist/build-fingerprint.d.ts +66 -0
- package/dist/build-fingerprint.d.ts.map +1 -0
- package/dist/build-fingerprint.js +70 -0
- package/dist/build-fingerprint.js.map +1 -0
- package/dist/build-info.generated.d.ts +3 -0
- package/dist/build-info.generated.d.ts.map +1 -0
- package/dist/build-info.generated.js +3 -0
- package/dist/build-info.generated.js.map +1 -0
- package/dist/capacity/resume-controller.d.ts +5 -3
- package/dist/capacity/resume-controller.d.ts.map +1 -1
- package/dist/capacity/resume-controller.js +9 -0
- package/dist/capacity/resume-controller.js.map +1 -1
- package/dist/chat-delegation-guard.d.ts +23 -0
- package/dist/chat-delegation-guard.d.ts.map +1 -0
- package/dist/chat-delegation-guard.js +62 -0
- package/dist/chat-delegation-guard.js.map +1 -0
- package/dist/chat-lane.d.ts +17 -6
- package/dist/chat-lane.d.ts.map +1 -1
- package/dist/chat-lane.js +29 -8
- package/dist/chat-lane.js.map +1 -1
- package/dist/companion-identity.d.ts +37 -0
- package/dist/companion-identity.d.ts.map +1 -1
- package/dist/companion-identity.js +98 -29
- package/dist/companion-identity.js.map +1 -1
- package/dist/companion-run.d.ts +1 -50
- package/dist/companion-run.d.ts.map +1 -1
- package/dist/companion-run.js +48 -105
- package/dist/companion-run.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -3
- package/dist/config.js.map +1 -1
- package/dist/conformance.d.ts +49 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +121 -0
- package/dist/conformance.js.map +1 -0
- package/dist/cost-pricing.d.ts +91 -0
- package/dist/cost-pricing.d.ts.map +1 -1
- package/dist/cost-pricing.js +115 -1
- package/dist/cost-pricing.js.map +1 -1
- package/dist/credential-identity.d.ts +70 -0
- package/dist/credential-identity.d.ts.map +1 -0
- package/dist/credential-identity.js +128 -0
- package/dist/credential-identity.js.map +1 -0
- package/dist/doctor.d.ts +37 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +300 -41
- package/dist/doctor.js.map +1 -1
- package/dist/engines/chat-stream.d.ts +71 -1
- package/dist/engines/chat-stream.d.ts.map +1 -1
- package/dist/engines/chat-stream.js +126 -8
- package/dist/engines/chat-stream.js.map +1 -1
- package/dist/engines/claude-code-chat.d.ts +11 -1
- package/dist/engines/claude-code-chat.d.ts.map +1 -1
- package/dist/engines/claude-code-chat.js +69 -5
- package/dist/engines/claude-code-chat.js.map +1 -1
- package/dist/engines/claude-code.d.ts.map +1 -1
- package/dist/engines/claude-code.js +30 -6
- package/dist/engines/claude-code.js.map +1 -1
- package/dist/engines/codex.d.ts.map +1 -1
- package/dist/engines/codex.js +18 -5
- package/dist/engines/codex.js.map +1 -1
- package/dist/engines/registry.d.ts +26 -0
- package/dist/engines/registry.d.ts.map +1 -1
- package/dist/engines/registry.js +37 -0
- package/dist/engines/registry.js.map +1 -1
- package/dist/engines/types.d.ts +5 -0
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/failure-classifier.d.ts +1 -1
- package/dist/failure-classifier.d.ts.map +1 -1
- package/dist/failure-classifier.js +65 -12
- package/dist/failure-classifier.js.map +1 -1
- package/dist/gh.d.ts +15 -0
- package/dist/gh.d.ts.map +1 -1
- package/dist/gh.js +18 -0
- package/dist/gh.js.map +1 -1
- package/dist/git.d.ts +6 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +27 -1
- package/dist/git.js.map +1 -1
- package/dist/instance.d.ts +30 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +51 -0
- package/dist/instance.js.map +1 -0
- package/dist/keychain.d.ts +20 -7
- package/dist/keychain.d.ts.map +1 -1
- package/dist/keychain.js +40 -4
- package/dist/keychain.js.map +1 -1
- package/dist/loc-advisory.d.ts +70 -0
- package/dist/loc-advisory.d.ts.map +1 -0
- package/dist/loc-advisory.js +196 -0
- package/dist/loc-advisory.js.map +1 -0
- package/dist/locks/claim-lock-policy.d.ts +67 -0
- package/dist/locks/claim-lock-policy.d.ts.map +1 -0
- package/dist/locks/claim-lock-policy.js +132 -0
- package/dist/locks/claim-lock-policy.js.map +1 -0
- package/dist/login.d.ts +63 -2
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +93 -8
- package/dist/login.js.map +1 -1
- package/dist/mcp-spawn.d.ts +54 -0
- package/dist/mcp-spawn.d.ts.map +1 -1
- package/dist/mcp-spawn.js +88 -4
- package/dist/mcp-spawn.js.map +1 -1
- package/dist/memory-context.d.ts +106 -0
- package/dist/memory-context.d.ts.map +1 -0
- package/dist/memory-context.js +220 -0
- package/dist/memory-context.js.map +1 -0
- package/dist/memory-curation.d.ts +172 -0
- package/dist/memory-curation.d.ts.map +1 -0
- package/dist/memory-curation.js +277 -0
- package/dist/memory-curation.js.map +1 -0
- package/dist/migration-seq-guard.d.ts +28 -1
- package/dist/migration-seq-guard.d.ts.map +1 -1
- package/dist/migration-seq-guard.js +111 -6
- package/dist/migration-seq-guard.js.map +1 -1
- package/dist/output-diagnostics.d.ts +15 -0
- package/dist/output-diagnostics.d.ts.map +1 -0
- package/dist/output-diagnostics.js +95 -0
- package/dist/output-diagnostics.js.map +1 -0
- package/dist/pr-open-guard.d.ts +67 -0
- package/dist/pr-open-guard.d.ts.map +1 -0
- package/dist/pr-open-guard.js +79 -0
- package/dist/pr-open-guard.js.map +1 -0
- package/dist/prepr-gate.d.ts +229 -1
- package/dist/prepr-gate.d.ts.map +1 -1
- package/dist/prepr-gate.js +406 -3
- package/dist/prepr-gate.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +43 -5
- package/dist/program.js.map +1 -1
- package/dist/provider-auth.d.ts +27 -0
- package/dist/provider-auth.d.ts.map +1 -1
- package/dist/provider-auth.js +33 -0
- package/dist/provider-auth.js.map +1 -1
- package/dist/runtime/cache-dir.d.ts.map +1 -1
- package/dist/runtime/cache-dir.js +8 -3
- package/dist/runtime/cache-dir.js.map +1 -1
- package/dist/runtime/decision-provenance.d.ts +63 -0
- package/dist/runtime/decision-provenance.d.ts.map +1 -0
- package/dist/runtime/decision-provenance.js +107 -0
- package/dist/runtime/decision-provenance.js.map +1 -0
- package/dist/runtime/prompt-substitute.d.ts +100 -0
- package/dist/runtime/prompt-substitute.d.ts.map +1 -0
- package/dist/runtime/prompt-substitute.js +124 -0
- package/dist/runtime/prompt-substitute.js.map +1 -0
- package/dist/runtime/quarantine.d.ts +11 -0
- package/dist/runtime/quarantine.d.ts.map +1 -1
- package/dist/runtime/quarantine.js +16 -1
- package/dist/runtime/quarantine.js.map +1 -1
- package/dist/runtime/review-cost-cap.d.ts +167 -0
- package/dist/runtime/review-cost-cap.d.ts.map +1 -0
- package/dist/runtime/review-cost-cap.js +182 -0
- package/dist/runtime/review-cost-cap.js.map +1 -0
- package/dist/runtime/reviewer-abstain.d.ts +101 -0
- package/dist/runtime/reviewer-abstain.d.ts.map +1 -0
- package/dist/runtime/reviewer-abstain.js +138 -0
- package/dist/runtime/reviewer-abstain.js.map +1 -0
- package/dist/runtime/reviewer.d.ts +165 -2
- package/dist/runtime/reviewer.d.ts.map +1 -1
- package/dist/runtime/reviewer.js +752 -111
- package/dist/runtime/reviewer.js.map +1 -1
- package/dist/runtime/running-build.d.ts +24 -0
- package/dist/runtime/running-build.d.ts.map +1 -0
- package/dist/runtime/running-build.js +62 -0
- package/dist/runtime/running-build.js.map +1 -0
- package/dist/runtime/singleton.d.ts.map +1 -1
- package/dist/runtime/singleton.js +9 -1
- package/dist/runtime/singleton.js.map +1 -1
- package/dist/runtime/worktree.d.ts +45 -0
- package/dist/runtime/worktree.d.ts.map +1 -1
- package/dist/runtime/worktree.js +174 -5
- package/dist/runtime/worktree.js.map +1 -1
- package/dist/serving-auth/index.d.ts +79 -0
- package/dist/serving-auth/index.d.ts.map +1 -0
- package/dist/serving-auth/index.js +169 -0
- package/dist/serving-auth/index.js.map +1 -0
- package/dist/task-runner.d.ts +134 -5
- package/dist/task-runner.d.ts.map +1 -1
- package/dist/task-runner.js +1255 -129
- package/dist/task-runner.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/watch-chat/wire.d.ts +80 -0
- package/dist/watch-chat/wire.d.ts.map +1 -1
- package/dist/watch-chat/wire.js +203 -43
- package/dist/watch-chat/wire.js.map +1 -1
- package/dist/watch.d.ts +70 -16
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +548 -108
- package/dist/watch.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Heading of the generated section. Matched case-insensitively on splice. */
|
|
2
|
+
export declare const LOC_ADVISORY_HEADING = "## LOC advisory";
|
|
3
|
+
/** `kind` of the structured task_event emitted alongside the section. */
|
|
4
|
+
export declare const LOC_ADVISORY_EVENT_KIND = "loc_advisory";
|
|
5
|
+
/** House guideline (CLAUDE.md "≤300 LOC per commit"), read as IMPL lines. */
|
|
6
|
+
export declare const HOUSE_IMPL_LOC_GUIDELINE = 300;
|
|
7
|
+
/** Added/removed lines of a diff, split into implementation vs test files. */
|
|
8
|
+
export interface LocSplit {
|
|
9
|
+
/** Added lines: non-test / test / both, then removed lines (never budgeted). */
|
|
10
|
+
impl: number;
|
|
11
|
+
tests: number;
|
|
12
|
+
total: number;
|
|
13
|
+
removed: number;
|
|
14
|
+
}
|
|
15
|
+
/** LOC ceilings declared by a task's acceptance criteria; null = undeclared. */
|
|
16
|
+
export type LocCeilings = {
|
|
17
|
+
impl: number | null;
|
|
18
|
+
total: number | null;
|
|
19
|
+
};
|
|
20
|
+
/** A computed overage. Only ever constructed when a ceiling is exceeded. */
|
|
21
|
+
export interface LocAdvisory extends LocSplit {
|
|
22
|
+
/** Effective impl ceiling — declared, else HOUSE_IMPL_LOC_GUIDELINE. */
|
|
23
|
+
ceiling: number;
|
|
24
|
+
/** Declared total ceiling (null = undeclared), and where `ceiling` came from. */
|
|
25
|
+
totalCeiling: number | null;
|
|
26
|
+
ceilingSource: "declared" | "house";
|
|
27
|
+
/** Which ceilings are exceeded, in report order. Never empty. */
|
|
28
|
+
exceeded: Array<"impl" | "total">;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* True when a repo-relative path is a TEST file: anything under a `tests/` /
|
|
32
|
+
* `__tests__/` dir at any depth, or a `*.test.*` / `*.spec.*` basename.
|
|
33
|
+
* Backslashes are normalised so a Windows-shaped path classifies identically.
|
|
34
|
+
*/
|
|
35
|
+
export declare function isTestPath(path: string | null | undefined): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Split a unified diff into impl vs test line counts. Binary files contribute
|
|
38
|
+
* nothing — the same convention the Files-changed table uses.
|
|
39
|
+
*/
|
|
40
|
+
export declare function splitDiffLoc(diff: string | null | undefined): LocSplit;
|
|
41
|
+
/**
|
|
42
|
+
* Parse the LOC ceilings a task declared in its acceptance criteria — the
|
|
43
|
+
* `<= N LOC` family named in the spec ("Implementation (non-test) additions
|
|
44
|
+
* <= 250; total diff <= 450 LOC", "LOC budget: implementation <= 250", or a
|
|
45
|
+
* bare "<= 300 LOC"). A criterion must mention LOC / lines / additions before
|
|
46
|
+
* any of its `<= N` clauses count — otherwise "retries <= 3" reads as a budget.
|
|
47
|
+
* Each clause (delimited by `;`, `,`, `.`) binds to a bucket by the qualifier
|
|
48
|
+
* words before its operator; an UNQUALIFIED ceiling fills `impl` first (the
|
|
49
|
+
* house guideline is itself impl-shaped), then `total`. First one per bucket wins.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseLocCeilings(acceptance: readonly string[] | null | undefined): LocCeilings;
|
|
52
|
+
/**
|
|
53
|
+
* Measure a pushed diff against the task's ceilings. Returns `null` — the common
|
|
54
|
+
* case — when nothing is exceeded, so the caller emits nothing at all.
|
|
55
|
+
*/
|
|
56
|
+
export declare function evaluateLocAdvisory(diff: string | null | undefined, acceptance: readonly string[] | null | undefined): LocAdvisory | null;
|
|
57
|
+
/** The `loc_advisory` task_event payload (snake_case, like its peers). */
|
|
58
|
+
export declare function locAdvisoryEventPayload(a: LocAdvisory): Record<string, unknown>;
|
|
59
|
+
/**
|
|
60
|
+
* Render the `## LOC advisory` section — deliberately short: state the split,
|
|
61
|
+
* name the ceiling that is over, say plainly that it is not a blocker.
|
|
62
|
+
*/
|
|
63
|
+
export declare function renderLocAdvisorySection(a: LocAdvisory): string;
|
|
64
|
+
/**
|
|
65
|
+
* Prepend the advisory to a PR body. Any pre-existing `## LOC advisory` section
|
|
66
|
+
* (up to the next `## ` heading) is REMOVED first, so a re-run can never stack
|
|
67
|
+
* two advisories.
|
|
68
|
+
*/
|
|
69
|
+
export declare function prependLocAdvisory(body: string | null | undefined, advisory: LocAdvisory): string;
|
|
70
|
+
//# sourceMappingURL=loc-advisory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loc-advisory.d.ts","sourceRoot":"","sources":["../src/loc-advisory.ts"],"names":[],"mappings":"AAuBA,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,8EAA8E;AAC9E,MAAM,WAAW,QAAQ;IACvB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAExE,4EAA4E;AAC5E,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,UAAU,GAAG,OAAO,CAAC;IACpC,iEAAiE;IACjE,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;CACnC;AAWD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAMnE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAUtE;AAWD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC/C,WAAW,CAuBb;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAC/C,WAAW,GAAG,IAAI,CAepB;AAED,0EAA0E;AAC1E,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAW/E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAkB/D;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,QAAQ,EAAE,WAAW,GACpB,MAAM,CAYR"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LOC-ADVISORY-2B — pre-PR LOC advisory, with an impl-vs-test line split.
|
|
3
|
+
*
|
|
4
|
+
* A PR that blows its LOC ceiling is discovered MID-review today: the reviewer
|
|
5
|
+
* reads the diff, notices the overage, and either rejects or grants a
|
|
6
|
+
* `loc_exception` after the fact (api/_lib/automerge-gates.ts). Both outcomes
|
|
7
|
+
* burn a review cycle on something the runner already knew at push time. So
|
|
8
|
+
* before opening the PR the runner measures the pushed diff, splits it into
|
|
9
|
+
* IMPLEMENTATION and TEST lines and — only when a ceiling is exceeded — emits a
|
|
10
|
+
* structured `loc_advisory` task_event and prepends a short `## LOC advisory`
|
|
11
|
+
* section to the PR body, so the overage is granted CONSCIOUSLY. The split
|
|
12
|
+
* matters because tests are the cheapest lines in a diff: 180 impl + 200 test
|
|
13
|
+
* lines is not the review risk that 380 impl lines is, and a single additions
|
|
14
|
+
* number cannot tell them apart.
|
|
15
|
+
*
|
|
16
|
+
* The advisory NEVER blocks. Everything here is pure and dependency-free; the
|
|
17
|
+
* caller wraps it so a parse error, a missing diff, or a failed event RPC all
|
|
18
|
+
* fall through to opening the PR anyway. impl/tests/total count ADDED lines,
|
|
19
|
+
* matching the server-side LOC gate (which budgets `additions`) and the house
|
|
20
|
+
* "≤300 LOC per commit" guideline; removed lines are context, never budgeted.
|
|
21
|
+
*/
|
|
22
|
+
import { parseDiffFileStats } from "./pr-body.js";
|
|
23
|
+
/** Heading of the generated section. Matched case-insensitively on splice. */
|
|
24
|
+
export const LOC_ADVISORY_HEADING = "## LOC advisory";
|
|
25
|
+
/** `kind` of the structured task_event emitted alongside the section. */
|
|
26
|
+
export const LOC_ADVISORY_EVENT_KIND = "loc_advisory";
|
|
27
|
+
/** House guideline (CLAUDE.md "≤300 LOC per commit"), read as IMPL lines. */
|
|
28
|
+
export const HOUSE_IMPL_LOC_GUIDELINE = 300;
|
|
29
|
+
/**
|
|
30
|
+
* Dirs whose contents are tests. `tests` is the spec'd one, `__tests__` is
|
|
31
|
+
* unambiguous; a bare `test/` is deliberately absent — it collides with real
|
|
32
|
+
* source dirs too often to assume.
|
|
33
|
+
*/
|
|
34
|
+
const TEST_DIR_SEGMENTS = new Set(["tests", "__tests__"]);
|
|
35
|
+
/** `foo.test.ts` / `foo.spec.tsx` — the test marker must precede the extension. */
|
|
36
|
+
const TEST_FILE_RE = /\.(test|spec)\.[^./]+$/i;
|
|
37
|
+
/**
|
|
38
|
+
* True when a repo-relative path is a TEST file: anything under a `tests/` /
|
|
39
|
+
* `__tests__/` dir at any depth, or a `*.test.*` / `*.spec.*` basename.
|
|
40
|
+
* Backslashes are normalised so a Windows-shaped path classifies identically.
|
|
41
|
+
*/
|
|
42
|
+
export function isTestPath(path) {
|
|
43
|
+
const p = (path ?? "").replace(/\\/g, "/").trim();
|
|
44
|
+
const segments = p.split("/").filter((s) => s.length > 0 && s !== ".");
|
|
45
|
+
if (segments.length === 0)
|
|
46
|
+
return false;
|
|
47
|
+
if (TEST_FILE_RE.test(segments[segments.length - 1]))
|
|
48
|
+
return true;
|
|
49
|
+
return segments.slice(0, -1).some((s) => TEST_DIR_SEGMENTS.has(s.toLowerCase()));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Split a unified diff into impl vs test line counts. Binary files contribute
|
|
53
|
+
* nothing — the same convention the Files-changed table uses.
|
|
54
|
+
*/
|
|
55
|
+
export function splitDiffLoc(diff) {
|
|
56
|
+
const split = { impl: 0, tests: 0, total: 0, removed: 0 };
|
|
57
|
+
for (const stat of parseDiffFileStats(diff)) {
|
|
58
|
+
if (stat.binary)
|
|
59
|
+
continue;
|
|
60
|
+
if (isTestPath(stat.path))
|
|
61
|
+
split.tests += stat.added;
|
|
62
|
+
else
|
|
63
|
+
split.impl += stat.added;
|
|
64
|
+
split.removed += stat.removed;
|
|
65
|
+
}
|
|
66
|
+
split.total = split.impl + split.tests;
|
|
67
|
+
return split;
|
|
68
|
+
}
|
|
69
|
+
/** A criterion only carries a ceiling if it talks about LOC/lines/additions. */
|
|
70
|
+
const LOC_CONTEXT_RE = /\b(loc|lines?|additions?)\b/i;
|
|
71
|
+
/** `<= 250`, `≤250`, `< 450` — the ceiling operators we accept. */
|
|
72
|
+
const CEILING_RE = /(<=|≤|<)\s*(\d{1,6})\b/g;
|
|
73
|
+
/** Words binding a ceiling to the implementation bucket. */
|
|
74
|
+
const IMPL_QUALIFIER_RE = /\b(impl|implementation|non-?test|source|code)\b/i;
|
|
75
|
+
/** Words binding a ceiling to the total bucket. */
|
|
76
|
+
const TOTAL_QUALIFIER_RE = /\b(total|overall|combined|whole|entire|diff)\b/i;
|
|
77
|
+
/**
|
|
78
|
+
* Parse the LOC ceilings a task declared in its acceptance criteria — the
|
|
79
|
+
* `<= N LOC` family named in the spec ("Implementation (non-test) additions
|
|
80
|
+
* <= 250; total diff <= 450 LOC", "LOC budget: implementation <= 250", or a
|
|
81
|
+
* bare "<= 300 LOC"). A criterion must mention LOC / lines / additions before
|
|
82
|
+
* any of its `<= N` clauses count — otherwise "retries <= 3" reads as a budget.
|
|
83
|
+
* Each clause (delimited by `;`, `,`, `.`) binds to a bucket by the qualifier
|
|
84
|
+
* words before its operator; an UNQUALIFIED ceiling fills `impl` first (the
|
|
85
|
+
* house guideline is itself impl-shaped), then `total`. First one per bucket wins.
|
|
86
|
+
*/
|
|
87
|
+
export function parseLocCeilings(acceptance) {
|
|
88
|
+
const out = { impl: null, total: null };
|
|
89
|
+
for (const raw of acceptance ?? []) {
|
|
90
|
+
if (typeof raw !== "string" || !LOC_CONTEXT_RE.test(raw))
|
|
91
|
+
continue;
|
|
92
|
+
const text = raw.replace(/\r\n/g, "\n");
|
|
93
|
+
CEILING_RE.lastIndex = 0;
|
|
94
|
+
let m;
|
|
95
|
+
while ((m = CEILING_RE.exec(text)) !== null) {
|
|
96
|
+
const n = Number.parseInt(m[2], 10);
|
|
97
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
98
|
+
continue;
|
|
99
|
+
// The clause is the run of text since the last delimiter — the phrase
|
|
100
|
+
// that qualifies THIS operator ("total diff <=" vs "implementation <=").
|
|
101
|
+
const head = text.slice(0, m.index);
|
|
102
|
+
const clause = head.slice(head.search(/[^;,.\n]*$/));
|
|
103
|
+
if (IMPL_QUALIFIER_RE.test(clause)) {
|
|
104
|
+
if (out.impl === null)
|
|
105
|
+
out.impl = n;
|
|
106
|
+
}
|
|
107
|
+
else if (TOTAL_QUALIFIER_RE.test(clause)) {
|
|
108
|
+
if (out.total === null)
|
|
109
|
+
out.total = n;
|
|
110
|
+
}
|
|
111
|
+
else if (out.impl === null)
|
|
112
|
+
out.impl = n;
|
|
113
|
+
else if (out.total === null)
|
|
114
|
+
out.total = n;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Measure a pushed diff against the task's ceilings. Returns `null` — the common
|
|
121
|
+
* case — when nothing is exceeded, so the caller emits nothing at all.
|
|
122
|
+
*/
|
|
123
|
+
export function evaluateLocAdvisory(diff, acceptance) {
|
|
124
|
+
const split = splitDiffLoc(diff);
|
|
125
|
+
const declared = parseLocCeilings(acceptance);
|
|
126
|
+
const ceiling = declared.impl ?? HOUSE_IMPL_LOC_GUIDELINE;
|
|
127
|
+
const exceeded = [];
|
|
128
|
+
if (split.impl > ceiling)
|
|
129
|
+
exceeded.push("impl");
|
|
130
|
+
if (declared.total !== null && split.total > declared.total)
|
|
131
|
+
exceeded.push("total");
|
|
132
|
+
if (exceeded.length === 0)
|
|
133
|
+
return null;
|
|
134
|
+
return {
|
|
135
|
+
...split,
|
|
136
|
+
ceiling,
|
|
137
|
+
totalCeiling: declared.total,
|
|
138
|
+
ceilingSource: declared.impl !== null ? "declared" : "house",
|
|
139
|
+
exceeded,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** The `loc_advisory` task_event payload (snake_case, like its peers). */
|
|
143
|
+
export function locAdvisoryEventPayload(a) {
|
|
144
|
+
return {
|
|
145
|
+
impl: a.impl,
|
|
146
|
+
tests: a.tests,
|
|
147
|
+
total: a.total,
|
|
148
|
+
ceiling: a.ceiling,
|
|
149
|
+
total_ceiling: a.totalCeiling,
|
|
150
|
+
ceiling_source: a.ceilingSource,
|
|
151
|
+
exceeded: a.exceeded,
|
|
152
|
+
removed: a.removed,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Render the `## LOC advisory` section — deliberately short: state the split,
|
|
157
|
+
* name the ceiling that is over, say plainly that it is not a blocker.
|
|
158
|
+
*/
|
|
159
|
+
export function renderLocAdvisorySection(a) {
|
|
160
|
+
const note = (n, cap, label) => cap === null ? "" : n > cap
|
|
161
|
+
? ` — **exceeds** the ${label} of ${cap} (over by ${n - cap})`
|
|
162
|
+
: ` (${label} ${cap})`;
|
|
163
|
+
const implLabel = a.ceilingSource === "declared" ? "declared ceiling" : "house guideline";
|
|
164
|
+
return [
|
|
165
|
+
LOC_ADVISORY_HEADING,
|
|
166
|
+
"",
|
|
167
|
+
`- Implementation (non-test) additions: **${a.impl}**${note(a.impl, a.ceiling, implLabel)}`,
|
|
168
|
+
`- Test additions: ${a.tests}`,
|
|
169
|
+
`- Total additions: **${a.total}**${note(a.total, a.totalCeiling, "declared total ceiling")}` +
|
|
170
|
+
` (removed: ${a.removed})`,
|
|
171
|
+
"",
|
|
172
|
+
"_(Advisory only — it does not block this PR. Grant a `loc_exception` in the " +
|
|
173
|
+
"review verdict if the diff is cohesive, or ask for a split.)_",
|
|
174
|
+
].join("\n");
|
|
175
|
+
}
|
|
176
|
+
/** Match an existing `## LOC advisory` heading at line start. */
|
|
177
|
+
const HEADING_RE = /^##[ \t]+loc advisory[ \t]*$/im;
|
|
178
|
+
/**
|
|
179
|
+
* Prepend the advisory to a PR body. Any pre-existing `## LOC advisory` section
|
|
180
|
+
* (up to the next `## ` heading) is REMOVED first, so a re-run can never stack
|
|
181
|
+
* two advisories.
|
|
182
|
+
*/
|
|
183
|
+
export function prependLocAdvisory(body, advisory) {
|
|
184
|
+
let text = (body ?? "").replace(/\r\n/g, "\n");
|
|
185
|
+
const match = HEADING_RE.exec(text);
|
|
186
|
+
if (match) {
|
|
187
|
+
const after = match.index + match[0].length;
|
|
188
|
+
const next = /^##[ \t]+\S/m.exec(text.slice(after));
|
|
189
|
+
const end = next != null ? after + next.index : text.length;
|
|
190
|
+
text = `${text.slice(0, match.index)}\n${text.slice(end)}`;
|
|
191
|
+
}
|
|
192
|
+
const tail = text.trim();
|
|
193
|
+
const section = renderLocAdvisorySection(advisory);
|
|
194
|
+
return tail.length > 0 ? `${section}\n\n${tail}\n` : `${section}\n`;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=loc-advisory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loc-advisory.js","sourceRoot":"","sources":["../src/loc-advisory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claim-time lock POLICY — runner-side copy.
|
|
3
|
+
*
|
|
4
|
+
* The runner is a standalone published package and MUST NOT import from
|
|
5
|
+
* api/_lib (see capacity-plugin.ts / cost-pricing.ts for the same rule), so this
|
|
6
|
+
* DUPLICATES the pure policy in api/_lib/claim-lock-policy.ts. Keep the two in
|
|
7
|
+
* sync — that api module is the canonical spec, and migration
|
|
8
|
+
* 0353_acc_claim_lock_file_granular.sql mirrors `declaredLockPaths` in SQL
|
|
9
|
+
* (acc._declared_lock_paths) so the DB overlap key is file-granular too.
|
|
10
|
+
*
|
|
11
|
+
* The rule (the bug this fixes): claim-time locking is FILE-granular. A broad
|
|
12
|
+
* directory glob (`api/_lib/**`, `tests/*`) is AUTHORIZATION scope, not lock
|
|
13
|
+
* scope — it acquires no directory-wide lock, so two tasks that share a parent
|
|
14
|
+
* directory but touch disjoint files never serialize. A concrete lock only
|
|
15
|
+
* exists once concrete files are known through the task's declared `allowed[]`
|
|
16
|
+
* or its touched-file reporting.
|
|
17
|
+
*/
|
|
18
|
+
/** At most three fast claim attempts against a live lock holder before yielding. */
|
|
19
|
+
export declare const CLAIM_LOCK_MAX_FAST_ATTEMPTS = 3;
|
|
20
|
+
/** Spacing between the fast attempts. */
|
|
21
|
+
export declare const CLAIM_LOCK_FAST_RETRY_MS = 60000;
|
|
22
|
+
/** Bounded back-off once the fast attempts are spent (AC3). */
|
|
23
|
+
export declare const CLAIM_LOCK_YIELD_MS: number;
|
|
24
|
+
/** Per-task claim-loss state, persisted across runTask invocations. */
|
|
25
|
+
export interface ClaimLockLossState {
|
|
26
|
+
attempts: number;
|
|
27
|
+
eventRecorded: boolean;
|
|
28
|
+
firstConflictAtMs: number;
|
|
29
|
+
}
|
|
30
|
+
export interface ClaimLockLossDecision {
|
|
31
|
+
attempts: number;
|
|
32
|
+
eventRecorded: boolean;
|
|
33
|
+
firstConflictAtMs: number;
|
|
34
|
+
nextAttemptAtMs: number;
|
|
35
|
+
/** Non-null once the fast attempts are spent: do not re-attempt before this. */
|
|
36
|
+
yieldUntilMs: number | null;
|
|
37
|
+
/** The single conflict event to record, or null when it was already recorded. */
|
|
38
|
+
event: {
|
|
39
|
+
phase: "claim_locks";
|
|
40
|
+
conflicts: string[];
|
|
41
|
+
message: string;
|
|
42
|
+
} | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The concrete file paths a task actually locks at claim time. Broad directory
|
|
46
|
+
* globs are dropped (authorization scope, not lock scope); concrete files from
|
|
47
|
+
* `allowed[]` and any reported `touched` files are kept, de-duplicated, sorted.
|
|
48
|
+
*/
|
|
49
|
+
export declare function declaredLockPaths(allowed: readonly string[] | null | undefined, touched?: readonly string[]): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Advance the claim-loss retry state after a file-lock conflict. Returns the
|
|
52
|
+
* back-off decision: fast retries up to CLAIM_LOCK_MAX_FAST_ATTEMPTS, then a
|
|
53
|
+
* bounded yield (AC3), plus the ONE conflict event to record — null after the
|
|
54
|
+
* first, so the caller emits a single event per contention episode (AC4).
|
|
55
|
+
*/
|
|
56
|
+
export declare function planClaimLockLoss(previous: ClaimLockLossState | null | undefined, conflicts: readonly string[], nowMs: number): ClaimLockLossDecision;
|
|
57
|
+
/**
|
|
58
|
+
* Clear the claim-loss state after a SUCCESSFUL claim so the next contention
|
|
59
|
+
* episode starts over — attempts back to 1 and a fresh conflict event emitted.
|
|
60
|
+
* `planClaimLockLoss` only ever advances state (attempts saturate at the cap,
|
|
61
|
+
* `eventRecorded` stays true), so without an explicit reset a task that once
|
|
62
|
+
* lost a claim could never resume fast attempts or re-open an event for the
|
|
63
|
+
* life of the state. Callers pass the result (null) back as `previous` on the
|
|
64
|
+
* next episode; passing null directly is equivalent.
|
|
65
|
+
*/
|
|
66
|
+
export declare function resetClaimLockLoss(): ClaimLockLossState | null;
|
|
67
|
+
//# sourceMappingURL=claim-lock-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-lock-policy.d.ts","sourceRoot":"","sources":["../../src/locks/claim-lock-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,oFAAoF;AACpF,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,yCAAyC;AACzC,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,QAAa,CAAC;AAE9C,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iFAAiF;IACjF,KAAK,EACD;QACE,KAAK,EAAE,aAAa,CAAC;QACrB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,GACD,IAAI,CAAC;CACV;AAyDD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAC7C,OAAO,GAAE,SAAS,MAAM,EAAO,GAC9B,MAAM,EAAE,CAOV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,EAC/C,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,KAAK,EAAE,MAAM,GACZ,qBAAqB,CAsBvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,kBAAkB,GAAG,IAAI,CAE9D"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claim-time lock POLICY — runner-side copy.
|
|
3
|
+
*
|
|
4
|
+
* The runner is a standalone published package and MUST NOT import from
|
|
5
|
+
* api/_lib (see capacity-plugin.ts / cost-pricing.ts for the same rule), so this
|
|
6
|
+
* DUPLICATES the pure policy in api/_lib/claim-lock-policy.ts. Keep the two in
|
|
7
|
+
* sync — that api module is the canonical spec, and migration
|
|
8
|
+
* 0353_acc_claim_lock_file_granular.sql mirrors `declaredLockPaths` in SQL
|
|
9
|
+
* (acc._declared_lock_paths) so the DB overlap key is file-granular too.
|
|
10
|
+
*
|
|
11
|
+
* The rule (the bug this fixes): claim-time locking is FILE-granular. A broad
|
|
12
|
+
* directory glob (`api/_lib/**`, `tests/*`) is AUTHORIZATION scope, not lock
|
|
13
|
+
* scope — it acquires no directory-wide lock, so two tasks that share a parent
|
|
14
|
+
* directory but touch disjoint files never serialize. A concrete lock only
|
|
15
|
+
* exists once concrete files are known through the task's declared `allowed[]`
|
|
16
|
+
* or its touched-file reporting.
|
|
17
|
+
*/
|
|
18
|
+
/** At most three fast claim attempts against a live lock holder before yielding. */
|
|
19
|
+
export const CLAIM_LOCK_MAX_FAST_ATTEMPTS = 3;
|
|
20
|
+
/** Spacing between the fast attempts. */
|
|
21
|
+
export const CLAIM_LOCK_FAST_RETRY_MS = 60_000;
|
|
22
|
+
/** Bounded back-off once the fast attempts are spent (AC3). */
|
|
23
|
+
export const CLAIM_LOCK_YIELD_MS = 5 * 60_000;
|
|
24
|
+
// ── shared file-lock scope helpers ──────────────────────────────────────────
|
|
25
|
+
// The block from EXTENSIONLESS_LOCK_FILENAMES through declaredLockPaths is kept
|
|
26
|
+
// BYTE-IDENTICAL with api/_lib/claim-lock-policy.ts (the canonical spec) and
|
|
27
|
+
// acc._declared_lock_paths in the migration. tests/unit/claim-lock-policy.test.ts
|
|
28
|
+
// runs BOTH copies over one shared input table and asserts identical output, so
|
|
29
|
+
// the three normalizers can never silently diverge into two different lock keys.
|
|
30
|
+
/**
|
|
31
|
+
* Canonical extensionless filenames that ARE concrete file locks despite having
|
|
32
|
+
* no dotted extension. Without this set they are indistinguishable from a bare
|
|
33
|
+
* directory and would be silently dropped from lock scope, so two tasks editing
|
|
34
|
+
* the same one would both claim. Kept small and closed — only conventional,
|
|
35
|
+
* unambiguous filenames.
|
|
36
|
+
*/
|
|
37
|
+
const EXTENSIONLESS_LOCK_FILENAMES = new Set([
|
|
38
|
+
"Dockerfile",
|
|
39
|
+
"Makefile",
|
|
40
|
+
"Rakefile",
|
|
41
|
+
"Gemfile",
|
|
42
|
+
"Procfile",
|
|
43
|
+
"Brewfile",
|
|
44
|
+
"Vagrantfile",
|
|
45
|
+
"Jenkinsfile",
|
|
46
|
+
"Caddyfile",
|
|
47
|
+
"LICENSE",
|
|
48
|
+
"NOTICE",
|
|
49
|
+
"CODEOWNERS",
|
|
50
|
+
]);
|
|
51
|
+
/** The wildcard-free leading token of a raw allowed[] entry, path-normalized. */
|
|
52
|
+
function normalizePath(raw) {
|
|
53
|
+
const first = (raw ?? "").trim().split(/\s+/)[0] ?? "";
|
|
54
|
+
return first
|
|
55
|
+
.replace(/^\.\//, "")
|
|
56
|
+
.replace(/^\/+/, "")
|
|
57
|
+
.replace(/\/{2,}/g, "/")
|
|
58
|
+
.replace(/\/+$/, "");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* True for a concrete file path — one that names a single file, not a directory
|
|
62
|
+
* or wildcard scope. A basename counts as a file when it carries a dotted
|
|
63
|
+
* extension, is a dotfile (`.env`, `.gitignore`), or is a canonical
|
|
64
|
+
* extensionless filename (Dockerfile, Makefile, …). A bare directory
|
|
65
|
+
* (`api/_lib`) has none of those and is authorization scope, not a lock. The
|
|
66
|
+
* `.` and `..` path segments are never files.
|
|
67
|
+
*/
|
|
68
|
+
function isConcreteFilePath(path) {
|
|
69
|
+
if (!path || path.includes("*") || path.endsWith("/"))
|
|
70
|
+
return false;
|
|
71
|
+
const base = path.split("/").pop() ?? "";
|
|
72
|
+
if (base === "" || base === "." || base === "..")
|
|
73
|
+
return false;
|
|
74
|
+
if (EXTENSIONLESS_LOCK_FILENAMES.has(base))
|
|
75
|
+
return true;
|
|
76
|
+
return base.includes(".");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The concrete file paths a task actually locks at claim time. Broad directory
|
|
80
|
+
* globs are dropped (authorization scope, not lock scope); concrete files from
|
|
81
|
+
* `allowed[]` and any reported `touched` files are kept, de-duplicated, sorted.
|
|
82
|
+
*/
|
|
83
|
+
export function declaredLockPaths(allowed, touched = []) {
|
|
84
|
+
const paths = new Set();
|
|
85
|
+
for (const raw of [...(allowed ?? []), ...touched]) {
|
|
86
|
+
const path = normalizePath(raw);
|
|
87
|
+
if (isConcreteFilePath(path))
|
|
88
|
+
paths.add(path);
|
|
89
|
+
}
|
|
90
|
+
return [...paths].sort();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Advance the claim-loss retry state after a file-lock conflict. Returns the
|
|
94
|
+
* back-off decision: fast retries up to CLAIM_LOCK_MAX_FAST_ATTEMPTS, then a
|
|
95
|
+
* bounded yield (AC3), plus the ONE conflict event to record — null after the
|
|
96
|
+
* first, so the caller emits a single event per contention episode (AC4).
|
|
97
|
+
*/
|
|
98
|
+
export function planClaimLockLoss(previous, conflicts, nowMs) {
|
|
99
|
+
const attempts = Math.min((previous?.attempts ?? 0) + 1, CLAIM_LOCK_MAX_FAST_ATTEMPTS);
|
|
100
|
+
const alreadyRecorded = previous?.eventRecorded === true;
|
|
101
|
+
const firstConflictAtMs = previous?.firstConflictAtMs ?? nowMs;
|
|
102
|
+
const boundedYield = attempts >= CLAIM_LOCK_MAX_FAST_ATTEMPTS;
|
|
103
|
+
const uniqueConflicts = [...new Set(conflicts.filter(Boolean))].sort();
|
|
104
|
+
const nextAttemptAtMs = nowMs + (boundedYield ? CLAIM_LOCK_YIELD_MS : CLAIM_LOCK_FAST_RETRY_MS);
|
|
105
|
+
return {
|
|
106
|
+
attempts,
|
|
107
|
+
eventRecorded: true,
|
|
108
|
+
firstConflictAtMs,
|
|
109
|
+
nextAttemptAtMs,
|
|
110
|
+
yieldUntilMs: boundedYield ? nextAttemptAtMs : null,
|
|
111
|
+
event: alreadyRecorded
|
|
112
|
+
? null
|
|
113
|
+
: {
|
|
114
|
+
phase: "claim_locks",
|
|
115
|
+
conflicts: uniqueConflicts,
|
|
116
|
+
message: `file-lock conflict with: ${uniqueConflicts.join(", ") || "(unknown)"}`,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Clear the claim-loss state after a SUCCESSFUL claim so the next contention
|
|
122
|
+
* episode starts over — attempts back to 1 and a fresh conflict event emitted.
|
|
123
|
+
* `planClaimLockLoss` only ever advances state (attempts saturate at the cap,
|
|
124
|
+
* `eventRecorded` stays true), so without an explicit reset a task that once
|
|
125
|
+
* lost a claim could never resume fast attempts or re-open an event for the
|
|
126
|
+
* life of the state. Callers pass the result (null) back as `previous` on the
|
|
127
|
+
* next episode; passing null directly is equivalent.
|
|
128
|
+
*/
|
|
129
|
+
export function resetClaimLockLoss() {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=claim-lock-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-lock-policy.js","sourceRoot":"","sources":["../../src/locks/claim-lock-policy.ts"],"names":[],"mappings":"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"}
|
package/dist/login.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type ConcurrencySource, type RunnerConcurrency } from "./config.js";
|
|
1
|
+
import { type ConcurrencySource, type RunnerConcurrency, type RunnerConfig } from "./config.js";
|
|
2
2
|
import type { RunnerCaps } from "./types.js";
|
|
3
|
+
import { type RunnerBuildCaps } from "./build-fingerprint.js";
|
|
4
|
+
import { type CredentialIdentity } from "./credential-identity.js";
|
|
3
5
|
export declare const RUNNER_CAPS: RunnerCaps;
|
|
4
6
|
/**
|
|
5
7
|
* Repo-scoped routing — build the register_runner `p_caps` payload with
|
|
@@ -33,13 +35,60 @@ export declare const RUNNER_CAPS: RunnerCaps;
|
|
|
33
35
|
* advertised number can never drift from the number the runner actually runs.
|
|
34
36
|
* Both keys are additive to the frozen caps shape — a pure superset.
|
|
35
37
|
*/
|
|
36
|
-
export declare function runnerCapsWithRepos(repos: readonly string[] | undefined, engines?: readonly string[] | undefined, conc?: RunnerConcurrency, source?: ConcurrencySource): RunnerCaps & {
|
|
38
|
+
export declare function runnerCapsWithRepos(repos: readonly string[] | undefined, engines?: readonly string[] | undefined, conc?: RunnerConcurrency, source?: ConcurrencySource, processCapabilities?: readonly string[], identity?: CredentialIdentity, build?: RunnerBuildCaps): RunnerCaps & {
|
|
37
39
|
repos: string[];
|
|
38
40
|
engines: string[];
|
|
41
|
+
process_capabilities: string[];
|
|
39
42
|
concurrency: number;
|
|
40
43
|
reserved_review_slots: number;
|
|
41
44
|
concurrency_source: ConcurrencySource;
|
|
45
|
+
account_email: string | null;
|
|
46
|
+
account_org: string | null;
|
|
47
|
+
credential_source: CredentialIdentity["credential_source"];
|
|
48
|
+
build?: RunnerBuildCaps;
|
|
42
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* CAPS-ENGINES-STALE-KEYCHAIN-1 (AC10): the SINGLE `register_runner` `p_caps`
|
|
52
|
+
* builder shared by the `login` CLI and the watch-boot register, so the two
|
|
53
|
+
* cannot drift for the same environment. Merged with the upstream caps shape:
|
|
54
|
+
* it also folds liveProcessCapabilities(cfg), the resolved credential identity
|
|
55
|
+
* (capacity-attribution), and the build fingerprint — the caller resolves the
|
|
56
|
+
* async `identity`/`build` once and passes them so both paths publish an
|
|
57
|
+
* identical rich caps payload.
|
|
58
|
+
*/
|
|
59
|
+
export declare function registerRunnerCaps(cfg: Pick<RunnerConfig, "repos" | "capabilities">, engines: readonly string[], conc: RunnerConcurrency, identity: CredentialIdentity, build: RunnerBuildCaps | undefined): ReturnType<typeof runnerCapsWithRepos>;
|
|
60
|
+
/**
|
|
61
|
+
* REGISTER-CAPS-PRESERVE-1 — the `p_capabilities` array every `register_runner`
|
|
62
|
+
* call must send. Neither call site passed the argument at all, so PostgREST
|
|
63
|
+
* omitted it, the RPC took its `text[] default '{}'` and the 0114/0153 body
|
|
64
|
+
* wrote that empty array straight over acc.runners.capabilities: a runner
|
|
65
|
+
* dispatchable for seven tags came back matching only tasks with an EMPTY
|
|
66
|
+
* required_capabilities — nothing the board queues. Migration 0349 makes the
|
|
67
|
+
* server refuse to shrink; this stops the client asking, which is what keeps
|
|
68
|
+
* 0349's activity-event alarm quiet in steady state. Same set that
|
|
69
|
+
* `set_runner_capabilities` publishes (ACC_RUNNER_CAPABILITIES > config.json >
|
|
70
|
+
* profile > []), so register and refresh can never disagree. Empty stays empty
|
|
71
|
+
* on the wire: 0349 reads it as "preserve", and on a FRESH row it is the 0114
|
|
72
|
+
* backward-compat default.
|
|
73
|
+
*/
|
|
74
|
+
export declare function advertisedCapabilities(cfg: Pick<RunnerConfig, "capabilities">): string[];
|
|
75
|
+
/**
|
|
76
|
+
* M5 (CODEX-DISPATCH-WIRE-1): the runner's LIVE process capabilities, published
|
|
77
|
+
* as `caps.process_capabilities` for the capability-divergence report (#2131).
|
|
78
|
+
* Advertised capabilities are static config (`ACC_RUNNER_CAPABILITIES`); the
|
|
79
|
+
* live set drops any advertised tag that names a batch engine THIS runner's
|
|
80
|
+
* registry does not currently register — e.g. a config advertising `codex`
|
|
81
|
+
* while `ACC_ENGINE_CODEX_ENABLED` is off. Publishing the config value verbatim
|
|
82
|
+
* (the pre-M5 behaviour) made `advertised == process` always, so `stale_config`
|
|
83
|
+
* could never fire; deriving it from `engineIds()` is what lets the fleet report
|
|
84
|
+
* surface a disabled/unregistered Codex runner whose advertised caps are stale.
|
|
85
|
+
* Non-engine tags (e.g. `code`, `migration`, `review`) pass through untouched.
|
|
86
|
+
*/
|
|
87
|
+
export declare function liveProcessCapabilities(cfg: Pick<RunnerConfig, "capabilities">, registeredEngineIds?: readonly string[]): string[];
|
|
88
|
+
/** The `machine` string the server dedups identity on. NAMED-INSTANCES-1
|
|
89
|
+
* appends `#<name>` so each instance resolves its own stable runner id;
|
|
90
|
+
* unnamed = the v0.44.0 string byte-for-byte. Every caller shares this fn so
|
|
91
|
+
* the suffix can never reach some payloads and not others. */
|
|
43
92
|
export declare function machineIdentity(): string;
|
|
44
93
|
export declare function detectInstalledModels(): Promise<string[]>;
|
|
45
94
|
/**
|
|
@@ -91,6 +140,18 @@ export interface LoginOptions extends BrowserOpenContext {
|
|
|
91
140
|
timeoutSeconds?: number;
|
|
92
141
|
/** Injectable `open` (tests). Defaults to the real `open` package. */
|
|
93
142
|
openBrowser?: (url: string) => Promise<unknown>;
|
|
143
|
+
/**
|
|
144
|
+
* AC10/AC11: engine-detection seam (mirrors WatchOptions.detectEngines).
|
|
145
|
+
* Defaults to the real detectCapableEngines; a test injects the same probe
|
|
146
|
+
* into login and watch to compare the two real caps paths without a mock.
|
|
147
|
+
*/
|
|
148
|
+
detectEngines?: () => Promise<string[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Injectable default-engine executable preflight. Production resolves `claude`
|
|
151
|
+
* before registering so a machine that cannot run the default engine fails the
|
|
152
|
+
* login loudly instead of registering a runner that can only fail at dispatch.
|
|
153
|
+
*/
|
|
154
|
+
claudePreflight?: () => void;
|
|
94
155
|
}
|
|
95
156
|
export declare function loginCommand(options?: LoginOptions): Promise<void>;
|
|
96
157
|
//# sourceMappingURL=login.d.ts.map
|
package/dist/login.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAaA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"}
|