@telora/daemon 0.20.19 → 0.20.28

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.
Files changed (107) hide show
  1. package/build-info.json +4 -3
  2. package/dist/audit-phase.d.ts +43 -6
  3. package/dist/audit-phase.d.ts.map +1 -1
  4. package/dist/audit-phase.js +124 -23
  5. package/dist/audit-phase.js.map +1 -1
  6. package/dist/cascade-restatement.d.ts +13 -147
  7. package/dist/cascade-restatement.d.ts.map +1 -1
  8. package/dist/cascade-restatement.js +13 -429
  9. package/dist/cascade-restatement.js.map +1 -1
  10. package/dist/cli/session-state.d.ts.map +1 -1
  11. package/dist/cli/session-state.js +6 -1
  12. package/dist/cli/session-state.js.map +1 -1
  13. package/dist/focus-engine.d.ts.map +1 -1
  14. package/dist/focus-engine.js +15 -0
  15. package/dist/focus-engine.js.map +1 -1
  16. package/dist/focus-loop-registry.d.ts.map +1 -1
  17. package/dist/focus-loop-registry.js +16 -90
  18. package/dist/focus-loop-registry.js.map +1 -1
  19. package/dist/focus-loop.d.ts +0 -2
  20. package/dist/focus-loop.d.ts.map +1 -1
  21. package/dist/focus-loop.js +33 -25
  22. package/dist/focus-loop.js.map +1 -1
  23. package/dist/focus-phase.d.ts +26 -0
  24. package/dist/focus-phase.d.ts.map +1 -1
  25. package/dist/focus-phase.js +38 -0
  26. package/dist/focus-phase.js.map +1 -1
  27. package/dist/listener.d.ts.map +1 -1
  28. package/dist/listener.js +40 -9
  29. package/dist/listener.js.map +1 -1
  30. package/dist/loops/llm-client.d.ts.map +1 -1
  31. package/dist/loops/llm-client.js +17 -4
  32. package/dist/loops/llm-client.js.map +1 -1
  33. package/dist/queries/audit-runs.d.ts +56 -2
  34. package/dist/queries/audit-runs.d.ts.map +1 -1
  35. package/dist/queries/audit-runs.js +40 -0
  36. package/dist/queries/audit-runs.js.map +1 -1
  37. package/dist/queries/deliveries.d.ts +27 -0
  38. package/dist/queries/deliveries.d.ts.map +1 -1
  39. package/dist/queries/deliveries.js.map +1 -1
  40. package/dist/queries/focuses.d.ts +0 -9
  41. package/dist/queries/focuses.d.ts.map +1 -1
  42. package/dist/queries/focuses.js +0 -14
  43. package/dist/queries/focuses.js.map +1 -1
  44. package/dist/resolvers/index.d.ts +1 -1
  45. package/dist/resolvers/index.d.ts.map +1 -1
  46. package/dist/resolvers/index.js +1 -1
  47. package/dist/resolvers/index.js.map +1 -1
  48. package/dist/resolvers/shared/audit.d.ts +5 -0
  49. package/dist/resolvers/shared/audit.d.ts.map +1 -1
  50. package/dist/resolvers/shared/audit.js +8 -3
  51. package/dist/resolvers/shared/audit.js.map +1 -1
  52. package/dist/resolvers/shared/git-diff.d.ts +13 -0
  53. package/dist/resolvers/shared/git-diff.d.ts.map +1 -1
  54. package/dist/resolvers/shared/git-diff.js +30 -0
  55. package/dist/resolvers/shared/git-diff.js.map +1 -1
  56. package/dist/spawn/review-role-fallback.d.ts +74 -0
  57. package/dist/spawn/review-role-fallback.d.ts.map +1 -0
  58. package/dist/spawn/review-role-fallback.js +62 -0
  59. package/dist/spawn/review-role-fallback.js.map +1 -0
  60. package/dist/unified-shell-status.d.ts.map +1 -1
  61. package/dist/unified-shell-status.js +5 -1
  62. package/dist/unified-shell-status.js.map +1 -1
  63. package/dist/verification-config.d.ts +64 -15
  64. package/dist/verification-config.d.ts.map +1 -1
  65. package/dist/verification-config.js +66 -21
  66. package/dist/verification-config.js.map +1 -1
  67. package/dist/verification-default-on.d.ts +73 -1
  68. package/dist/verification-default-on.d.ts.map +1 -1
  69. package/dist/verification-default-on.js +79 -0
  70. package/dist/verification-default-on.js.map +1 -1
  71. package/dist/verification-engine.d.ts +16 -2
  72. package/dist/verification-engine.d.ts.map +1 -1
  73. package/dist/verification-engine.js +168 -84
  74. package/dist/verification-engine.js.map +1 -1
  75. package/dist/verification-feedback.d.ts +26 -1
  76. package/dist/verification-feedback.d.ts.map +1 -1
  77. package/dist/verification-feedback.js +82 -0
  78. package/dist/verification-feedback.js.map +1 -1
  79. package/dist/verification-manifest.d.ts +110 -0
  80. package/dist/verification-manifest.d.ts.map +1 -0
  81. package/dist/verification-manifest.js +150 -0
  82. package/dist/verification-manifest.js.map +1 -0
  83. package/dist/verify-reconciliation.d.ts +16 -1
  84. package/dist/verify-reconciliation.d.ts.map +1 -1
  85. package/dist/verify-reconciliation.js +18 -2
  86. package/dist/verify-reconciliation.js.map +1 -1
  87. package/dist/verify-restatement.d.ts +7 -0
  88. package/dist/verify-restatement.d.ts.map +1 -1
  89. package/dist/verify-restatement.js +1 -0
  90. package/dist/verify-restatement.js.map +1 -1
  91. package/package.json +2 -2
  92. package/dist/drift-ratify-loop.d.ts +0 -68
  93. package/dist/drift-ratify-loop.d.ts.map +0 -1
  94. package/dist/drift-ratify-loop.js +0 -161
  95. package/dist/drift-ratify-loop.js.map +0 -1
  96. package/dist/negative-branch.d.ts +0 -136
  97. package/dist/negative-branch.d.ts.map +0 -1
  98. package/dist/negative-branch.js +0 -241
  99. package/dist/negative-branch.js.map +0 -1
  100. package/dist/shortfall-disposition-config.d.ts +0 -34
  101. package/dist/shortfall-disposition-config.d.ts.map +0 -1
  102. package/dist/shortfall-disposition-config.js +0 -46
  103. package/dist/shortfall-disposition-config.js.map +0 -1
  104. package/dist/shortfall-disposition-loop.d.ts +0 -86
  105. package/dist/shortfall-disposition-loop.d.ts.map +0 -1
  106. package/dist/shortfall-disposition-loop.js +0 -309
  107. package/dist/shortfall-disposition-loop.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/resolvers/shared/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUrF"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/resolvers/shared/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOrF"}
