@telora/daemon 0.20.54 → 0.20.60
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/build-info.json +6 -3
- package/dist/cli/session-state.d.ts +9 -0
- package/dist/cli/session-state.d.ts.map +1 -1
- package/dist/cli/session-state.js.map +1 -1
- package/dist/completion/review-exit-escalations.d.ts +85 -0
- package/dist/completion/review-exit-escalations.d.ts.map +1 -0
- package/dist/completion/review-exit-escalations.js +203 -0
- package/dist/completion/review-exit-escalations.js.map +1 -0
- package/dist/completion/review-exit-phase.d.ts.map +1 -1
- package/dist/completion/review-exit-phase.js +43 -135
- package/dist/completion/review-exit-phase.js.map +1 -1
- package/dist/delivery-advance-block.d.ts.map +1 -1
- package/dist/delivery-advance-block.js +8 -1
- package/dist/delivery-advance-block.js.map +1 -1
- package/dist/external-hold.d.ts +104 -0
- package/dist/external-hold.d.ts.map +1 -0
- package/dist/external-hold.js +149 -0
- package/dist/external-hold.js.map +1 -0
- package/dist/listener-auto-advance.d.ts.map +1 -1
- package/dist/listener-auto-advance.js +12 -0
- package/dist/listener-auto-advance.js.map +1 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +56 -11
- package/dist/listener.js.map +1 -1
- package/dist/prompt-sections/execution-sections.d.ts.map +1 -1
- package/dist/prompt-sections/execution-sections.js +25 -23
- package/dist/prompt-sections/execution-sections.js.map +1 -1
- package/dist/queries/deliveries.d.ts +62 -0
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +1 -0
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/holds.d.ts +177 -0
- package/dist/queries/holds.d.ts.map +1 -0
- package/dist/queries/holds.js +232 -0
- package/dist/queries/holds.js.map +1 -0
- package/dist/queries/issues.d.ts +3 -99
- package/dist/queries/issues.d.ts.map +1 -1
- package/dist/queries/issues.js +4 -137
- package/dist/queries/issues.js.map +1 -1
- package/dist/queries/schemas.d.ts +2 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +5 -0
- package/dist/queries/schemas.js.map +1 -1
- package/dist/resolver-dispatch.d.ts +108 -0
- package/dist/resolver-dispatch.d.ts.map +1 -0
- package/dist/resolver-dispatch.js +83 -0
- package/dist/resolver-dispatch.js.map +1 -0
- package/dist/resolver-reach.d.ts +192 -0
- package/dist/resolver-reach.d.ts.map +1 -0
- package/dist/resolver-reach.js +168 -0
- package/dist/resolver-reach.js.map +1 -0
- package/dist/resolvers/git-diff-against-base.d.ts.map +1 -1
- package/dist/resolvers/git-diff-against-base.js +8 -2
- package/dist/resolvers/git-diff-against-base.js.map +1 -1
- package/dist/resolvers/index.d.ts +1 -1
- package/dist/resolvers/index.d.ts.map +1 -1
- package/dist/resolvers/index.js +1 -1
- package/dist/resolvers/index.js.map +1 -1
- package/dist/resolvers/shared/git-diff.d.ts +47 -0
- package/dist/resolvers/shared/git-diff.d.ts.map +1 -1
- package/dist/resolvers/shared/git-diff.js +103 -15
- package/dist/resolvers/shared/git-diff.js.map +1 -1
- package/dist/spawn/review-role-fallback.d.ts +37 -3
- package/dist/spawn/review-role-fallback.d.ts.map +1 -1
- package/dist/spawn/review-role-fallback.js +38 -3
- package/dist/spawn/review-role-fallback.js.map +1 -1
- package/dist/stall-detectors.d.ts +33 -4
- package/dist/stall-detectors.d.ts.map +1 -1
- package/dist/stall-detectors.js +64 -5
- package/dist/stall-detectors.js.map +1 -1
- package/dist/verification-engine.d.ts +10 -0
- package/dist/verification-engine.d.ts.map +1 -1
- package/dist/verification-engine.js +142 -96
- package/dist/verification-engine.js.map +1 -1
- package/dist/verification-feedback.d.ts +44 -1
- package/dist/verification-feedback.d.ts.map +1 -1
- package/dist/verification-feedback.js +130 -1
- package/dist/verification-feedback.js.map +1 -1
- package/dist/verify-reconciliation.d.ts +25 -1
- package/dist/verify-reconciliation.d.ts.map +1 -1
- package/dist/verify-reconciliation.js +64 -2
- package/dist/verify-reconciliation.js.map +1 -1
- package/dist/verify-restatement.d.ts +22 -4
- package/dist/verify-restatement.d.ts.map +1 -1
- package/dist/verify-restatement.js +18 -1
- package/dist/verify-restatement.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver reach is BOUNDED up front, and its out-of-worktree actions are ON
|
|
3
|
+
* THE RECORD. The negative branch of the resolver-dispatch seam
|
|
4
|
+
* (resolver-dispatch.ts).
|
|
5
|
+
*
|
|
6
|
+
* The resolver only closes anything if it holds reach the sandboxed worktree
|
|
7
|
+
* agent lacks (spawn-sandbox.ts documents that asymmetry: a git worktree bounds
|
|
8
|
+
* the branch but NOT the OS -- credentials to other machines, sibling repos, the
|
|
9
|
+
* operator's home are all reachable). That same reach, granted without a
|
|
10
|
+
* declared bound, is unattended credentialed action on hosts with nothing
|
|
11
|
+
* reviewing what it did: a resolver's host actions produce no diff and pass no
|
|
12
|
+
* review gate, unlike code changes. Today's paste-into-Claude-Code workaround at
|
|
13
|
+
* least happens with a human watching; removing the human removes that too.
|
|
14
|
+
*
|
|
15
|
+
* Two invariants, both provable without a live host:
|
|
16
|
+
*
|
|
17
|
+
* 1. REACH IS DECLARED IN ADVANCE, PER BLOCKAGE CLASS, and FAIL-CLOSED. A
|
|
18
|
+
* resolver acts only within a bound declared before it runs ("this class may
|
|
19
|
+
* restart a container on host H"); an action outside that bound is REFUSED,
|
|
20
|
+
* not permitted-and-logged. An unrecognized or undeclared blockage class
|
|
21
|
+
* yields NO reach -- never a default to broad reach. This follows the
|
|
22
|
+
* spawn-sandbox.ts shape: explicit, fail-closed, declared rather than
|
|
23
|
+
* ambient. Reach is a property of the declared grant, never inferred from
|
|
24
|
+
* what an attempt happened to touch (a reach granted by outcome is not a
|
|
25
|
+
* bound).
|
|
26
|
+
*
|
|
27
|
+
* 2. EVERY OUT-OF-WORKTREE ACTION IS RECORDED, durably and credential-free, on
|
|
28
|
+
* the success, failure, AND throwing paths -- a failed unattended action is
|
|
29
|
+
* exactly the one that must not vanish. The record identifies the blockage,
|
|
30
|
+
* the action attempted, and its outcome. The sink is injectable (tests
|
|
31
|
+
* capture records without a live host); the default writes a structured line
|
|
32
|
+
* to the canonical daemon log, which is durable and human-reviewable.
|
|
33
|
+
*
|
|
34
|
+
* This module is NOT a second resolver and does not re-open the dispatch design.
|
|
35
|
+
* It supplies the reach `bound` that feeds `BlockageResolver.reach` and wraps a
|
|
36
|
+
* single host action so it is authorized against the bound and recorded --
|
|
37
|
+
* composing with dispatchBlockage, not rewriting it.
|
|
38
|
+
*
|
|
39
|
+
* @module resolver-reach
|
|
40
|
+
*/
|
|
41
|
+
import { createLogger } from './log.js';
|
|
42
|
+
const log = createLogger({ module: 'resolver-reach' });
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a blockage class to its declared reach bound. FAIL-CLOSED: an
|
|
45
|
+
* unrecognized/undeclared class -- or a declared grant that permits no kind or
|
|
46
|
+
* no target -- yields `reach: false` and `grant: null`. There is no path that
|
|
47
|
+
* defaults an unknown class to broad reach.
|
|
48
|
+
*/
|
|
49
|
+
export function resolveReachBound(blockageClass, registry) {
|
|
50
|
+
const grant = registry.get(blockageClass) ?? null;
|
|
51
|
+
const reach = grant !== null &&
|
|
52
|
+
grant.allowedActionKinds.length > 0 &&
|
|
53
|
+
grant.allowedTargets.length > 0;
|
|
54
|
+
return { blockageClass, reach, grant: reach ? grant : null };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Authorize a single action against a resolved bound. REFUSES (does not
|
|
58
|
+
* permit-and-log) when the bound has no reach, the action serves a different
|
|
59
|
+
* class than the bound, or the action's kind/target is outside the declared
|
|
60
|
+
* grant. A refusal means the action must NOT run.
|
|
61
|
+
*/
|
|
62
|
+
export function authorizeAction(bound, action) {
|
|
63
|
+
if (!bound.reach || bound.grant === null) {
|
|
64
|
+
return { authorized: false, reason: `no declared reach for blockage class "${action.blockageClass}"` };
|
|
65
|
+
}
|
|
66
|
+
if (action.blockageClass !== bound.blockageClass) {
|
|
67
|
+
return {
|
|
68
|
+
authorized: false,
|
|
69
|
+
reason: `action serves class "${action.blockageClass}" but bound is for "${bound.blockageClass}"`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (!bound.grant.allowedActionKinds.includes(action.kind)) {
|
|
73
|
+
return { authorized: false, reason: `action kind "${action.kind}" is outside the declared bound for "${bound.blockageClass}"` };
|
|
74
|
+
}
|
|
75
|
+
if (!bound.grant.allowedTargets.includes(action.target)) {
|
|
76
|
+
return { authorized: false, reason: `target "${action.target}" is outside the declared bound for "${bound.blockageClass}"` };
|
|
77
|
+
}
|
|
78
|
+
return { authorized: true };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The default production recorder: a structured line in the canonical daemon
|
|
82
|
+
* log (~/.telora/daemon.log) -- durable, rotated, and human-reviewable after
|
|
83
|
+
* the fact, which is precisely what a diff-less host action otherwise lacks.
|
|
84
|
+
* The record's `detail` is already redacted before it arrives here, so this
|
|
85
|
+
* sink cannot leak credentials.
|
|
86
|
+
*/
|
|
87
|
+
export const logResolverAction = (record) => {
|
|
88
|
+
log.info('resolver action recorded', {
|
|
89
|
+
blockageClass: record.blockageClass,
|
|
90
|
+
actionKind: record.action.kind,
|
|
91
|
+
target: record.action.target,
|
|
92
|
+
summary: record.action.summary,
|
|
93
|
+
outcome: record.outcome,
|
|
94
|
+
...(record.detail !== undefined ? { detail: record.detail } : {}),
|
|
95
|
+
recordedAt: record.recordedAt,
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Redact credential-shaped material from free-text before it enters a record.
|
|
100
|
+
* A record a human reviews must never itself become a credential leak, so this
|
|
101
|
+
* scrubs bearer/authorization values, `key=value` pairs whose key names a
|
|
102
|
+
* secret, and long opaque token blobs. Conservative and lossy on purpose --
|
|
103
|
+
* over-redaction is safe; under-redaction is the failure.
|
|
104
|
+
*/
|
|
105
|
+
export function redactResolverDetail(text) {
|
|
106
|
+
return text
|
|
107
|
+
// Authorization: Bearer <token> / bearer <token>
|
|
108
|
+
.replace(/\b(bearer)\s+[A-Za-z0-9._\-+/=]+/gi, '$1 [REDACTED]')
|
|
109
|
+
// key=value / key: value where the key names a secret
|
|
110
|
+
.replace(/\b(authorization|api[_-]?key|secret|password|passwd|token|access[_-]?key|private[_-]?key|client[_-]?secret)\b(\s*[:=]\s*)("?)[^\s"']+\3/gi, '$1$2[REDACTED]')
|
|
111
|
+
// Long opaque token blobs (>=24 chars of token alphabet) not otherwise caught.
|
|
112
|
+
.replace(/\b[A-Za-z0-9._\-+/=]{24,}\b/g, '[REDACTED]');
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Run one out-of-worktree resolver action within its declared bound, recording
|
|
116
|
+
* every path.
|
|
117
|
+
*
|
|
118
|
+
* Guarantees, all provable without a live host:
|
|
119
|
+
* - The action is AUTHORIZED against the pre-declared bound FIRST. An action
|
|
120
|
+
* outside the bound (or under an undeclared class) is REFUSED -- `execute` is
|
|
121
|
+
* never called -- and the refusal is recorded.
|
|
122
|
+
* - On execution, `success` or `failure` is recorded from the result.
|
|
123
|
+
* - If `execute` THROWS, a `failure` record is written (via catch) BEFORE the
|
|
124
|
+
* error propagates -- the failed unattended action never vanishes.
|
|
125
|
+
* - The recorded `detail` is always redacted, so no credential material enters
|
|
126
|
+
* the record regardless of the sink.
|
|
127
|
+
*/
|
|
128
|
+
export async function runReachBoundedAction(deps, action, execute) {
|
|
129
|
+
const record = deps.record ?? logResolverAction;
|
|
130
|
+
const redact = deps.redact ?? redactResolverDetail;
|
|
131
|
+
const clock = deps.clock ?? (() => new Date().toISOString());
|
|
132
|
+
const write = async (outcome, detail) => {
|
|
133
|
+
const entry = {
|
|
134
|
+
blockageClass: action.blockageClass,
|
|
135
|
+
action: { kind: action.kind, target: action.target, summary: action.summary },
|
|
136
|
+
outcome,
|
|
137
|
+
recordedAt: clock(),
|
|
138
|
+
};
|
|
139
|
+
if (detail !== undefined)
|
|
140
|
+
entry.detail = redact(detail);
|
|
141
|
+
await record(entry);
|
|
142
|
+
};
|
|
143
|
+
const bound = resolveReachBound(action.blockageClass, deps.registry);
|
|
144
|
+
const decision = authorizeAction(bound, action);
|
|
145
|
+
if (!decision.authorized) {
|
|
146
|
+
// Refused: the action is NOT executed. Record the refusal for the audit trail.
|
|
147
|
+
await write('refused', decision.reason);
|
|
148
|
+
return { outcome: 'refused', reason: decision.reason };
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const result = await execute();
|
|
152
|
+
if (result.ok) {
|
|
153
|
+
await write('success', result.detail);
|
|
154
|
+
return { outcome: 'success' };
|
|
155
|
+
}
|
|
156
|
+
await write('failure', result.detail);
|
|
157
|
+
return result.detail !== undefined
|
|
158
|
+
? { outcome: 'failure', detail: redact(result.detail) }
|
|
159
|
+
: { outcome: 'failure' };
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
// A throwing action is exactly the one whose record must not vanish.
|
|
163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
164
|
+
await write('failure', message);
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=resolver-reach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver-reach.js","sourceRoot":"","sources":["../src/resolver-reach.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAyDvD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,aAA4B,EAAE,QAAuB;IACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC;IAClD,MAAM,KAAK,GACT,KAAK,KAAK,IAAI;QACd,KAAK,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC;QACnC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAClC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAiB,EAAE,MAAsB;IACvE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACzC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,MAAM,CAAC,aAAa,GAAG,EAAE,CAAC;IACzG,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;QACjD,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,wBAAwB,MAAM,CAAC,aAAa,uBAAuB,KAAK,CAAC,aAAa,GAAG;SAClG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,MAAM,CAAC,IAAI,wCAAwC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC;IAClI,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,MAAM,CAAC,MAAM,wCAAwC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC;IAC/H,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AA2BD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B,CAAC,MAAM,EAAE,EAAE;IAClE,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE;QACnC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;QAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;QAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;QAC9B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,IAAI;QACT,iDAAiD;SAChD,OAAO,CAAC,oCAAoC,EAAE,eAAe,CAAC;QAC/D,sDAAsD;SACrD,OAAO,CACN,2IAA2I,EAC3I,gBAAgB,CACjB;QACD,+EAA+E;SAC9E,OAAO,CAAC,8BAA8B,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC;AA4BD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAsB,EACtB,MAAsB,EACtB,OAA6C;IAE7C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,iBAAiB,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,oBAAoB,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAE7D,MAAM,KAAK,GAAG,KAAK,EAAE,OAA8B,EAAE,MAAe,EAAiB,EAAE;QACrF,MAAM,KAAK,GAAyB;YAClC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;YAC7E,OAAO;YACP,UAAU,EAAE,KAAK,EAAE;SACpB,CAAC;QACF,IAAI,MAAM,KAAK,SAAS;YAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACxD,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,+EAA+E;QAC/E,MAAM,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACtC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QAChC,CAAC;QACD,MAAM,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS;YAChC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YACvD,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,qEAAqE;QACrE,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-diff-against-base.d.ts","sourceRoot":"","sources":["../../src/resolvers/git-diff-against-base.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,oGAAoG;AACpG,wBAAgB,kCAAkC,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"git-diff-against-base.d.ts","sourceRoot":"","sources":["../../src/resolvers/git-diff-against-base.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,oGAAoG;AACpG,wBAAgB,kCAAkC,IAAI,IAAI,CA2CzD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { registerSourceResolver } from '../assembly-engine.js';
|
|
2
|
-
import { getGitDiff, getDiffStatSummary, MAX_DIFF_BYTES } from './shared/git-diff.js';
|
|
2
|
+
import { getGitDiff, getDeliveryDiff, getDiffStatSummary, MAX_DIFF_BYTES } from './shared/git-diff.js';
|
|
3
3
|
import { createLogger } from '../log.js';
|
|
4
4
|
const log = createLogger({ module: 'assembly-engine' });
|
|
5
5
|
/**
|
|
@@ -19,7 +19,13 @@ export function registerGitDiffAgainstBaseResolver() {
|
|
|
19
19
|
// (reviewed_through_sha) so a resumed reviewer sees only watermark..tip;
|
|
20
20
|
// every other caller diffs against the integration branch.
|
|
21
21
|
const baseBranch = context.diffBaseOverride ?? context.config.integrationBranch;
|
|
22
|
-
|
|
22
|
+
// For the watermark-override case the range is always ahead by construction,
|
|
23
|
+
// so a plain base...HEAD diff is correct. For the default integration base,
|
|
24
|
+
// use the delivery-diff resolver so a focus branch that has ALREADY merged
|
|
25
|
+
// (level with integration) still yields its work rather than an empty diff.
|
|
26
|
+
const diff = context.diffBaseOverride
|
|
27
|
+
? getGitDiff(context.worktreePath, baseBranch)
|
|
28
|
+
: getDeliveryDiff(context.worktreePath, baseBranch);
|
|
23
29
|
if (!diff.trim())
|
|
24
30
|
return '';
|
|
25
31
|
if (diff.length > MAX_DIFF_BYTES) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-diff-against-base.js","sourceRoot":"","sources":["../../src/resolvers/git-diff-against-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"git-diff-against-base.js","sourceRoot":"","sources":["../../src/resolvers/git-diff-against-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvG,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;AAGxD;;;;;GAKG;AACH,oGAAoG;AACpG,MAAM,UAAU,kCAAkC;IAChD,sBAAsB,CAAC,uBAAuB,EAAE,KAAK,EAAE,OAAwB,EAAmB,EAAE;QAClG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;YAC9D,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,wEAAwE;QACxE,yEAAyE;QACzE,2DAA2D;QAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAChF,6EAA6E;QAC7E,4EAA4E;QAC5E,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB;YACnC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC;YAC9C,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC;QAE5B,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;YAChD,OAAO;gBACL,wBAAwB,UAAU,GAAG;gBACrC,EAAE;gBACF,8BAA8B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,qBAAqB,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK;gBACvH,EAAE;gBACF,kBAAkB;gBAClB,EAAE;gBACF,KAAK;gBACL,IAAI,CAAC,IAAI,EAAE;gBACX,KAAK;gBACL,EAAE;gBACF,SAAS;gBACT,SAAS;gBACT,KAAK;aACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;QAED,OAAO,wBAAwB,UAAU,oBAAoB,IAAI,UAAU,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* (FocusEngine.init) can list them in the startup log.
|
|
29
29
|
*/
|
|
30
30
|
export declare function initResolvers(): string[];
|
|
31
|
-
export { MAX_DIFF_BYTES, getGitDiff, getDiffStatSummary, getChangedFiles, getCommitsAhead } from './shared/git-diff.js';
|
|
31
|
+
export { MAX_DIFF_BYTES, getGitDiff, getDiffStatSummary, getChangedFiles, getCommitsAhead, getGitDiffRange, getDiffStatRange, getChangedFilesRange, findDeliveryMergeCommit, resolveDeliveryDiffRange, getDeliveryDiff, } from './shared/git-diff.js';
|
|
32
32
|
export { CRT_DUMP_BUDGET_CHARS, renderRealityTreeDump, FOCUS_REALITY_TREE_EMPTY_STATE, } from './shared/reality-tree.js';
|
|
33
33
|
export type { RealityTreeRow, RealityTreeListResponse, RealityNodeRow, RealityEdgeRow, NodeListResponse, EdgeListResponse, } from './shared/reality-tree.js';
|
|
34
34
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAyFH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAgBxC;AAGD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAyFH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAgBxC;AAGD,OAAO,EACL,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC"}
|
package/dist/resolvers/index.js
CHANGED
|
@@ -125,6 +125,6 @@ export function initResolvers() {
|
|
|
125
125
|
return keys;
|
|
126
126
|
}
|
|
127
127
|
// ── Shared public surface (re-exports for external consumers) ─────────
|
|
128
|
-
export { MAX_DIFF_BYTES, getGitDiff, getDiffStatSummary, getChangedFiles, getCommitsAhead } from './shared/git-diff.js';
|
|
128
|
+
export { MAX_DIFF_BYTES, getGitDiff, getDiffStatSummary, getChangedFiles, getCommitsAhead, getGitDiffRange, getDiffStatRange, getChangedFilesRange, findDeliveryMergeCommit, resolveDeliveryDiffRange, getDeliveryDiff, } from './shared/git-diff.js';
|
|
129
129
|
export { CRT_DUMP_BUDGET_CHARS, renderRealityTreeDump, FOCUS_REALITY_TREE_EMPTY_STATE, } from './shared/reality-tree.js';
|
|
130
130
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,0CAA0C,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,mCAAmC,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,kCAAkC,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,EAAE,uCAAuC,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,wCAAwC,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,qCAAqC,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAEnF,yEAAyE;AAEzE,yEAAyE;AACzE,MAAM,kBAAkB,GAA8B;IACpD,0CAA0C;IAC1C,mCAAmC;IACnC,8BAA8B;IAC9B,4BAA4B;IAC5B,qCAAqC;IACrC,gCAAgC;IAChC,0BAA0B;IAC1B,yBAAyB;IACzB,kCAAkC;IAClC,uCAAuC;IACvC,8BAA8B;IAC9B,iCAAiC;IACjC,+BAA+B;IAC/B,+BAA+B;IAC/B,8BAA8B;IAC9B,uCAAuC;IACvC,wCAAwC;IACxC,8BAA8B;IAC9B,kCAAkC;IAClC,6BAA6B;IAC7B,6BAA6B;IAC7B,2BAA2B;IAC3B,2BAA2B;IAC3B,mCAAmC;IACnC,gCAAgC;IAChC,6BAA6B;IAC7B,gCAAgC;IAChC,mCAAmC;IACnC,gCAAgC;IAChC,iCAAiC;IACjC,iCAAiC;IACjC,qCAAqC;IACrC,gCAAgC;IAChC,iCAAiC;IACjC,mCAAmC;IACnC,0BAA0B;IAC1B,0BAA0B;IAC1B,oCAAoC;CACrC,CAAC;AAEF,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;YAC1C,QAAQ,EAAE,CAAC;QACb,CAAC;QACD,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,0BAA0B,EAAE,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,2EAA2E;YAC3E,mEAAmE;YACnE,kEAAkE,CACnE,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yEAAyE;AACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
* Git diff helpers shared across resolvers.
|
|
3
3
|
*/
|
|
4
4
|
export declare const MAX_DIFF_BYTES: number;
|
|
5
|
+
/**
|
|
6
|
+
* Run `git diff <range>` in a worktree. Returns the raw diff output, or empty
|
|
7
|
+
* string on failure. `range` is any ref expression git diff accepts, e.g.
|
|
8
|
+
* `integration...HEAD` or `<merge>^1...<merge>`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getGitDiffRange(worktreePath: string, range: string): string;
|
|
11
|
+
/** `git diff --stat <range>` (for the truncation header). Empty on failure. */
|
|
12
|
+
export declare function getDiffStatRange(worktreePath: string, range: string): string;
|
|
13
|
+
/** `git diff --name-only <range>` (name-only). Empty array on failure. */
|
|
14
|
+
export declare function getChangedFilesRange(worktreePath: string, range: string): string[];
|
|
5
15
|
/**
|
|
6
16
|
* Run git diff in a worktree against the base branch.
|
|
7
17
|
* Returns the raw diff output, or empty string on failure.
|
|
@@ -24,4 +34,41 @@ export declare function getChangedFiles(worktreePath: string, baseBranch: string
|
|
|
24
34
|
* worktree. Returns 0 on failure so callers treat "unknown" as "no commits".
|
|
25
35
|
*/
|
|
26
36
|
export declare function getCommitsAhead(worktreePath: string, baseBranch: string): number;
|
|
37
|
+
/**
|
|
38
|
+
* Find the merge commit on `baseBranch` that merged the current focus branch
|
|
39
|
+
* (the worktree's HEAD) into it.
|
|
40
|
+
*
|
|
41
|
+
* `git diff base...HEAD` answers "what is left to merge"; it empties the moment
|
|
42
|
+
* the focus branch merges into the base. But when the base advanced past the
|
|
43
|
+
* fork point, the merge is a real merge commit whose non-first parent IS the
|
|
44
|
+
* focus tip -- so `git diff <merge>^1 <merge>` still recovers exactly the
|
|
45
|
+
* delivery's contribution. This locates that merge commit deterministically
|
|
46
|
+
* from what is in the repo (no session ids, no reflog): scan the base branch's
|
|
47
|
+
* merge commits for one whose second (or later) parent equals HEAD.
|
|
48
|
+
*
|
|
49
|
+
* Returns null when no such merge exists -- an unmerged branch, or a merge that
|
|
50
|
+
* FAST-FORWARDED (no merge commit, so the fork point leaves no in-tree marker).
|
|
51
|
+
* The caller then yields an empty diff, which the instrument-fault path handles.
|
|
52
|
+
*/
|
|
53
|
+
export declare function findDeliveryMergeCommit(worktreePath: string, baseBranch: string): string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the git range that contains a delivery's work, robust to the focus
|
|
56
|
+
* branch having already merged into its base:
|
|
57
|
+
*
|
|
58
|
+
* - branch AHEAD of base -> `base...HEAD` (historic behaviour,
|
|
59
|
+
* byte-identical to the old getGitDiff)
|
|
60
|
+
* - branch LEVEL/BEHIND after merge -> `<merge>^1...<merge>` (recovered from
|
|
61
|
+
* the merge commit that brought it in)
|
|
62
|
+
* - no attributable commits -> null (caller yields empty; the
|
|
63
|
+
* instrument-fault path handles it)
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveDeliveryDiffRange(worktreePath: string, baseBranch: string): string | null;
|
|
66
|
+
/**
|
|
67
|
+
* The delivery's diff, resolved from the range that actually contains its work
|
|
68
|
+
* (see resolveDeliveryDiffRange). For a branch still ahead of base this is
|
|
69
|
+
* byte-identical to `getGitDiff(worktreePath, baseBranch)`; for a merged branch
|
|
70
|
+
* it recovers the delivery's contribution from the merge commit; for a delivery
|
|
71
|
+
* with no attributable commits it returns ''.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getDeliveryDiff(worktreePath: string, baseBranch: string): string;
|
|
27
74
|
//# sourceMappingURL=git-diff.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-diff.d.ts","sourceRoot":"","sources":["../../../src/resolvers/shared/git-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,eAAO,MAAM,cAAc,QAAY,CAAC;AAExC;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"git-diff.d.ts","sourceRoot":"","sources":["../../../src/resolvers/shared/git-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,eAAO,MAAM,cAAc,QAAY,CAAC;AAExC;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3E;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAS5E;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAUlF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAElF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWhF;AAKD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB/F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGhF"}
|
|
@@ -4,42 +4,58 @@
|
|
|
4
4
|
import { execSync } from 'node:child_process';
|
|
5
5
|
export const MAX_DIFF_BYTES = 50 * 1024; // 50 KB truncation limit for git diffs
|
|
6
6
|
/**
|
|
7
|
-
* Run git diff in a worktree
|
|
8
|
-
*
|
|
7
|
+
* Run `git diff <range>` in a worktree. Returns the raw diff output, or empty
|
|
8
|
+
* string on failure. `range` is any ref expression git diff accepts, e.g.
|
|
9
|
+
* `integration...HEAD` or `<merge>^1...<merge>`.
|
|
9
10
|
*/
|
|
10
|
-
export function
|
|
11
|
+
export function getGitDiffRange(worktreePath, range) {
|
|
11
12
|
try {
|
|
12
|
-
const diff = execSync(`git diff ${
|
|
13
|
+
const diff = execSync(`git diff ${range}`, { cwd: worktreePath, maxBuffer: 10 * 1024 * 1024, encoding: 'utf-8' });
|
|
13
14
|
return diff;
|
|
14
15
|
}
|
|
15
16
|
catch {
|
|
16
17
|
return '';
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
export function getDiffStatSummary(worktreePath, baseBranch) {
|
|
20
|
+
/** `git diff --stat <range>` (for the truncation header). Empty on failure. */
|
|
21
|
+
export function getDiffStatRange(worktreePath, range) {
|
|
23
22
|
try {
|
|
24
|
-
return execSync(`git diff --stat ${
|
|
23
|
+
return execSync(`git diff --stat ${range}`, { cwd: worktreePath, maxBuffer: 1024 * 1024, encoding: 'utf-8' });
|
|
25
24
|
}
|
|
26
25
|
catch {
|
|
27
26
|
return '';
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
* Returns an empty array on failure (missing worktree / bad range).
|
|
33
|
-
*/
|
|
34
|
-
export function getChangedFiles(worktreePath, baseBranch) {
|
|
29
|
+
/** `git diff --name-only <range>` (name-only). Empty array on failure. */
|
|
30
|
+
export function getChangedFilesRange(worktreePath, range) {
|
|
35
31
|
try {
|
|
36
|
-
const out = execSync(`git diff --name-only ${
|
|
32
|
+
const out = execSync(`git diff --name-only ${range}`, { cwd: worktreePath, maxBuffer: 1024 * 1024, encoding: 'utf-8' });
|
|
37
33
|
return out.split('\n').map((l) => l.trim()).filter((l) => l !== '');
|
|
38
34
|
}
|
|
39
35
|
catch {
|
|
40
36
|
return [];
|
|
41
37
|
}
|
|
42
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Run git diff in a worktree against the base branch.
|
|
41
|
+
* Returns the raw diff output, or empty string on failure.
|
|
42
|
+
*/
|
|
43
|
+
export function getGitDiff(worktreePath, baseBranch) {
|
|
44
|
+
return getGitDiffRange(worktreePath, `${baseBranch}...HEAD`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get a summary of files changed in a diff (for truncation header).
|
|
48
|
+
*/
|
|
49
|
+
export function getDiffStatSummary(worktreePath, baseBranch) {
|
|
50
|
+
return getDiffStatRange(worktreePath, `${baseBranch}...HEAD`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* List the files changed between the base branch and HEAD (name-only).
|
|
54
|
+
* Returns an empty array on failure (missing worktree / bad range).
|
|
55
|
+
*/
|
|
56
|
+
export function getChangedFiles(worktreePath, baseBranch) {
|
|
57
|
+
return getChangedFilesRange(worktreePath, `${baseBranch}...HEAD`);
|
|
58
|
+
}
|
|
43
59
|
/**
|
|
44
60
|
* Count commits on HEAD that are not reachable from the base branch
|
|
45
61
|
* (`git rev-list --count base..HEAD`). This is the delivery's own commit
|
|
@@ -57,4 +73,76 @@ export function getCommitsAhead(worktreePath, baseBranch) {
|
|
|
57
73
|
return 0;
|
|
58
74
|
}
|
|
59
75
|
}
|
|
76
|
+
/** How many merge commits back to scan on the base branch for a delivery merge. */
|
|
77
|
+
const MERGE_SCAN_LIMIT = 2000;
|
|
78
|
+
/**
|
|
79
|
+
* Find the merge commit on `baseBranch` that merged the current focus branch
|
|
80
|
+
* (the worktree's HEAD) into it.
|
|
81
|
+
*
|
|
82
|
+
* `git diff base...HEAD` answers "what is left to merge"; it empties the moment
|
|
83
|
+
* the focus branch merges into the base. But when the base advanced past the
|
|
84
|
+
* fork point, the merge is a real merge commit whose non-first parent IS the
|
|
85
|
+
* focus tip -- so `git diff <merge>^1 <merge>` still recovers exactly the
|
|
86
|
+
* delivery's contribution. This locates that merge commit deterministically
|
|
87
|
+
* from what is in the repo (no session ids, no reflog): scan the base branch's
|
|
88
|
+
* merge commits for one whose second (or later) parent equals HEAD.
|
|
89
|
+
*
|
|
90
|
+
* Returns null when no such merge exists -- an unmerged branch, or a merge that
|
|
91
|
+
* FAST-FORWARDED (no merge commit, so the fork point leaves no in-tree marker).
|
|
92
|
+
* The caller then yields an empty diff, which the instrument-fault path handles.
|
|
93
|
+
*/
|
|
94
|
+
export function findDeliveryMergeCommit(worktreePath, baseBranch) {
|
|
95
|
+
try {
|
|
96
|
+
const head = execSync('git rev-parse HEAD', {
|
|
97
|
+
cwd: worktreePath, maxBuffer: 1024 * 1024, encoding: 'utf-8',
|
|
98
|
+
}).trim();
|
|
99
|
+
if (head === '')
|
|
100
|
+
return null;
|
|
101
|
+
const out = execSync(`git rev-list --merges --parents -n ${MERGE_SCAN_LIMIT} ${baseBranch}`, { cwd: worktreePath, maxBuffer: 10 * 1024 * 1024, encoding: 'utf-8' });
|
|
102
|
+
for (const line of out.split('\n')) {
|
|
103
|
+
const parts = line.trim().split(/\s+/).filter((p) => p !== '');
|
|
104
|
+
// Format: <merge> <parent1> <parent2> [...]. A merge has >= 2 parents.
|
|
105
|
+
if (parts.length < 3)
|
|
106
|
+
continue;
|
|
107
|
+
const merge = parts[0];
|
|
108
|
+
const nonFirstParents = parts.slice(2); // second+ parents = the merged-in tips
|
|
109
|
+
if (nonFirstParents.includes(head))
|
|
110
|
+
return merge ?? null;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Resolve the git range that contains a delivery's work, robust to the focus
|
|
120
|
+
* branch having already merged into its base:
|
|
121
|
+
*
|
|
122
|
+
* - branch AHEAD of base -> `base...HEAD` (historic behaviour,
|
|
123
|
+
* byte-identical to the old getGitDiff)
|
|
124
|
+
* - branch LEVEL/BEHIND after merge -> `<merge>^1...<merge>` (recovered from
|
|
125
|
+
* the merge commit that brought it in)
|
|
126
|
+
* - no attributable commits -> null (caller yields empty; the
|
|
127
|
+
* instrument-fault path handles it)
|
|
128
|
+
*/
|
|
129
|
+
export function resolveDeliveryDiffRange(worktreePath, baseBranch) {
|
|
130
|
+
if (getCommitsAhead(worktreePath, baseBranch) > 0)
|
|
131
|
+
return `${baseBranch}...HEAD`;
|
|
132
|
+
const merge = findDeliveryMergeCommit(worktreePath, baseBranch);
|
|
133
|
+
if (merge)
|
|
134
|
+
return `${merge}^1...${merge}`;
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The delivery's diff, resolved from the range that actually contains its work
|
|
139
|
+
* (see resolveDeliveryDiffRange). For a branch still ahead of base this is
|
|
140
|
+
* byte-identical to `getGitDiff(worktreePath, baseBranch)`; for a merged branch
|
|
141
|
+
* it recovers the delivery's contribution from the merge commit; for a delivery
|
|
142
|
+
* with no attributable commits it returns ''.
|
|
143
|
+
*/
|
|
144
|
+
export function getDeliveryDiff(worktreePath, baseBranch) {
|
|
145
|
+
const range = resolveDeliveryDiffRange(worktreePath, baseBranch);
|
|
146
|
+
return range ? getGitDiffRange(worktreePath, range) : '';
|
|
147
|
+
}
|
|
60
148
|
//# sourceMappingURL=git-diff.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-diff.js","sourceRoot":"","sources":["../../../src/resolvers/shared/git-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,uCAAuC;AAEhF
|
|
1
|
+
{"version":3,"file":"git-diff.js","sourceRoot":"","sources":["../../../src/resolvers/shared/git-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,uCAAuC;AAEhF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,KAAa;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CACnB,YAAY,KAAK,EAAE,EACnB,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtE,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,YAAoB,EAAE,KAAa;IAClE,IAAI,CAAC;QACH,OAAO,QAAQ,CACb,mBAAmB,KAAK,EAAE,EAC1B,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CACjE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,oBAAoB,CAAC,YAAoB,EAAE,KAAa;IACtE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAClB,wBAAwB,KAAK,EAAE,EAC/B,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CACjE,CAAC;QACF,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB,EAAE,UAAkB;IACjE,OAAO,eAAe,CAAC,YAAY,EAAE,GAAG,UAAU,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAoB,EAAE,UAAkB;IACzE,OAAO,gBAAgB,CAAC,YAAY,EAAE,GAAG,UAAU,SAAS,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,UAAkB;IACtE,OAAO,oBAAoB,CAAC,YAAY,EAAE,GAAG,UAAU,SAAS,CAAC,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,UAAkB;IACtE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAClB,wBAAwB,UAAU,QAAQ,EAC1C,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CACjE,CAAC;QACF,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,uBAAuB,CAAC,YAAoB,EAAE,UAAkB;IAC9E,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,EAAE;YAC1C,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO;SAC7D,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QAC7B,MAAM,GAAG,GAAG,QAAQ,CAClB,sCAAsC,gBAAgB,IAAI,UAAU,EAAE,EACtE,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtE,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YAC/D,uEAAuE;YACvE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,uCAAuC;YAC/E,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,IAAI,IAAI,CAAC;QAC3D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,YAAoB,EAAE,UAAkB;IAC/E,IAAI,eAAe,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,UAAU,SAAS,CAAC;IACjF,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAChE,IAAI,KAAK;QAAE,OAAO,GAAG,KAAK,QAAQ,KAAK,EAAE,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,UAAkB;IACtE,MAAM,KAAK,GAAG,wBAAwB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACjE,OAAO,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -61,14 +61,48 @@ export declare function resolveReviewerFallbackRole(roles: Iterable<AgentRole>):
|
|
|
61
61
|
/**
|
|
62
62
|
* Decide what to do with a null-role pending spawn directive.
|
|
63
63
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
64
|
+
* A null assigned_agent_role_id now means one of TWO things, and they must be
|
|
65
|
+
* told apart:
|
|
66
|
+
*
|
|
67
|
+
* - An OPERATOR STOP (product_focuses.operator_stopped_at is set): the human
|
|
68
|
+
* pulled the Play toggle to halt the focus. This is authoritative and wins
|
|
69
|
+
* over everything -- when `operatorStopped` is true we `skip` for EVERY
|
|
70
|
+
* sessionType, review included. The stop lever must never become the trigger
|
|
71
|
+
* for the path it was meant to stop.
|
|
72
|
+
* - A LIFECYCLE CLEAR (operator_stopped_at null): auto_terminate_focus_team()
|
|
73
|
+
* nulled the role at completion. Here the pre-existing layered fallback
|
|
74
|
+
* applies -- a review directive is a SECOND team that must spawn AFTER
|
|
75
|
+
* completion (spawn under the fallback role, else clear); a coding directive
|
|
76
|
+
* is the intended off-state and is skipped.
|
|
77
|
+
*
|
|
78
|
+
* With `operatorStopped` false the behaviour is byte-identical to before the
|
|
79
|
+
* operator-stop fact existed.
|
|
67
80
|
*
|
|
68
81
|
* Pure and exported for unit testing (peer of resolveReviewerFallbackRole).
|
|
69
82
|
*/
|
|
70
83
|
export declare function decideNullRoleSpawn(input: {
|
|
71
84
|
sessionType: 'coding' | 'review' | undefined;
|
|
72
85
|
fallbackRole: AgentRole | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* Whether an operator has stopped this focus (product_focuses.
|
|
88
|
+
* operator_stopped_at is set). When true, no spawn happens for any
|
|
89
|
+
* sessionType -- the operator's stop is authoritative.
|
|
90
|
+
*/
|
|
91
|
+
operatorStopped: boolean;
|
|
73
92
|
}): NullRoleSpawnDecision;
|
|
93
|
+
/**
|
|
94
|
+
* Once-per-blocked-episode gate for the null-role "coding off-state" skip
|
|
95
|
+
* warning. The listener holds a Set of focus ids already warned for the current
|
|
96
|
+
* continuous blocked episode; this mutates it and returns whether to emit the
|
|
97
|
+
* warning now:
|
|
98
|
+
*
|
|
99
|
+
* - focus not yet in the set -> add it and return true (warn once, on entry).
|
|
100
|
+
* - focus already in the set -> return false (suppress the per-poll repeat).
|
|
101
|
+
*
|
|
102
|
+
* The listener removes the focus from the set when it resumes (role assigned,
|
|
103
|
+
* directive cleared, or focus leaves the active set), so a later re-entry warns
|
|
104
|
+
* again. Pure w.r.t. its inputs (Set in, boolean out) and exported for unit
|
|
105
|
+
* testing without standing up the poll loop.
|
|
106
|
+
*/
|
|
107
|
+
export declare function shouldWarnNullRoleSkip(warnedFocuses: Set<string>, focusId: string): boolean;
|
|
74
108
|
//# sourceMappingURL=review-role-fallback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-role-fallback.d.ts","sourceRoot":"","sources":["../../src/spawn/review-role-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,cAAc,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAExB;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,GACzB,SAAS,GAAG,SAAS,CAKvB;AAED
|
|
1
|
+
{"version":3,"file":"review-role-fallback.d.ts","sourceRoot":"","sources":["../../src/spawn/review-role-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,cAAc,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAExB;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,GACzB,SAAS,GAAG,SAAS,CAKvB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC7C,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;CAC1B,GAAG,qBAAqB,CAKxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAIT"}
|
|
@@ -46,17 +46,52 @@ export function resolveReviewerFallbackRole(roles) {
|
|
|
46
46
|
/**
|
|
47
47
|
* Decide what to do with a null-role pending spawn directive.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* A null assigned_agent_role_id now means one of TWO things, and they must be
|
|
50
|
+
* told apart:
|
|
51
|
+
*
|
|
52
|
+
* - An OPERATOR STOP (product_focuses.operator_stopped_at is set): the human
|
|
53
|
+
* pulled the Play toggle to halt the focus. This is authoritative and wins
|
|
54
|
+
* over everything -- when `operatorStopped` is true we `skip` for EVERY
|
|
55
|
+
* sessionType, review included. The stop lever must never become the trigger
|
|
56
|
+
* for the path it was meant to stop.
|
|
57
|
+
* - A LIFECYCLE CLEAR (operator_stopped_at null): auto_terminate_focus_team()
|
|
58
|
+
* nulled the role at completion. Here the pre-existing layered fallback
|
|
59
|
+
* applies -- a review directive is a SECOND team that must spawn AFTER
|
|
60
|
+
* completion (spawn under the fallback role, else clear); a coding directive
|
|
61
|
+
* is the intended off-state and is skipped.
|
|
62
|
+
*
|
|
63
|
+
* With `operatorStopped` false the behaviour is byte-identical to before the
|
|
64
|
+
* operator-stop fact existed.
|
|
52
65
|
*
|
|
53
66
|
* Pure and exported for unit testing (peer of resolveReviewerFallbackRole).
|
|
54
67
|
*/
|
|
55
68
|
export function decideNullRoleSpawn(input) {
|
|
69
|
+
if (input.operatorStopped)
|
|
70
|
+
return { action: 'skip' };
|
|
56
71
|
if (input.sessionType !== 'review')
|
|
57
72
|
return { action: 'skip' };
|
|
58
73
|
if (input.fallbackRole)
|
|
59
74
|
return { action: 'spawn', role: input.fallbackRole };
|
|
60
75
|
return { action: 'clear' };
|
|
61
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Once-per-blocked-episode gate for the null-role "coding off-state" skip
|
|
79
|
+
* warning. The listener holds a Set of focus ids already warned for the current
|
|
80
|
+
* continuous blocked episode; this mutates it and returns whether to emit the
|
|
81
|
+
* warning now:
|
|
82
|
+
*
|
|
83
|
+
* - focus not yet in the set -> add it and return true (warn once, on entry).
|
|
84
|
+
* - focus already in the set -> return false (suppress the per-poll repeat).
|
|
85
|
+
*
|
|
86
|
+
* The listener removes the focus from the set when it resumes (role assigned,
|
|
87
|
+
* directive cleared, or focus leaves the active set), so a later re-entry warns
|
|
88
|
+
* again. Pure w.r.t. its inputs (Set in, boolean out) and exported for unit
|
|
89
|
+
* testing without standing up the poll loop.
|
|
90
|
+
*/
|
|
91
|
+
export function shouldWarnNullRoleSkip(warnedFocuses, focusId) {
|
|
92
|
+
if (warnedFocuses.has(focusId))
|
|
93
|
+
return false;
|
|
94
|
+
warnedFocuses.add(focusId);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
62
97
|
//# sourceMappingURL=review-role-fallback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-role-fallback.js","sourceRoot":"","sources":["../../src/spawn/review-role-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CAAC;AAmBtD;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAA0B;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,0BAA0B;YAAE,OAAO,IAAI,CAAC;IAC5D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"review-role-fallback.js","sourceRoot":"","sources":["../../src/spawn/review-role-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CAAC;AAmBtD;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAA0B;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,0BAA0B;YAAE,OAAO,IAAI,CAAC;IAC5D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,mBAAmB,CAAC,KASnC;IACC,IAAI,KAAK,CAAC,eAAe;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACrD,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC9D,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC;IAC7E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,sBAAsB,CACpC,aAA0B,EAC1B,OAAe;IAEf,IAAI,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC"}
|