@telora/daemon 0.22.137 → 0.22.146
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 +13 -3
- package/dist/audit/audit-phase.d.ts +34 -1
- package/dist/audit/audit-phase.d.ts.map +1 -1
- package/dist/audit/audit-phase.js +92 -9
- package/dist/audit/audit-phase.js.map +1 -1
- package/dist/audit/audit-prompt.d.ts +174 -0
- package/dist/audit/audit-prompt.d.ts.map +1 -1
- package/dist/audit/audit-prompt.js +365 -2
- package/dist/audit/audit-prompt.js.map +1 -1
- package/dist/completion/review-coverage-shas.d.ts +49 -0
- package/dist/completion/review-coverage-shas.d.ts.map +1 -0
- package/dist/completion/review-coverage-shas.js +128 -0
- package/dist/completion/review-coverage-shas.js.map +1 -0
- package/dist/completion/review-exit-deps.d.ts +15 -2
- package/dist/completion/review-exit-deps.d.ts.map +1 -1
- package/dist/completion/review-exit-deps.js +9 -3
- package/dist/completion/review-exit-deps.js.map +1 -1
- package/dist/delivery/delivery-review-coverage.d.ts +216 -0
- package/dist/delivery/delivery-review-coverage.d.ts.map +1 -0
- package/dist/delivery/delivery-review-coverage.js +208 -0
- package/dist/delivery/delivery-review-coverage.js.map +1 -0
- package/dist/queries/focus-branch-work-evidence.d.ts +55 -0
- package/dist/queries/focus-branch-work-evidence.d.ts.map +1 -0
- package/dist/queries/focus-branch-work-evidence.js +65 -0
- package/dist/queries/focus-branch-work-evidence.js.map +1 -0
- package/dist/queries/focus-criteria-standing.d.ts +138 -0
- package/dist/queries/focus-criteria-standing.d.ts.map +1 -0
- package/dist/queries/focus-criteria-standing.js +98 -0
- package/dist/queries/focus-criteria-standing.js.map +1 -0
- package/dist/queries/focus-review-watermark.d.ts +35 -0
- package/dist/queries/focus-review-watermark.d.ts.map +1 -0
- package/dist/queries/focus-review-watermark.js +47 -0
- package/dist/queries/focus-review-watermark.js.map +1 -0
- package/dist/queries/focuses.d.ts +0 -9
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +0 -14
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/shared.js +1 -1
- package/dist/queries/verification.d.ts +23 -25
- package/dist/queries/verification.d.ts.map +1 -1
- package/dist/queries/verification.js +66 -45
- package/dist/queries/verification.js.map +1 -1
- package/dist/resolvers/assembly-engine.d.ts +51 -0
- package/dist/resolvers/assembly-engine.d.ts.map +1 -1
- package/dist/resolvers/assembly-engine.js +10 -20
- package/dist/resolvers/assembly-engine.js.map +1 -1
- package/dist/resolvers/branch-work-arming.d.ts +133 -0
- package/dist/resolvers/branch-work-arming.d.ts.map +1 -0
- package/dist/resolvers/branch-work-arming.js +67 -0
- package/dist/resolvers/branch-work-arming.js.map +1 -0
- package/dist/resolvers/focus-criteria-standing.d.ts +24 -0
- package/dist/resolvers/focus-criteria-standing.d.ts.map +1 -0
- package/dist/resolvers/focus-criteria-standing.js +234 -0
- package/dist/resolvers/focus-criteria-standing.js.map +1 -0
- package/dist/resolvers/focus-review-coverage.d.ts +189 -0
- package/dist/resolvers/focus-review-coverage.d.ts.map +1 -0
- package/dist/resolvers/focus-review-coverage.js +516 -0
- package/dist/resolvers/focus-review-coverage.js.map +1 -0
- package/dist/resolvers/git-diff-against-base.d.ts.map +1 -1
- package/dist/resolvers/git-diff-against-base.js +11 -0
- package/dist/resolvers/git-diff-against-base.js.map +1 -1
- package/dist/resolvers/index.d.ts.map +1 -1
- package/dist/resolvers/index.js +7 -1
- package/dist/resolvers/index.js.map +1 -1
- package/dist/resolvers/reality-tree-snapshot.d.ts +9 -4
- package/dist/resolvers/reality-tree-snapshot.d.ts.map +1 -1
- package/dist/resolvers/reality-tree-snapshot.js +64 -17
- package/dist/resolvers/reality-tree-snapshot.js.map +1 -1
- package/dist/resolvers/shared/branch-fact-provenance.d.ts +258 -0
- package/dist/resolvers/shared/branch-fact-provenance.d.ts.map +1 -0
- package/dist/resolvers/shared/branch-fact-provenance.js +571 -0
- package/dist/resolvers/shared/branch-fact-provenance.js.map +1 -0
- package/dist/resolvers/shared/reality-tree-arrival.d.ts +71 -0
- package/dist/resolvers/shared/reality-tree-arrival.d.ts.map +1 -0
- package/dist/resolvers/shared/reality-tree-arrival.js +129 -0
- package/dist/resolvers/shared/reality-tree-arrival.js.map +1 -0
- package/dist/testing/fixtures/index.js +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
-
// Pinned by: packages/daemon/src/
|
|
2
|
+
// Pinned by: packages/daemon/src/audit/audit-phase.test.ts,
|
|
3
|
+
// packages/daemon/src/prompt/decision-rule-replaces-escalation.test.ts
|
|
3
4
|
// PINNED-BY-END
|
|
4
5
|
/**
|
|
5
6
|
* Posture-independent intro. The first line is stable across postures (a spawn
|
|
@@ -171,7 +172,367 @@ injection-anchored plan inverts that: remediation is scoped one root cause at a
|
|
|
171
172
|
time from an injection, with acceptance pinned to a desired effect, so there is
|
|
172
173
|
nothing to over-complete. The structured CRT + FRT make a wrong root cause
|
|
173
174
|
legible as a plan -- catchable up front rather than only after code has moved.`;
|
|
174
|
-
|
|
175
|
+
/**
|
|
176
|
+
* The withhold half of the test, identical wherever it is stated: the same
|
|
177
|
+
* candidate, the same disposition, no conditions anywhere.
|
|
178
|
+
*/
|
|
179
|
+
const WITHHOLD_RESIDUE = {
|
|
180
|
+
candidate: 'residue_or_restatement',
|
|
181
|
+
disposition: 'withhold',
|
|
182
|
+
conditions: [],
|
|
183
|
+
nonDeciding: [],
|
|
184
|
+
obligations: [],
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* The declared floor. Everything normative the floor says about what may be
|
|
188
|
+
* anchored is in the TYPED fields here; the prose below is generated from
|
|
189
|
+
* them, and the free-text fields carry context only.
|
|
190
|
+
*/
|
|
191
|
+
export const AUDIT_FLOOR_POLICY = {
|
|
192
|
+
universalLead: 'The floor stops ELABORATION, not new work.',
|
|
193
|
+
universal: [
|
|
194
|
+
WITHHOLD_RESIDUE,
|
|
195
|
+
{
|
|
196
|
+
candidate: 'new_root_cause',
|
|
197
|
+
disposition: 'anchor',
|
|
198
|
+
conditions: [],
|
|
199
|
+
nonDeciding: ['criterion_coverage'],
|
|
200
|
+
obligations: ['why the cause is new rather than residue or a restatement'],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
universalClosing: [
|
|
204
|
+
'Anchoring past a reached floor is a DECLARED act, never a silent one. Where the unreviewed-work hold below also stands in the way, declare it through the recorded override that section names (`allowUnreviewedResidue=true` with `unreviewedResidueReason`): that makes the deviation visible and traceable, and it is not a freeze.',
|
|
205
|
+
],
|
|
206
|
+
bases: [
|
|
207
|
+
{
|
|
208
|
+
basis: 'all_criteria_addressed',
|
|
209
|
+
isFloor: true,
|
|
210
|
+
lead: 'Basis `all_criteria_addressed` -- the floor is REACHED.',
|
|
211
|
+
situation: 'Every criterion the focus declared already has a delivery pointing at it, so there is no OPEN declared work to elaborate against.',
|
|
212
|
+
rules: [
|
|
213
|
+
WITHHOLD_RESIDUE,
|
|
214
|
+
{
|
|
215
|
+
candidate: 'new_root_cause',
|
|
216
|
+
disposition: 'anchor',
|
|
217
|
+
conditions: [],
|
|
218
|
+
nonDeciding: ['criterion_coverage'],
|
|
219
|
+
obligations: [
|
|
220
|
+
'why the cause is new rather than residue or a restatement',
|
|
221
|
+
'which criterion it touches',
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
caveat: 'Note what the basis does NOT mean: addressed is not MET. Whether the work satisfies a criterion is the focus review\'s judgement, not yours, so "the floor is reached" is never "the focus is done" -- it is "there is nothing further for THIS pass to ELABORATE".',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
basis: 'open_criteria_remain',
|
|
229
|
+
isFloor: false,
|
|
230
|
+
lead: 'Basis `open_criteria_remain` -- the open criteria ARE the remaining work.',
|
|
231
|
+
situation: 'Work against them by name: each injection you author should trace to an OPEN criterion, and your audit summary should say which.',
|
|
232
|
+
rules: [
|
|
233
|
+
{
|
|
234
|
+
candidate: 'new_root_cause',
|
|
235
|
+
disposition: 'anchor',
|
|
236
|
+
conditions: [],
|
|
237
|
+
nonDeciding: [],
|
|
238
|
+
obligations: [],
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
caveat: 'A new delivery that addresses no open criterion needs an explicit reason for existing, stated in the summary.',
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
basis: 'no_criteria_declared',
|
|
245
|
+
isFloor: false,
|
|
246
|
+
lead: 'Basis `no_criteria_declared` -- this is NOT a floor.',
|
|
247
|
+
situation: 'A focus that declared no acceptance criteria has gone UNMEASURED, not arrived.',
|
|
248
|
+
rules: [
|
|
249
|
+
WITHHOLD_RESIDUE,
|
|
250
|
+
{
|
|
251
|
+
candidate: 'new_root_cause',
|
|
252
|
+
disposition: 'anchor',
|
|
253
|
+
conditions: [],
|
|
254
|
+
nonDeciding: [],
|
|
255
|
+
obligations: [
|
|
256
|
+
'that this focus declares no criteria, so no floor could be computed for it',
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
caveat: 'Do not read the empty set as "everything is addressed", and do not read it as licence to elaborate without limit: judge each candidate on the tree\'s own evidence.',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
basis: 'read_failed',
|
|
264
|
+
isFloor: false,
|
|
265
|
+
lead: 'If that section says READ FAILED, you have NO floor.',
|
|
266
|
+
situation: 'An unreadable standing is not evidence that every criterion is addressed.',
|
|
267
|
+
rules: [
|
|
268
|
+
WITHHOLD_RESIDUE,
|
|
269
|
+
{
|
|
270
|
+
candidate: 'new_root_cause',
|
|
271
|
+
disposition: 'anchor',
|
|
272
|
+
conditions: [],
|
|
273
|
+
nonDeciding: [],
|
|
274
|
+
obligations: ['that the standing was unreadable on this pass'],
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* CLOSED LEXICON (1/4): the subject of the normative sentence, chosen by the
|
|
282
|
+
* rule's `candidate`. Stated in full where the test is introduced, and short
|
|
283
|
+
* at each basis so the definition is given once rather than four times.
|
|
284
|
+
*/
|
|
285
|
+
const CANDIDATE_SUBJECT = {
|
|
286
|
+
universal: {
|
|
287
|
+
new_root_cause: 'A GENUINELY NEW ROOT CAUSE -- one no existing delivery already covers --',
|
|
288
|
+
residue_or_restatement: 'RESIDUE of work still in flight -- or a RESTATEMENT or refinement of a cause an existing delivery already covers --',
|
|
289
|
+
},
|
|
290
|
+
basis: {
|
|
291
|
+
new_root_cause: 'A genuinely new root cause',
|
|
292
|
+
residue_or_restatement: 'Residue, or a restatement or refinement of a cause already covered,',
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
/** CLOSED LEXICON (2/4): the same candidate named as the side of the test. */
|
|
296
|
+
const CANDIDATE_LABEL = {
|
|
297
|
+
new_root_cause: 'NEW ROOT CAUSE',
|
|
298
|
+
residue_or_restatement: 'RESIDUE OR RESTATEMENT',
|
|
299
|
+
};
|
|
300
|
+
/** CLOSED LEXICON (3/4): what the floor DOES, chosen by `disposition`. */
|
|
301
|
+
const DISPOSITION_VERB = {
|
|
302
|
+
anchor: 'is ANCHORED',
|
|
303
|
+
withhold: 'is WITHHELD',
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* CLOSED LEXICON (4/4): how a disposition with NO declared conditions states
|
|
307
|
+
* its own scope. An unconditional rule must SAY it is unconditional: a
|
|
308
|
+
* sentence that merely omits the scope is one a reader fills with the last
|
|
309
|
+
* rule they were taught.
|
|
310
|
+
*/
|
|
311
|
+
const UNCONDITIONAL_SCOPE = {
|
|
312
|
+
universal: {
|
|
313
|
+
anchor: 'at every basis below, in every case those bases can present, with nothing further to satisfy first',
|
|
314
|
+
withhold: 'at every basis below, in every case those bases can present',
|
|
315
|
+
},
|
|
316
|
+
basis: {
|
|
317
|
+
anchor: 'here, in every case this basis can present, with nothing further to satisfy first',
|
|
318
|
+
withhold: 'here, in every case this basis can present',
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Prose for each non-deciding factor. One sentence per factor, stated once
|
|
323
|
+
* here, so "coverage is not the test" cannot drift from rule to rule.
|
|
324
|
+
*/
|
|
325
|
+
const NON_DECIDING_PROSE = {
|
|
326
|
+
criterion_coverage: 'Whether a declared criterion already covers the ground a cause sits on is NOT the test and never decides it: coverage tells you whether declared work remains OPEN, it cannot tell you whether a cause is NEW.',
|
|
327
|
+
};
|
|
328
|
+
/** How an obligation sentence opens, per disposition. */
|
|
329
|
+
const OBLIGATION_LEAD = {
|
|
330
|
+
anchor: 'When you anchor, say in your audit summary',
|
|
331
|
+
withhold: 'When you withhold, say in your audit summary',
|
|
332
|
+
};
|
|
333
|
+
// ---- BACKSTOP: a fast, INCOMPLETE check on the policy's remaining prose ----
|
|
334
|
+
//
|
|
335
|
+
// Read this before trusting the rules below. They are an ENUMERATION of
|
|
336
|
+
// wordings, NOT the guarantee that context prose carries no restriction -- the
|
|
337
|
+
// equality pin on the rendered section is (round-8 note above). What they buy
|
|
338
|
+
// is EARLINESS and a NAMED reason: a claim in vocabulary they happen to know
|
|
339
|
+
// fails at module load with the offending path, instead of surfacing later as
|
|
340
|
+
// an unexplained diff against the pin. Stated limits:
|
|
341
|
+
// - the lists are finite, and no list can be complete. The two escapes review
|
|
342
|
+
// filed -- "Fresh findings wait for review." and "A genuinely new root
|
|
343
|
+
// cause proceeds after every existing delivery is reviewed." -- carry no
|
|
344
|
+
// listed noun/verb pair and no scope marker, so these rules PASS them. The
|
|
345
|
+
// pin rejects them.
|
|
346
|
+
// - they can only ADD rejections. Nothing reads a green result as evidence
|
|
347
|
+
// that prose is clean: a green backstop over a changed render is still RED.
|
|
348
|
+
// Widening the lists is allowed and harmless. It is not progress, and it must
|
|
349
|
+
// never be written up as closing the class.
|
|
350
|
+
/** Nouns that name one of the floor's candidates. Finite; not exhaustive. */
|
|
351
|
+
const CANDIDATE_NOUN = /\b(root causes?|residue|restatements?|refinements?)\b/i;
|
|
352
|
+
/** Verbs that state what the floor DOES with a candidate. Finite; not exhaustive. */
|
|
353
|
+
const DISPOSITION_VERB_IN_PROSE = /\b(anchors?|anchored|anchoring|withholds?|withheld|suppress(?:es|ed)?|defers?|deferred|skips?|skipped|omits?|omitted|excludes?|excluded)\b/i;
|
|
354
|
+
/** Markers that narrow a claim's scope. A scope is declared, never written. */
|
|
355
|
+
const SCOPE_MARKER = /\b(only|unless|except|solely|provided that|so long as|as long as|conditional on|contingent on)\b/i;
|
|
356
|
+
/**
|
|
357
|
+
* Every free-text field of the policy. `conditions` is deliberately absent: it
|
|
358
|
+
* IS the declared channel for a scope, and it is counted rather than banned.
|
|
359
|
+
*
|
|
360
|
+
* Exported so the suite can prove the equality pin COVERS this set (every
|
|
361
|
+
* field's exact text appears verbatim inside the pinned render) rather than
|
|
362
|
+
* trusting a hand-maintained field list that goes stale on the next addition.
|
|
363
|
+
*/
|
|
364
|
+
export function floorProseFields(policy = AUDIT_FLOOR_POLICY) {
|
|
365
|
+
const obligationsOf = (at, rules) => rules.flatMap((rule, j) => rule.obligations.map((text, k) => ({ path: `${at}.rules[${j}].obligations[${k}]`, text })));
|
|
366
|
+
const fields = [
|
|
367
|
+
{ path: 'universalLead', text: policy.universalLead },
|
|
368
|
+
...policy.universalClosing.map((text, i) => ({ path: `universalClosing[${i}]`, text })),
|
|
369
|
+
...obligationsOf('universal', policy.universal),
|
|
370
|
+
];
|
|
371
|
+
policy.bases.forEach((basis, i) => {
|
|
372
|
+
const at = `bases[${i}]`;
|
|
373
|
+
fields.push({ path: `${at}.lead`, text: basis.lead });
|
|
374
|
+
fields.push({ path: `${at}.situation`, text: basis.situation });
|
|
375
|
+
if (basis.caveat !== undefined)
|
|
376
|
+
fields.push({ path: `${at}.caveat`, text: basis.caveat });
|
|
377
|
+
fields.push(...obligationsOf(at, basis.rules));
|
|
378
|
+
});
|
|
379
|
+
return fields;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Prose fields that state normative content IN A WORDING THESE LISTS KNOW. An
|
|
383
|
+
* empty result means "nothing recognised", NEVER "nothing normative" -- see the
|
|
384
|
+
* BACKSTOP note above for why no wording list can mean the latter. The
|
|
385
|
+
* completeness guarantee is the equality pin in audit-phase.test.ts; this only
|
|
386
|
+
* makes the recognised cases fail earlier, at load, with a named path. Exported
|
|
387
|
+
* so a test can demonstrate rejection on a mutated policy.
|
|
388
|
+
*/
|
|
389
|
+
export function findFloorProseViolations(policy = AUDIT_FLOOR_POLICY) {
|
|
390
|
+
const violations = [];
|
|
391
|
+
for (const field of floorProseFields(policy)) {
|
|
392
|
+
if (CANDIDATE_NOUN.test(field.text) && DISPOSITION_VERB_IN_PROSE.test(field.text)) {
|
|
393
|
+
violations.push({
|
|
394
|
+
path: field.path,
|
|
395
|
+
text: field.text,
|
|
396
|
+
reason: 'states a DISPOSITION for a CANDIDATE in prose. That claim is composed from '
|
|
397
|
+
+ '`candidate` + `disposition` + `conditions`; written by hand it is the one place a '
|
|
398
|
+
+ 'restriction sits where no structural channel sees it.',
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
if (SCOPE_MARKER.test(field.text)) {
|
|
402
|
+
violations.push({
|
|
403
|
+
path: field.path,
|
|
404
|
+
text: field.text,
|
|
405
|
+
reason: 'narrows a claim with a scope marker. A scope on the floor is declared in a rule\'s '
|
|
406
|
+
+ '`conditions`, where it is rendered as one clause and counted; context prose states none.',
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return violations;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Fail LOUDLY rather than compose a prompt that contradicts its own structure.
|
|
414
|
+
* The policy is a static constant, so a green test run is proof this can never
|
|
415
|
+
* throw at runtime; it throws at module load if someone edits prose into a
|
|
416
|
+
* normative claim THE BACKSTOP RECOGNISES. Prose it does not recognise composes
|
|
417
|
+
* fine here and is caught by the equality pin instead.
|
|
418
|
+
*/
|
|
419
|
+
function assertFloorProseIsContextOnly(policy) {
|
|
420
|
+
const violations = findFloorProseViolations(policy);
|
|
421
|
+
if (violations.length === 0)
|
|
422
|
+
return;
|
|
423
|
+
const detail = violations
|
|
424
|
+
.map((v) => ` ${v.path}: ${v.reason}\n text: ${v.text}`)
|
|
425
|
+
.join('\n');
|
|
426
|
+
throw new Error('audit floor policy: free-text field(s) carry normative content. The floor\'s normative '
|
|
427
|
+
+ 'claims are composed from the typed fields (candidate, disposition, conditions, '
|
|
428
|
+
+ 'nonDeciding); prose carries context only.\n' + detail);
|
|
429
|
+
}
|
|
430
|
+
/** Join clauses into one readable list ("a, b, and c"). */
|
|
431
|
+
function joinClauses(items) {
|
|
432
|
+
if (items.length < 2)
|
|
433
|
+
return items[0] ?? '';
|
|
434
|
+
return `${items.slice(0, -1).join(', ')}, and ${items[items.length - 1] ?? ''}`;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Render one rule as prose, entirely from its typed fields. A CONDITIONAL
|
|
438
|
+
* clause is emitted if and only if the rule declares conditions -- that
|
|
439
|
+
* one-to-one correspondence is what the tests count, so a freeze cannot be
|
|
440
|
+
* smuggled in as an extra sentence, and there is no sentence to write it in.
|
|
441
|
+
*/
|
|
442
|
+
function renderRule(rule, scope) {
|
|
443
|
+
const dispositionScope = rule.conditions.length > 0
|
|
444
|
+
? `only where ${joinClauses(rule.conditions)}`
|
|
445
|
+
: UNCONDITIONAL_SCOPE[scope][rule.disposition];
|
|
446
|
+
const parts = [
|
|
447
|
+
`${CANDIDATE_SUBJECT[scope][rule.candidate]} ${DISPOSITION_VERB[rule.disposition]} ${dispositionScope}.`,
|
|
448
|
+
];
|
|
449
|
+
for (const factor of rule.nonDeciding)
|
|
450
|
+
parts.push(NON_DECIDING_PROSE[factor]);
|
|
451
|
+
if (rule.obligations.length > 0) {
|
|
452
|
+
parts.push(`${OBLIGATION_LEAD[rule.disposition]} ${joinClauses(rule.obligations)}.`);
|
|
453
|
+
}
|
|
454
|
+
return parts.join(' ');
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Name the test, and state whether it holds everywhere. The "same test at
|
|
458
|
+
* every basis" half is COMPUTED against the bases rather than asserted, so a
|
|
459
|
+
* basis that departed from the universal rule would change this sentence
|
|
460
|
+
* instead of being contradicted by it.
|
|
461
|
+
*/
|
|
462
|
+
function renderTestSentence(policy) {
|
|
463
|
+
const universalDisposition = new Map(policy.universal.map((rule) => [rule.candidate, rule.disposition]));
|
|
464
|
+
const uniform = policy.bases.every((basis) => basis.rules.every((rule) => {
|
|
465
|
+
const declared = universalDisposition.get(rule.candidate);
|
|
466
|
+
return declared === undefined || (declared === rule.disposition && rule.conditions.length === 0);
|
|
467
|
+
}));
|
|
468
|
+
const sameness = uniform
|
|
469
|
+
? 'and it is the SAME test at every basis below'
|
|
470
|
+
: 'and the bases below depart from it -- read each one on its own terms';
|
|
471
|
+
return `The test is ${CANDIDATE_LABEL.residue_or_restatement} vs ${CANDIDATE_LABEL.new_root_cause}, ${sameness}.`;
|
|
472
|
+
}
|
|
473
|
+
/** Render one basis as a markdown bullet. */
|
|
474
|
+
function renderBasis(basis) {
|
|
475
|
+
const body = [basis.situation, ...basis.rules.map((rule) => renderRule(rule, 'basis'))];
|
|
476
|
+
if (basis.caveat !== undefined)
|
|
477
|
+
body.push(basis.caveat);
|
|
478
|
+
return `- **${basis.lead}** ${body.join(' ')}`;
|
|
479
|
+
}
|
|
480
|
+
/** Render the policy: the universal paragraph, then one bullet per basis. */
|
|
481
|
+
export function renderFloorPolicy(policy = AUDIT_FLOOR_POLICY) {
|
|
482
|
+
assertFloorProseIsContextOnly(policy);
|
|
483
|
+
const universal = [
|
|
484
|
+
`**${policy.universalLead}**`,
|
|
485
|
+
renderTestSentence(policy),
|
|
486
|
+
...policy.universal.map((rule) => renderRule(rule, 'universal')),
|
|
487
|
+
...policy.universalClosing,
|
|
488
|
+
].join(' ');
|
|
489
|
+
return [universal, '', ...policy.bases.map(renderBasis)];
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* The composed floor section: the pointer at the standing section (which
|
|
493
|
+
* states no rule about what may be anchored), then the rendered policy.
|
|
494
|
+
*/
|
|
495
|
+
export function renderFloorSection(policy = AUDIT_FLOOR_POLICY) {
|
|
496
|
+
return [
|
|
497
|
+
'',
|
|
498
|
+
'## Before you anchor (round 5): has this focus reached its declared floor?',
|
|
499
|
+
'',
|
|
500
|
+
'The "Focus acceptance criteria standing" section of your context lists this focus\'s OWN declared acceptance criteria, states for each whether a current delivery addresses it, and states the FLOOR with the basis it rests on. READ IT BEFORE YOU ANCHOR ANYTHING. It is the only thing in your context that says what this focus was for, and therefore the only thing that can tell you there is nothing left to anchor.',
|
|
501
|
+
'',
|
|
502
|
+
...renderFloorPolicy(policy),
|
|
503
|
+
];
|
|
504
|
+
}
|
|
505
|
+
const AUDIT_CRITERIA_FLOOR = renderFloorSection();
|
|
506
|
+
/**
|
|
507
|
+
* Round-5 pre-condition: the unreviewed-residue hold.
|
|
508
|
+
*
|
|
509
|
+
* Deliberately OUTSIDE the SHARED-AUDIT-GUIDE sentinels. The shared block is
|
|
510
|
+
* the posture-neutral tree-authoring discipline the MCP handler mirrors
|
|
511
|
+
* byte-for-byte; this text is specific to a pass that has the daemon's
|
|
512
|
+
* `focus.review_coverage` section in front of it (the assembly recipe supplies
|
|
513
|
+
* it, the MCP guide's readers have no such section), so putting it in the
|
|
514
|
+
* shared block would state a precondition its other reader cannot satisfy.
|
|
515
|
+
*
|
|
516
|
+
* WHY IT EXISTS. Round 5 anchors one remediation delivery per injection. Left
|
|
517
|
+
* alone, a pass anchors residue of work a reviewer has not looked at yet as a
|
|
518
|
+
* fresh sibling, and the focus re-opens on new work while the pass that
|
|
519
|
+
* produced it is never judged -- an armed focus with no floor. The create path
|
|
520
|
+
* already refuses that mechanically (unreviewed_residue_hold); this tells the
|
|
521
|
+
* pass the rule BEFORE it spends a call on a create that will be refused, and
|
|
522
|
+
* names the escape so the hold stays a presume-and-escape rather than a freeze.
|
|
523
|
+
*/
|
|
524
|
+
const AUDIT_UNREVIEWED_RESIDUE = [
|
|
525
|
+
'',
|
|
526
|
+
'## Before you anchor (round 5): is this residue of UNREVIEWED work?',
|
|
527
|
+
'',
|
|
528
|
+
'The "Delivery review coverage" section of your context partitions this focus\'s deliveries by review state -- reviewed, unreviewed, no work yet -- and states the basis it partitioned on. READ IT BEFORE YOU CREATE ANY DELIVERY. It is how you tell a fact produced by work a reviewer has judged from a fact produced by work no reviewer has seen.',
|
|
529
|
+
'',
|
|
530
|
+
'- **Attribute the fact before you judge it.** That section\'s "Fact provenance" sub-section maps each commit on the focus branch -- and each file those commits touched -- to the delivery that produced it and that delivery\'s review state. Use it to decide which partition an observed fact belongs to. Do NOT infer the producing delivery from a file path, a commit subject, or which delivery sounds related: the mapping is read from each commit\'s `Telora-Delivery` trailer, and a guess is exactly the inference this section exists to remove. A file the mapping shows was touched by MORE THAN ONE delivery belongs to all of them -- do not pick one. A fact the mapping reports as UNATTRIBUTED has no known producing delivery: treat it as UNREVIEWED and apply the hold below. If the mapping says NOT AVAILABLE, no fact on the branch is attributable at all -- treat every one of them as unreviewed.',
|
|
531
|
+
'- **Residue of an UNREVIEWED delivery is HELD, not anchored.** A defect or gap in work an unreviewed delivery produced is not new information: it is the not-yet-judged tail of work already in flight, and the review that has not happened yet is exactly where it gets judged. Hold it: keep the UDE in the tree with `evidence` naming the unreviewed delivery it came from, do NOT anchor a remediation delivery for it, and say in your audit summary that it is held pending that review. Anchoring a sibling removes the floor the review gate provides -- the focus re-opens on new work while the pass that produced it is never judged.',
|
|
532
|
+
'- **A genuinely NEW root cause is still anchored.** The hold is a presumption, not a verdict on your judgement. While the focus carries unreviewed work-bearing deliveries, `telora_product_delivery` action=create is refused (`unreviewed_residue_hold`, no row) unless you DECLARE the deviation: pass `allowUnreviewedResidue=true` AND `unreviewedResidueReason="<why this is a new root cause and not residue of that work>"`. Both, every time -- a bare flag with no reason is refused (`override_reason_required`).',
|
|
533
|
+
'- **Declare it, never work around it.** The reason is recorded durably on the delivery with its attribution, so anchoring ahead of the review is a traced act rather than a silent one. Do not restate the same cause under a new name to slip past the hold, and do not treat the override as the default path: an escape declares ONE deviation, not all of them -- it does not relax the injection-anchoring contract.',
|
|
534
|
+
'- **If that section says READ FAILED, the review state is UNKNOWN.** Treat every delivery on the focus as unreviewed and apply the hold. An unreadable review state is not evidence that nothing is unreviewed.',
|
|
535
|
+
];
|
|
175
536
|
/**
|
|
176
537
|
* Compose the audit assessor prompt for a given posture. The read-only and live
|
|
177
538
|
* postures differ ONLY in the posture section; the discipline (AUDIT_GUIDE_SHARED)
|
|
@@ -183,6 +544,8 @@ export function buildAuditPrompt(posture) {
|
|
|
183
544
|
...auditPostureSection(posture),
|
|
184
545
|
'',
|
|
185
546
|
AUDIT_GUIDE_SHARED,
|
|
547
|
+
...AUDIT_CRITERIA_FLOOR,
|
|
548
|
+
...AUDIT_UNREVIEWED_RESIDUE,
|
|
186
549
|
...AUDIT_SUMMARY_TAIL,
|
|
187
550
|
].join('\n');
|
|
188
551
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-prompt.js","sourceRoot":"","sources":["../../src/audit/audit-prompt.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,
|
|
1
|
+
{"version":3,"file":"audit-prompt.js","sourceRoot":"","sources":["../../src/audit/audit-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Injectable IO seams; each defaults to the real implementation. */
|
|
2
|
+
export interface ReviewCoverageShaDeps {
|
|
3
|
+
/** The focus's registered worktree path, or null when none is registered. */
|
|
4
|
+
worktreePathFor: (focusId: string) => string | null;
|
|
5
|
+
/** The focus's delivery merge commit shas (in any order). Throws when unreadable. */
|
|
6
|
+
listMergeShas: (focusId: string) => Promise<string[]>;
|
|
7
|
+
/** True iff `sha` is an ancestor of `tip` in `worktreePath`. False when unreadable. */
|
|
8
|
+
isAncestor: (worktreePath: string, sha: string, tip: string) => boolean;
|
|
9
|
+
/** True iff `sha` resolves to a commit in `worktreePath`. */
|
|
10
|
+
commitResolves: (worktreePath: string, sha: string) => boolean;
|
|
11
|
+
/** Persist the watermark and the covered set together. */
|
|
12
|
+
writeWatermark: (focusId: string, sha: string, coveredMergeShas?: readonly string[]) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The production wiring: the real worktree registry, the real delivery read,
|
|
16
|
+
* and REAL git for both ancestry questions.
|
|
17
|
+
*
|
|
18
|
+
* Exported so a seam test can spread it and replace only the parts that need
|
|
19
|
+
* a fixture (which focus, which deliveries, where the write lands) while the
|
|
20
|
+
* ancestry itself still runs through the same `git merge-base --is-ancestor`
|
|
21
|
+
* production uses. A test that re-implemented those two calls would pass
|
|
22
|
+
* whether or not production's ones work.
|
|
23
|
+
*/
|
|
24
|
+
export declare const defaultReviewCoverageShaDeps: ReviewCoverageShaDeps;
|
|
25
|
+
/**
|
|
26
|
+
* The delivery merge commits `watermark` covers: each one git proves is an
|
|
27
|
+
* ANCESTOR of it in the focus worktree. Returns null when the question could
|
|
28
|
+
* not be asked at all (no worktree, an unresolvable watermark, an unreadable
|
|
29
|
+
* delivery list) -- null means "unknown", which the caller sends as "do not
|
|
30
|
+
* change the stored set", NOT as "nothing is covered".
|
|
31
|
+
*
|
|
32
|
+
* Ancestry per delivery rather than one walk of a range, for the same reason
|
|
33
|
+
* `resolvers/focus-review-coverage.ts` does it: the range's base is not a fact
|
|
34
|
+
* this module owns, and a delivery merged before that base moved would be
|
|
35
|
+
* missed by a range walk.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveCoveredMergeShas(focusId: string, watermark: string, deps?: ReviewCoverageShaDeps): Promise<string[] | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Stamp the review coverage watermark AND the merge commits it covers.
|
|
40
|
+
*
|
|
41
|
+
* This is the production binding of the review exit's `setReviewedThroughSha`
|
|
42
|
+
* dependency: the exit phase still asks for one thing ("record that this
|
|
43
|
+
* review covered this commit"), and recording it honestly means recording the
|
|
44
|
+
* range, because a watermark alone is what held the earlier deliveries. A
|
|
45
|
+
* resolution failure degrades to the watermark-only write rather than failing
|
|
46
|
+
* the stamp.
|
|
47
|
+
*/
|
|
48
|
+
export declare function stampReviewCoverage(focusId: string, sha: string, deps?: ReviewCoverageShaDeps): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=review-coverage-shas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-coverage-shas.d.ts","sourceRoot":"","sources":["../../src/completion/review-coverage-shas.ts"],"names":[],"mappings":"AA4CA,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACpD,qFAAqF;IACrF,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,uFAAuF;IACvF,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxE,6DAA6D;IAC7D,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/D,0DAA0D;IAC1D,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvG;AAkBD;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,EAAE,qBAU1C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,qBAAoD,GACzD,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAa1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,qBAAoD,GACzD,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
|
|
2
|
+
// Pinned by: packages/daemon/src/completion/review-coverage-seam.test.ts,
|
|
3
|
+
// packages/daemon/src/completion/review-coverage-shas.test.ts
|
|
4
|
+
// PINNED-BY-END
|
|
5
|
+
/**
|
|
6
|
+
* Resolve WHICH delivery merge commits a review pass covered, and stamp them
|
|
7
|
+
* with the watermark they belong to.
|
|
8
|
+
*
|
|
9
|
+
* WHY THIS EXISTS (Bug TEL-10). Coverage is a RANGE. The review-exit stamp
|
|
10
|
+
* records its tip (`product_focuses.reviewed_through_sha`), and the daemon can
|
|
11
|
+
* always re-derive the rest -- it owns the repo. The product-api create gate
|
|
12
|
+
* cannot: the edge runtime has no repository, so asked "is this delivery's
|
|
13
|
+
* merge commit inside the reviewed range?" it could only compare against the
|
|
14
|
+
* tip itself. Every delivery that merged EARLIER in that same range came back
|
|
15
|
+
* 'unreviewed' and held the create -- and no later event could ever clear it,
|
|
16
|
+
* because a subsequent review moves the watermark FORWARD, never onto the
|
|
17
|
+
* earlier merge commit. A hold nothing can discharge is a freeze.
|
|
18
|
+
*
|
|
19
|
+
* So the side that can answer writes the answer down. This module resolves the
|
|
20
|
+
* ancestry once, at the moment the watermark is stamped, and sends both in one
|
|
21
|
+
* write. It is the same relation `resolvers/focus-review-coverage.ts` resolves
|
|
22
|
+
* live for the audit prompt (`git merge-base --is-ancestor`), and deliberately
|
|
23
|
+
* the same one: the gate must enforce the state the scoping pass was shown.
|
|
24
|
+
*
|
|
25
|
+
* FAILS CLOSED IN EVERY DIRECTION. No worktree, an unresolvable watermark, an
|
|
26
|
+
* unreadable delivery list, a git failure -- each yields a SMALLER covered set
|
|
27
|
+
* (at worst an empty one), and a smaller set can only hold MORE deliveries.
|
|
28
|
+
* The watermark write itself is never blocked by a resolution failure: the
|
|
29
|
+
* coverage record is an improvement on the hold, not a precondition for
|
|
30
|
+
* recording that the review happened.
|
|
31
|
+
*
|
|
32
|
+
* @module completion/review-coverage-shas
|
|
33
|
+
*/
|
|
34
|
+
import { execFileSync } from 'node:child_process';
|
|
35
|
+
import { getFocusWorktree } from '../focus/focus-worktree-state.js';
|
|
36
|
+
import { getFocusDeliveries } from '../queries/focuses.js';
|
|
37
|
+
import { setReviewedThroughSha } from '../queries/focus-review-watermark.js';
|
|
38
|
+
import { createLogger } from '../shell/log.js';
|
|
39
|
+
const log = createLogger({ module: 'focus-executor' });
|
|
40
|
+
const GIT_OPTS = {
|
|
41
|
+
maxBuffer: 1024 * 1024,
|
|
42
|
+
encoding: 'utf-8',
|
|
43
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
44
|
+
};
|
|
45
|
+
/** Whether a git command exits 0 in `cwd`. A throw is a NO, never a yes. */
|
|
46
|
+
function gitSucceeds(args, cwd) {
|
|
47
|
+
try {
|
|
48
|
+
execFileSync('git', args, { ...GIT_OPTS, cwd });
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The production wiring: the real worktree registry, the real delivery read,
|
|
57
|
+
* and REAL git for both ancestry questions.
|
|
58
|
+
*
|
|
59
|
+
* Exported so a seam test can spread it and replace only the parts that need
|
|
60
|
+
* a fixture (which focus, which deliveries, where the write lands) while the
|
|
61
|
+
* ancestry itself still runs through the same `git merge-base --is-ancestor`
|
|
62
|
+
* production uses. A test that re-implemented those two calls would pass
|
|
63
|
+
* whether or not production's ones work.
|
|
64
|
+
*/
|
|
65
|
+
export const defaultReviewCoverageShaDeps = {
|
|
66
|
+
worktreePathFor: (focusId) => getFocusWorktree(focusId)?.worktreePath ?? null,
|
|
67
|
+
listMergeShas: async (focusId) => (await getFocusDeliveries(focusId))
|
|
68
|
+
.map((d) => (typeof d.mergeCommitSha === 'string' ? d.mergeCommitSha.trim() : ''))
|
|
69
|
+
.filter((sha) => sha !== ''),
|
|
70
|
+
isAncestor: (worktreePath, sha, tip) => gitSucceeds(['merge-base', '--is-ancestor', sha, tip], worktreePath),
|
|
71
|
+
commitResolves: (worktreePath, sha) => gitSucceeds(['rev-parse', '--verify', '--quiet', `${sha}^{commit}`], worktreePath),
|
|
72
|
+
writeWatermark: setReviewedThroughSha,
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The delivery merge commits `watermark` covers: each one git proves is an
|
|
76
|
+
* ANCESTOR of it in the focus worktree. Returns null when the question could
|
|
77
|
+
* not be asked at all (no worktree, an unresolvable watermark, an unreadable
|
|
78
|
+
* delivery list) -- null means "unknown", which the caller sends as "do not
|
|
79
|
+
* change the stored set", NOT as "nothing is covered".
|
|
80
|
+
*
|
|
81
|
+
* Ancestry per delivery rather than one walk of a range, for the same reason
|
|
82
|
+
* `resolvers/focus-review-coverage.ts` does it: the range's base is not a fact
|
|
83
|
+
* this module owns, and a delivery merged before that base moved would be
|
|
84
|
+
* missed by a range walk.
|
|
85
|
+
*/
|
|
86
|
+
export async function resolveCoveredMergeShas(focusId, watermark, deps = defaultReviewCoverageShaDeps) {
|
|
87
|
+
const tip = watermark.trim();
|
|
88
|
+
if (tip === '')
|
|
89
|
+
return null;
|
|
90
|
+
const worktreePath = deps.worktreePathFor(focusId);
|
|
91
|
+
if (!worktreePath)
|
|
92
|
+
return null;
|
|
93
|
+
if (!deps.commitResolves(worktreePath, tip))
|
|
94
|
+
return null;
|
|
95
|
+
let mergeShas;
|
|
96
|
+
try {
|
|
97
|
+
mergeShas = await deps.listMergeShas(focusId);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return mergeShas.filter((sha) => deps.isAncestor(worktreePath, sha, tip));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Stamp the review coverage watermark AND the merge commits it covers.
|
|
106
|
+
*
|
|
107
|
+
* This is the production binding of the review exit's `setReviewedThroughSha`
|
|
108
|
+
* dependency: the exit phase still asks for one thing ("record that this
|
|
109
|
+
* review covered this commit"), and recording it honestly means recording the
|
|
110
|
+
* range, because a watermark alone is what held the earlier deliveries. A
|
|
111
|
+
* resolution failure degrades to the watermark-only write rather than failing
|
|
112
|
+
* the stamp.
|
|
113
|
+
*/
|
|
114
|
+
export async function stampReviewCoverage(focusId, sha, deps = defaultReviewCoverageShaDeps) {
|
|
115
|
+
let covered = null;
|
|
116
|
+
try {
|
|
117
|
+
covered = await resolveCoveredMergeShas(focusId, sha, deps);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
log.warn(`[focus-executor] Review coverage range unresolved for focus ${focusId}: ${err.message}`);
|
|
121
|
+
}
|
|
122
|
+
if (covered === null) {
|
|
123
|
+
await deps.writeWatermark(focusId, sha);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
await deps.writeWatermark(focusId, sha, covered);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=review-coverage-shas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-coverage-shas.js","sourceRoot":"","sources":["../../src/completion/review-coverage-shas.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ import { type ReviewWindowCommit } from '../resolvers/shared/review-window-commi
|
|
|
15
15
|
import { getActiveFocuses } from '../queries/focus-discovery.js';
|
|
16
16
|
import { hasPendingSpawnDirective } from '../directive/directive-queue.js';
|
|
17
17
|
import { emitLoopTrigger } from '../loops/index.js';
|
|
18
|
-
import { getFocusDeliveries, getFocusIssues, clearReviewRequestedAt,
|
|
18
|
+
import { getFocusDeliveries, getFocusIssues, clearReviewRequestedAt, setReviewCycleCount, setReviewHandoffCount, getFocusReviewReportForSession, getFocusReviewFiledIssueIds } from '../queries/focuses.js';
|
|
19
19
|
import { resolveReviewCycleCap, resolveReviewHandoffCap } from '../verify/stall-detector-config.js';
|
|
20
20
|
import { getDeliveryIssues, rehomeIssueToDelivery } from '../queries/issues.js';
|
|
21
21
|
import { createEscalation, hasOpenFocusEscalation, hasOpenEscalationForDelivery } from '../queries/escalations.js';
|
|
@@ -41,7 +41,20 @@ export interface ReviewExitDeps {
|
|
|
41
41
|
clearReviewRequestedAt: typeof clearReviewRequestedAt;
|
|
42
42
|
fileReworkForFailedVerdict?: (focusId: string, verdict: FailedGateVerdict) => Promise<number>;
|
|
43
43
|
clearPendingReviewDirective?: (focusId: string) => boolean;
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Record that this review pass covered a commit. The PRODUCTION binding is
|
|
46
|
+
* `stampReviewCoverage` (review-coverage-shas.ts), not the bare query: it
|
|
47
|
+
* writes the watermark AND the delivery merge commits git proves that commit
|
|
48
|
+
* covers, in one call.
|
|
49
|
+
*
|
|
50
|
+
* Declared at the ARITY THE PHASE USES (focusId, sha) rather than as
|
|
51
|
+
* `typeof setReviewedThroughSha`: what the exit knows is "this review covered
|
|
52
|
+
* this commit", and how much of the range the binding manages to record with
|
|
53
|
+
* it is the binding's business, not a decision the routing tree makes. Both
|
|
54
|
+
* the bare query and the coverage stamp satisfy it, as does a two-argument
|
|
55
|
+
* test stub.
|
|
56
|
+
*/
|
|
57
|
+
setReviewedThroughSha: (focusId: string, sha: string) => Promise<void>;
|
|
45
58
|
setReviewCycleCount?: typeof setReviewCycleCount;
|
|
46
59
|
resolveReviewCycleCap?: typeof resolveReviewCycleCap;
|
|
47
60
|
setReviewHandoffCount?: typeof setReviewHandoffCount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-exit-deps.d.ts","sourceRoot":"","sources":["../../src/completion/review-exit-deps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"review-exit-deps.d.ts","sourceRoot":"","sources":["../../src/completion/review-exit-deps.ts"],"names":[],"mappings":"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"}
|