@@ -8,18 +8,23 @@
8
8
  * If no prior audit exists or the lookup fails, the resolvers fall back
9
9
  * to "all since focus start" (no lower bound).
10
10
  */
11
- import { callApi } from '../../queries/shared.js';
11
+ import { getRecentAuditRun } from '../../queries/audit-runs.js';
12
12
  /**
13
13
  * Best-effort cycle window. Returns the previous cycle's completed_at as
14
14
  * the lower bound for "things that happened in the current cycle". Null
15
15
  * means "no prior cycle, include everything since focus start". Failures
16
16
  * fall back to null so a missing audit_runs table or transient API error
17
17
  * does not blank out the resolver output.
18
+ *
19
+ * The snake_case -> camelCase transform lives in getRecentAuditRun (the API
20
+ * returns the Supabase row verbatim -- neither successResponse nor callApi
21
+ * maps keys). Reading `completedAt` off the raw response here always yielded
22
+ * undefined, so this window silently never narrowed.
18
23
  */
19
24
  export async function getAuditCycleLowerBound(focusId) {
20
25
  try {
21
- const result = await callApi('daemon_get_recent_audit_run_for_focus', { focusId });
22
- return result.auditRun?.completedAt ?? null;
26
+ const run = await getRecentAuditRun(focusId);
27
+ return run?.completedAt ?? null;
23
28
  }
24
29
  catch {
25
30
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/resolvers/shared/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AASlD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAAe;IAC3D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,uCAAuC,EACvC,EAAE,OAAO,EAAE,CACZ,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,EAAE,WAAW,IAAI,IAAI,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/resolvers/shared/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAAe;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,GAAG,EAAE,WAAW,IAAI,IAAI,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -11,4 +11,17 @@ export declare function getGitDiff(worktreePath: string, baseBranch: string): st
11
11
  * Get a summary of files changed in a diff (for truncation header).
12
12
  */
13
13
  export declare function getDiffStatSummary(worktreePath: string, baseBranch: string): string;
14
+ /**
15
+ * List the files changed between the base branch and HEAD (name-only).
16
+ * Returns an empty array on failure (missing worktree / bad range).
17
+ */
18
+ export declare function getChangedFiles(worktreePath: string, baseBranch: string): string[];
19
+ /**
20
+ * Count commits on HEAD that are not reachable from the base branch
21
+ * (`git rev-list --count base..HEAD`). This is the delivery's own commit
22
+ * count relative to the integration base -- distinct from the diff, which
23
+ * can be empty even when commits exist if it is resolved in the wrong
24
+ * worktree. Returns 0 on failure so callers treat "unknown" as "no commits".
25
+ */
26
+ export declare function getCommitsAhead(worktreePath: string, baseBranch: string): number;
14
27
  //# 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,CAU3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CASnF"}
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,CAU3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CASnF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAUlF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWhF"}
@@ -27,4 +27,34 @@ export function getDiffStatSummary(worktreePath, baseBranch) {
27
27
  return '';
28
28
  }
29
29
  }
30
+ /**
31
+ * List the files changed between the base branch and HEAD (name-only).
32
+ * Returns an empty array on failure (missing worktree / bad range).
33
+ */
34
+ export function getChangedFiles(worktreePath, baseBranch) {
35
+ try {
36
+ const out = execSync(`git diff --name-only ${baseBranch}...HEAD`, { cwd: worktreePath, maxBuffer: 1024 * 1024, encoding: 'utf-8' });
37
+ return out.split('\n').map((l) => l.trim()).filter((l) => l !== '');
38
+ }
39
+ catch {
40
+ return [];
41
+ }
42
+ }
43
+ /**
44
+ * Count commits on HEAD that are not reachable from the base branch
45
+ * (`git rev-list --count base..HEAD`). This is the delivery's own commit
46
+ * count relative to the integration base -- distinct from the diff, which
47
+ * can be empty even when commits exist if it is resolved in the wrong
48
+ * worktree. Returns 0 on failure so callers treat "unknown" as "no commits".
49
+ */
50
+ export function getCommitsAhead(worktreePath, baseBranch) {
51
+ try {
52
+ const out = execSync(`git rev-list --count ${baseBranch}..HEAD`, { cwd: worktreePath, maxBuffer: 1024 * 1024, encoding: 'utf-8' });
53
+ const n = Number.parseInt(out.trim(), 10);
54
+ return Number.isFinite(n) && n > 0 ? n : 0;
55
+ }
56
+ catch {
57
+ return 0;
58
+ }
59
+ }
30
60
  //# 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;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB,EAAE,UAAkB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CACnB,YAAY,UAAU,SAAS,EAC/B,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;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAoB,EAAE,UAAkB;IACzE,IAAI,CAAC;QACH,OAAO,QAAQ,CACb,mBAAmB,UAAU,SAAS,EACtC,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"}
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;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB,EAAE,UAAkB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CACnB,YAAY,UAAU,SAAS,EAC/B,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;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,YAAoB,EAAE,UAAkB;IACzE,IAAI,CAAC;QACH,OAAO,QAAQ,CACb,mBAAmB,UAAU,SAAS,EACtC,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;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,UAAkB;IACtE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAClB,wBAAwB,UAAU,SAAS,EAC3C,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;;;;;;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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Review-spawn reviewer-role fallback.
3
+ *
4
+ * When a coding team completes, the auto_terminate_focus_team() Postgres trigger
5
+ * nulls product_focuses.assigned_agent_role_id -- correct team-lifecycle
6
+ * shutdown (the Play/queue toggle cleared). But a review is a SECOND team that
7
+ * must spawn AFTER that completion, and the pending review directive it left
8
+ * behind still needs a role to spawn under. With assigned_agent_role_id null,
9
+ * the listener's pending-spawn path used to skip the queued review directive
10
+ * every poll, and the directive-executor suppressed re-firing (an equivalent
11
+ * directive is "already queued") -- a review that can never spawn, spin-logging
12
+ * until review_window_stalled escalates to a human at ~6h.
13
+ *
14
+ * This module holds the prevent-at-source decision: for a REVIEW directive with
15
+ * a null role, resolve a layered reviewer-role fallback (the org's seeded
16
+ * Developer role) and spawn. It mirrors nexus intake's resolveIntakeRoleLayered
17
+ * (the org's seeded 'Developer' role is the zero-config fallback). The fallback
18
+ * is scoped STRICTLY to review spawns: a null role on a CODING spawn is the
19
+ * intended off-state and must NOT auto-spawn. Defense-in-depth: if even the
20
+ * fallback resolves nothing, the caller clears the pending directive so it stops
21
+ * spin-logging and lets the stall detector escalate promptly.
22
+ */
23
+ import type { AgentRole } from '../types/session.js';
24
+ /**
25
+ * Name of the org's auto-seeded, full-codebase agent role used as the reviewer
26
+ * fallback. Every organization gets one on creation (migration
27
+ * seed_default_agent_roles: 'Developer'). Mirrors nexus intake's
28
+ * DEFAULT_INTAKE_ROLE_NAME so review-spawn and intake-spawn share the same
29
+ * zero-config fallback identity.
30
+ */
31
+ export declare const DEFAULT_REVIEWER_ROLE_NAME = "Developer";
32
+ /**
33
+ * What to do with a pending spawn directive whose focus has a null
34
+ * assigned_agent_role_id.
35
+ *
36
+ * - skip: a CODING directive (or no directive) -- the intended off-state
37
+ * (Play/queue toggle cleared). Never auto-spawn.
38
+ * - spawn: a REVIEW directive with a resolved fallback role -- spawn the
39
+ * review team under it.
40
+ * - clear: a REVIEW directive with NO resolvable fallback role -- drop the
41
+ * directive so the stranded-review re-fire suppression cannot spin
42
+ * forever; review_window_stalled remains the escalation path.
43
+ */
44
+ export type NullRoleSpawnDecision = {
45
+ action: 'skip';
46
+ } | {
47
+ action: 'spawn';
48
+ role: AgentRole;
49
+ } | {
50
+ action: 'clear';
51
+ };
52
+ /**
53
+ * Resolve the org's seeded Developer role from an already-loaded roles
54
+ * collection (the listener keeps every org agent role in memory). Returns the
55
+ * first role named DEFAULT_REVIEWER_ROLE_NAME, or undefined when the org has no
56
+ * seeded Developer role (the degenerate case the 'clear' decision handles).
57
+ *
58
+ * Pure and exported for unit testing.
59
+ */
60
+ export declare function resolveReviewerFallbackRole(roles: Iterable<AgentRole>): AgentRole | undefined;
61
+ /**
62
+ * Decide what to do with a null-role pending spawn directive.
63
+ *
64
+ * The layered fallback applies ONLY to review directives; a coding directive
65
+ * with a null role is the intended off-state and is always skipped. A review
66
+ * directive spawns under the fallback role when one resolves, else clears.
67
+ *
68
+ * Pure and exported for unit testing (peer of resolveReviewerFallbackRole).
69
+ */
70
+ export declare function decideNullRoleSpawn(input: {
71
+ sessionType: 'coding' | 'review' | undefined;
72
+ fallbackRole: AgentRole | undefined;
73
+ }): NullRoleSpawnDecision;
74
+ //# sourceMappingURL=review-role-fallback.d.ts.map
@@ -0,0 +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;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC7C,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;CACrC,GAAG,qBAAqB,CAIxB"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Review-spawn reviewer-role fallback.
3
+ *
4
+ * When a coding team completes, the auto_terminate_focus_team() Postgres trigger
5
+ * nulls product_focuses.assigned_agent_role_id -- correct team-lifecycle
6
+ * shutdown (the Play/queue toggle cleared). But a review is a SECOND team that
7
+ * must spawn AFTER that completion, and the pending review directive it left
8
+ * behind still needs a role to spawn under. With assigned_agent_role_id null,
9
+ * the listener's pending-spawn path used to skip the queued review directive
10
+ * every poll, and the directive-executor suppressed re-firing (an equivalent
11
+ * directive is "already queued") -- a review that can never spawn, spin-logging
12
+ * until review_window_stalled escalates to a human at ~6h.
13
+ *
14
+ * This module holds the prevent-at-source decision: for a REVIEW directive with
15
+ * a null role, resolve a layered reviewer-role fallback (the org's seeded
16
+ * Developer role) and spawn. It mirrors nexus intake's resolveIntakeRoleLayered
17
+ * (the org's seeded 'Developer' role is the zero-config fallback). The fallback
18
+ * is scoped STRICTLY to review spawns: a null role on a CODING spawn is the
19
+ * intended off-state and must NOT auto-spawn. Defense-in-depth: if even the
20
+ * fallback resolves nothing, the caller clears the pending directive so it stops
21
+ * spin-logging and lets the stall detector escalate promptly.
22
+ */
23
+ /**
24
+ * Name of the org's auto-seeded, full-codebase agent role used as the reviewer
25
+ * fallback. Every organization gets one on creation (migration
26
+ * seed_default_agent_roles: 'Developer'). Mirrors nexus intake's
27
+ * DEFAULT_INTAKE_ROLE_NAME so review-spawn and intake-spawn share the same
28
+ * zero-config fallback identity.
29
+ */
30
+ export const DEFAULT_REVIEWER_ROLE_NAME = 'Developer';
31
+ /**
32
+ * Resolve the org's seeded Developer role from an already-loaded roles
33
+ * collection (the listener keeps every org agent role in memory). Returns the
34
+ * first role named DEFAULT_REVIEWER_ROLE_NAME, or undefined when the org has no
35
+ * seeded Developer role (the degenerate case the 'clear' decision handles).
36
+ *
37
+ * Pure and exported for unit testing.
38
+ */
39
+ export function resolveReviewerFallbackRole(roles) {
40
+ for (const role of roles) {
41
+ if (role.name === DEFAULT_REVIEWER_ROLE_NAME)
42
+ return role;
43
+ }
44
+ return undefined;
45
+ }
46
+ /**
47
+ * Decide what to do with a null-role pending spawn directive.
48
+ *
49
+ * The layered fallback applies ONLY to review directives; a coding directive
50
+ * with a null role is the intended off-state and is always skipped. A review
51
+ * directive spawns under the fallback role when one resolves, else clears.
52
+ *
53
+ * Pure and exported for unit testing (peer of resolveReviewerFallbackRole).
54
+ */
55
+ export function decideNullRoleSpawn(input) {
56
+ if (input.sessionType !== 'review')
57
+ return { action: 'skip' };
58
+ if (input.fallbackRole)
59
+ return { action: 'spawn', role: input.fallbackRole };
60
+ return { action: 'clear' };
61
+ }
62
+ //# sourceMappingURL=review-role-fallback.js.map
@@ -0,0 +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;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAGnC;IACC,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"unified-shell-status.d.ts","sourceRoot":"","sources":["../src/unified-shell-status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAU5F;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAmBV;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,IAAI,CA8DnG;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CA6BrE"}
1
+ {"version":3,"file":"unified-shell-status.d.ts","sourceRoot":"","sources":["../src/unified-shell-status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAU5F;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,aAAa,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAuBV;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,IAAI,CA8DnG;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CA6BrE"}
@@ -23,7 +23,11 @@ export function formatVerificationPostureLines(config, env = process.env) {
23
23
  const { defaultVerification, products } = resolveVerificationCarriage(config.rawFileConfig, config.base.products ?? []);
24
24
  return products.map((p) => {
25
25
  // Per-product override wins; else the global block (mirrors configForProduct).
26
- const scoped = { defaultVerification: p.defaultVerification ?? defaultVerification };
26
+ // repoPath carries the repo-committed telora.verify.json layer below both.
27
+ const scoped = {
28
+ defaultVerification: p.defaultVerification ?? defaultVerification,
29
+ repoPath: p.repoPath,
30
+ };
27
31
  const posture = deriveVerificationPosture(scoped, env);
28
32
  const label = productLabel(p);
29
33
  if (posture === 'configured') {
@@ -1 +1 @@
1
- {"version":3,"file":"unified-shell-status.js","sourceRoot":"","sources":["../src/unified-shell-status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unified-shell-status.js","sourceRoot":"","sources":["../src/unified-shell-status.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,21 @@
6
6
  * it the DEFAULT for every delivery entering verify, using a config-default
7
7
  * command run daemon-side at the coding->verify edge.
8
8
  *
9
- * Resolution precedence (env > file > typed default), mirroring how
10
- * resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
11
- * - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > '' (disabled)
12
- * - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > 30 min
13
- * - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > 1
9
+ * Resolution precedence (env > operator file > repo manifest > typed default),
10
+ * mirroring how resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
11
+ * - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > telora.verify.json > '' (disabled)
12
+ * - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > telora.verify.json > 30 min
13
+ * - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > telora.verify.json > 1
14
+ *
15
+ * The repo-manifest layer (`telora.verify.json`, see verification-manifest.ts)
16
+ * is what lets a REPO declare its own gate: the two layers above it are both
17
+ * per-workstation and untracked (`.gitignore:72` ignores `.telora/` wholesale;
18
+ * cli/verify-setup.ts:218 writes to ~/.telora/daemon.json), so without it no PR
19
+ * could arm the gate and a fresh clone was ungated by construction.
20
+ *
21
+ * The seam stays OPT-IN: a repo shipping no manifest still resolves to ''
22
+ * (disabled). No default command is ever hard-coded here -- the daemon manages
23
+ * products that have no whole-repo verification command at all.
14
24
  *
15
25
  * The env knobs are read directly from `process.env` here rather than through
16
26
  * daemon-core's env-config Zod index: daemon-core is a registry-installed
@@ -21,6 +31,7 @@
21
31
  * @module verification-config
22
32
  */
23
33
  import type { DaemonConfig, DefaultVerificationConfig } from './types.js';
34
+ import { type VerifyManifestReader } from './verification-manifest.js';
24
35
  /** Default timeout for the default-on deterministic run: 30 min (full build+test sweep). */
25
36
  export declare const DEFAULT_VERIFY_TIMEOUT_MS: number;
26
37
  /** Default max concurrent daemon-side verification runs. */
@@ -43,17 +54,52 @@ export interface ResolvedDefaultVerification {
43
54
  enabled: boolean;
44
55
  }
45
56
  /**
46
- * Resolve the default-on verification config from env > file(config) > default.
57
+ * The config slice these resolvers need: the (already per-product-selected)
58
+ * verification block, plus the product's repo root so the repo-manifest layer
59
+ * can be read.
60
+ *
61
+ * `repoPath` is OPTIONAL rather than picked from DaemonConfig (where it is
62
+ * required) so that callers holding only a scoped `{ defaultVerification }`
63
+ * still typecheck; a missing repoPath simply means "no repo manifest layer".
64
+ * A product-scoped config always carries it -- `configForProduct`
65
+ * (config.ts:351) sets `repoPath` per product -- so the real daemon paths get
66
+ * the manifest layer for free.
67
+ */
68
+ export type VerificationConfigScope = Pick<DaemonConfig, 'defaultVerification'> & {
69
+ /** Product repo root; the manifest is read from `<repoPath>/telora.verify.json`. */
70
+ repoPath?: string;
71
+ };
72
+ /**
73
+ * Resolve the default-on verification config from
74
+ * env > operator file > repo manifest > typed default.
75
+ *
76
+ * Pure w.r.t. its inputs: env is injectable, and the repo-manifest read is
77
+ * injected via `readManifest` rather than touching fs inside this resolver, so
78
+ * the whole precedence chain is assertable without a real repo.
79
+ *
80
+ * Env values are parsed by daemon-core's loadEnvConfig, so an invalid numeric
81
+ * value fails loudly at daemon startup (naming the var) instead of silently
82
+ * degrading mid-tick. A malformed repo manifest fails the same way (naming the
83
+ * file) -- see verification-manifest.ts for why that is never degraded to
84
+ * "disabled".
85
+ *
86
+ * The manifest is read whenever a repoPath is present, regardless of which
87
+ * layer ultimately wins, so a broken repo declaration surfaces even on a
88
+ * workstation whose env/operator file happens to override it.
47
89
  *
48
- * Pure w.r.t. its inputs (env is injectable for tests). Env values are parsed
49
- * by daemon-core's loadEnvConfig, so an invalid numeric value fails loudly at
50
- * daemon startup (naming the var) instead of silently degrading mid-tick.
90
+ * One asymmetry worth naming: an operator's explicit `declined: true` marker
91
+ * SUPPRESSES the repo-manifest command. The marker is a recorded operator
92
+ * decision to gate on AI review only, and the operator file outranks the repo
93
+ * manifest -- so a repo declaring a command cannot silently overturn it. Env
94
+ * still wins over both (an explicit env command beats a stale decline marker,
95
+ * unchanged).
51
96
  */
52
- export declare function resolveDefaultVerification(config: Pick<DaemonConfig, 'defaultVerification'>, env?: NodeJS.ProcessEnv): ResolvedDefaultVerification;
97
+ export declare function resolveDefaultVerification(config: VerificationConfigScope, env?: NodeJS.ProcessEnv, readManifest?: VerifyManifestReader): ResolvedDefaultVerification;
53
98
  /**
54
99
  * Declarative verification posture, derived at read time from config (never a
55
100
  * filed event, so it cannot spam and self-clears once configured):
56
- * - `configured` -- a non-empty verification command resolves (env or file).
101
+ * - `configured` -- a non-empty verification command resolves (env, operator
102
+ * file, or the repo's committed `telora.verify.json`).
57
103
  * - `declined` -- no command resolves AND an explicit review-only decline
58
104
  * marker is recorded. Deliveries gate on AI review only,
59
105
  * by deliberate decision (not a gap).
@@ -68,13 +114,15 @@ export type VerificationPosture = 'configured' | 'declined' | 'unconfigured';
68
114
  * escalation/side-effect path -- posture is declarative state, surfaced on
69
115
  * ambient read surfaces, never a filed escalation. Callers pass a product-scoped
70
116
  * config (from `configForProduct`) so `config.defaultVerification` is already the
71
- * selected per-product-or-global block.
117
+ * selected per-product-or-global block and `repoPath` points at that product's
118
+ * repo -- which is what lets a repo-manifest-only command read `configured`.
72
119
  *
73
120
  * An explicitly resolved command wins over the decline marker: an operator who
74
121
  * sets a command (via env or file) has configured verification regardless of a
75
- * stale `declined` flag.
122
+ * stale `declined` flag. The marker still suppresses the repo manifest (the
123
+ * operator file outranks it), so `declined: true` keeps reading `declined`.
76
124
  */
77
- export declare function deriveVerificationPosture(config: Pick<DaemonConfig, 'defaultVerification'>, env?: NodeJS.ProcessEnv): VerificationPosture;
125
+ export declare function deriveVerificationPosture(config: VerificationConfigScope, env?: NodeJS.ProcessEnv, readManifest?: VerifyManifestReader): VerificationPosture;
78
126
  /** Structured posture for one product, published for app consumption. */
79
127
  export interface ProductVerificationPosture {
80
128
  posture: VerificationPosture;
@@ -92,6 +140,7 @@ export interface ProductVerificationPosture {
92
140
  */
93
141
  export declare function buildProductPostureMap(products: ReadonlyArray<{
94
142
  id: string;
143
+ repoPath?: string;
95
144
  defaultVerification?: DefaultVerificationConfig;
96
- }>, globalBlock: DefaultVerificationConfig | undefined, env?: NodeJS.ProcessEnv): Record<string, ProductVerificationPosture>;
145
+ }>, globalBlock: DefaultVerificationConfig | undefined, env?: NodeJS.ProcessEnv, readManifest?: VerifyManifestReader): Record<string, ProductVerificationPosture>;
97
146
  //# sourceMappingURL=verification-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verification-config.d.ts","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAG1E,4FAA4F;AAC5F,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAExD,4DAA4D;AAC5D,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,2DAA2D;AAC3D,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,EACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,2BAA2B,CA0B7B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,CAAC;AAE7E;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,EACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,mBAAmB,CAKrB;AAED,yEAAyE;AACzE,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,yBAAyB,CAAA;CAAE,CAAC,EACxF,WAAW,EAAE,yBAAyB,GAAG,SAAS,EAClD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAY5C"}
1
+ {"version":3,"file":"verification-config.d.ts","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAsB,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAE3F,4FAA4F;AAC5F,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAExD,4DAA4D;AAC5D,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,2DAA2D;AAC3D,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,GAAG;IAChF,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,uBAAuB,EAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,YAAY,GAAE,oBAAyC,GACtD,2BAA2B,CAmC7B;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,CAAC;AAE7E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,uBAAuB,EAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,YAAY,GAAE,oBAAyC,GACtD,mBAAmB,CAKrB;AAED,yEAAyE;AACzE,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,yBAAyB,CAAA;CAAE,CAAC,EAC3G,WAAW,EAAE,yBAAyB,GAAG,SAAS,EAClD,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,YAAY,GAAE,oBAAyC,GACtD,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAiB5C"}
@@ -6,11 +6,21 @@
6
6
  * it the DEFAULT for every delivery entering verify, using a config-default
7
7
  * command run daemon-side at the coding->verify edge.
8
8
  *
9
- * Resolution precedence (env > file > typed default), mirroring how
10
- * resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
11
- * - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > '' (disabled)
12
- * - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > 30 min
13
- * - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > 1
9
+ * Resolution precedence (env > operator file > repo manifest > typed default),
10
+ * mirroring how resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
11
+ * - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > telora.verify.json > '' (disabled)
12
+ * - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > telora.verify.json > 30 min
13
+ * - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > telora.verify.json > 1
14
+ *
15
+ * The repo-manifest layer (`telora.verify.json`, see verification-manifest.ts)
16
+ * is what lets a REPO declare its own gate: the two layers above it are both
17
+ * per-workstation and untracked (`.gitignore:72` ignores `.telora/` wholesale;
18
+ * cli/verify-setup.ts:218 writes to ~/.telora/daemon.json), so without it no PR
19
+ * could arm the gate and a fresh clone was ungated by construction.
20
+ *
21
+ * The seam stays OPT-IN: a repo shipping no manifest still resolves to ''
22
+ * (disabled). No default command is ever hard-coded here -- the daemon manages
23
+ * products that have no whole-repo verification command at all.
14
24
  *
15
25
  * The env knobs are read directly from `process.env` here rather than through
16
26
  * daemon-core's env-config Zod index: daemon-core is a registry-installed
@@ -21,6 +31,7 @@
21
31
  * @module verification-config
22
32
  */
23
33
  import { loadEnvConfig } from '@telora/daemon-core';
34
+ import { readVerifyManifest } from './verification-manifest.js';
24
35
  /** Default timeout for the default-on deterministic run: 30 min (full build+test sweep). */
25
36
  export const DEFAULT_VERIFY_TIMEOUT_MS = 30 * 60 * 1000;
26
37
  /** Default max concurrent daemon-side verification runs. */
@@ -32,24 +43,51 @@ export const VERIFY_ENV = {
32
43
  MAX_CONCURRENT: 'TELORA_DEFAULT_VERIFY_MAX_CONCURRENT',
33
44
  };
34
45
  /**
35
- * Resolve the default-on verification config from env > file(config) > default.
46
+ * Resolve the default-on verification config from
47
+ * env > operator file > repo manifest > typed default.
48
+ *
49
+ * Pure w.r.t. its inputs: env is injectable, and the repo-manifest read is
50
+ * injected via `readManifest` rather than touching fs inside this resolver, so
51
+ * the whole precedence chain is assertable without a real repo.
36
52
  *
37
- * Pure w.r.t. its inputs (env is injectable for tests). Env values are parsed
38
- * by daemon-core's loadEnvConfig, so an invalid numeric value fails loudly at
39
- * daemon startup (naming the var) instead of silently degrading mid-tick.
53
+ * Env values are parsed by daemon-core's loadEnvConfig, so an invalid numeric
54
+ * value fails loudly at daemon startup (naming the var) instead of silently
55
+ * degrading mid-tick. A malformed repo manifest fails the same way (naming the
56
+ * file) -- see verification-manifest.ts for why that is never degraded to
57
+ * "disabled".
58
+ *
59
+ * The manifest is read whenever a repoPath is present, regardless of which
60
+ * layer ultimately wins, so a broken repo declaration surfaces even on a
61
+ * workstation whose env/operator file happens to override it.
62
+ *
63
+ * One asymmetry worth naming: an operator's explicit `declined: true` marker
64
+ * SUPPRESSES the repo-manifest command. The marker is a recorded operator
65
+ * decision to gate on AI review only, and the operator file outranks the repo
66
+ * manifest -- so a repo declaring a command cannot silently overturn it. Env
67
+ * still wins over both (an explicit env command beats a stale decline marker,
68
+ * unchanged).
40
69
  */
41
- export function resolveDefaultVerification(config, env = process.env) {
70
+ export function resolveDefaultVerification(config, env = process.env, readManifest = readVerifyManifest) {
42
71
  const file = config.defaultVerification;
43
72
  const envCfg = loadEnvConfig(env);
73
+ const manifest = readManifest(config.repoPath);
44
74
  const envCommand = envCfg.TELORA_DEFAULT_VERIFY_COMMAND;
45
- const command = envCommand !== undefined && envCommand.trim() !== ''
46
- ? envCommand
47
- : (typeof file?.command === 'string' ? file.command : '');
75
+ const fileCommand = typeof file?.command === 'string' && file.command.trim() !== ''
76
+ ? file.command
77
+ : undefined;
78
+ // An explicit operator decline outranks the repo manifest (see docstring).
79
+ const manifestCommand = file?.declined === true ? undefined : manifest?.command;
80
+ const command = (envCommand !== undefined && envCommand.trim() !== '' ? envCommand : undefined)
81
+ ?? fileCommand
82
+ ?? manifestCommand
83
+ ?? '';
48
84
  const timeoutMs = envCfg.TELORA_DEFAULT_VERIFY_TIMEOUT_MS
49
85
  ?? (typeof file?.timeoutMs === 'number' && file.timeoutMs > 0 ? file.timeoutMs : undefined)
86
+ ?? manifest?.timeoutMs
50
87
  ?? DEFAULT_VERIFY_TIMEOUT_MS;
51
88
  const maxConcurrent = envCfg.TELORA_DEFAULT_VERIFY_MAX_CONCURRENT
52
89
  ?? (typeof file?.maxConcurrent === 'number' && file.maxConcurrent > 0 ? file.maxConcurrent : undefined)
90
+ ?? manifest?.maxConcurrent
53
91
  ?? DEFAULT_VERIFY_MAX_CONCURRENT;
54
92
  return {
55
93
  command,
@@ -65,14 +103,16 @@ export function resolveDefaultVerification(config, env = process.env) {
65
103
  * escalation/side-effect path -- posture is declarative state, surfaced on
66
104
  * ambient read surfaces, never a filed escalation. Callers pass a product-scoped
67
105
  * config (from `configForProduct`) so `config.defaultVerification` is already the
68
- * selected per-product-or-global block.
106
+ * selected per-product-or-global block and `repoPath` points at that product's
107
+ * repo -- which is what lets a repo-manifest-only command read `configured`.
69
108
  *
70
109
  * An explicitly resolved command wins over the decline marker: an operator who
71
110
  * sets a command (via env or file) has configured verification regardless of a
72
- * stale `declined` flag.
111
+ * stale `declined` flag. The marker still suppresses the repo manifest (the
112
+ * operator file outranks it), so `declined: true` keeps reading `declined`.
73
113
  */
74
- export function deriveVerificationPosture(config, env = process.env) {
75
- const resolved = resolveDefaultVerification(config, env);
114
+ export function deriveVerificationPosture(config, env = process.env, readManifest = readVerifyManifest) {
115
+ const resolved = resolveDefaultVerification(config, env, readManifest);
76
116
  if (resolved.enabled)
77
117
  return 'configured';
78
118
  if (config.defaultVerification?.declined === true)
@@ -86,13 +126,18 @@ export function deriveVerificationPosture(config, env = process.env) {
86
126
  * formatVerificationPostureLines, used to PUBLISH posture (e.g. in the daemon
87
127
  * heartbeat metadata) for the web app to read. Never files an escalation.
88
128
  */
89
- export function buildProductPostureMap(products, globalBlock, env = process.env) {
129
+ export function buildProductPostureMap(products, globalBlock, env = process.env, readManifest = readVerifyManifest) {
90
130
  const map = {};
91
131
  for (const p of products) {
92
- const scoped = { defaultVerification: p.defaultVerification ?? globalBlock };
93
- const resolved = resolveDefaultVerification(scoped, env);
132
+ // repoPath is carried through so each product's own committed manifest is
133
+ // the layer below its operator block (mirrors configForProduct).
134
+ const scoped = {
135
+ defaultVerification: p.defaultVerification ?? globalBlock,
136
+ ...(p.repoPath !== undefined ? { repoPath: p.repoPath } : {}),
137
+ };
138
+ const resolved = resolveDefaultVerification(scoped, env, readManifest);
94
139
  map[p.id] = {
95
- posture: deriveVerificationPosture(scoped, env),
140
+ posture: deriveVerificationPosture(scoped, env, readManifest),
96
141
  command: resolved.command,
97
142
  timeoutMs: resolved.timeoutMs,
98
143
  };
@@ -1 +1 @@
1
- {"version":3,"file":"verification-config.js","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verification-config.js","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"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"}