@telora/daemon 0.22.169 → 0.22.187

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 (254) hide show
  1. package/build-info.json +9 -3
  2. package/dist/audit/audit-floor-policy.d.ts +188 -0
  3. package/dist/audit/audit-floor-policy.d.ts.map +1 -0
  4. package/dist/audit/audit-floor-policy.js +353 -0
  5. package/dist/audit/audit-floor-policy.js.map +1 -0
  6. package/dist/audit/audit-prompt.d.ts +4 -177
  7. package/dist/audit/audit-prompt.d.ts.map +1 -1
  8. package/dist/audit/audit-prompt.js +6 -329
  9. package/dist/audit/audit-prompt.js.map +1 -1
  10. package/dist/completion/commit-verdict-release.d.ts +37 -1
  11. package/dist/completion/commit-verdict-release.d.ts.map +1 -1
  12. package/dist/completion/commit-verdict-release.js +90 -15
  13. package/dist/completion/commit-verdict-release.js.map +1 -1
  14. package/dist/completion/escalations.d.ts.map +1 -1
  15. package/dist/completion/escalations.js +3 -1
  16. package/dist/completion/escalations.js.map +1 -1
  17. package/dist/completion/review-exit-verdict-gate.d.ts +11 -5
  18. package/dist/completion/review-exit-verdict-gate.d.ts.map +1 -1
  19. package/dist/completion/review-exit-verdict-gate.js +6 -3
  20. package/dist/completion/review-exit-verdict-gate.js.map +1 -1
  21. package/dist/delivery/commit-verdict-hold.d.ts.map +1 -1
  22. package/dist/delivery/commit-verdict-hold.js +2 -1
  23. package/dist/delivery/commit-verdict-hold.js.map +1 -1
  24. package/dist/directive/stranded-review-reroute.js +1 -1
  25. package/dist/directive/stranded-review-reroute.js.map +1 -1
  26. package/dist/focus/focus-executor.d.ts.map +1 -1
  27. package/dist/focus/focus-executor.js +2 -0
  28. package/dist/focus/focus-executor.js.map +1 -1
  29. package/dist/focus/pending-review-approved-head.d.ts +1 -1
  30. package/dist/focus/pending-review-approved-head.d.ts.map +1 -1
  31. package/dist/focus/pending-review-approved-head.js +4 -3
  32. package/dist/focus/pending-review-approved-head.js.map +1 -1
  33. package/dist/focus/session-health.d.ts.map +1 -1
  34. package/dist/focus/session-health.js +2 -1
  35. package/dist/focus/session-health.js.map +1 -1
  36. package/dist/focus-stage-lifecycle/planning-release.d.ts +52 -17
  37. package/dist/focus-stage-lifecycle/planning-release.d.ts.map +1 -1
  38. package/dist/focus-stage-lifecycle/planning-release.js +58 -70
  39. package/dist/focus-stage-lifecycle/planning-release.js.map +1 -1
  40. package/dist/focus-stage-lifecycle/ratify-bar-gate.d.ts +108 -0
  41. package/dist/focus-stage-lifecycle/ratify-bar-gate.d.ts.map +1 -0
  42. package/dist/focus-stage-lifecycle/ratify-bar-gate.js +174 -0
  43. package/dist/focus-stage-lifecycle/ratify-bar-gate.js.map +1 -0
  44. package/dist/git/merge-to-main.d.ts.map +1 -1
  45. package/dist/git/merge-to-main.js.map +1 -1
  46. package/dist/nexus/index.d.ts.map +1 -1
  47. package/dist/nexus/index.js +2 -1
  48. package/dist/nexus/index.js.map +1 -1
  49. package/dist/nexus/intake-prompt-sections.d.ts +70 -0
  50. package/dist/nexus/intake-prompt-sections.d.ts.map +1 -0
  51. package/dist/nexus/intake-prompt-sections.js +145 -0
  52. package/dist/nexus/intake-prompt-sections.js.map +1 -0
  53. package/dist/nexus/intake-spawn.d.ts +49 -13
  54. package/dist/nexus/intake-spawn.d.ts.map +1 -1
  55. package/dist/nexus/intake-spawn.js +45 -122
  56. package/dist/nexus/intake-spawn.js.map +1 -1
  57. package/dist/nexus/intake.d.ts +55 -0
  58. package/dist/nexus/intake.d.ts.map +1 -1
  59. package/dist/nexus/intake.js +62 -1
  60. package/dist/nexus/intake.js.map +1 -1
  61. package/dist/prd/arm-readiness.d.ts +93 -0
  62. package/dist/prd/arm-readiness.d.ts.map +1 -0
  63. package/dist/prd/arm-readiness.js +254 -0
  64. package/dist/prd/arm-readiness.js.map +1 -0
  65. package/dist/prd/arm-refusal.d.ts +149 -0
  66. package/dist/prd/arm-refusal.d.ts.map +1 -0
  67. package/dist/prd/arm-refusal.js +219 -0
  68. package/dist/prd/arm-refusal.js.map +1 -0
  69. package/dist/prd/controller-shared.d.ts +111 -0
  70. package/dist/prd/controller-shared.d.ts.map +1 -1
  71. package/dist/prd/controller-shared.js +3 -1
  72. package/dist/prd/controller-shared.js.map +1 -1
  73. package/dist/prd/controller.d.ts +16 -10
  74. package/dist/prd/controller.d.ts.map +1 -1
  75. package/dist/prd/controller.js +28 -35
  76. package/dist/prd/controller.js.map +1 -1
  77. package/dist/prd/frontier-arming.d.ts +151 -0
  78. package/dist/prd/frontier-arming.d.ts.map +1 -0
  79. package/dist/prd/frontier-arming.js +315 -0
  80. package/dist/prd/frontier-arming.js.map +1 -0
  81. package/dist/prd/index.d.ts +10 -1
  82. package/dist/prd/index.d.ts.map +1 -1
  83. package/dist/prd/index.js +9 -1
  84. package/dist/prd/index.js.map +1 -1
  85. package/dist/prd/scoping-prompt.d.ts +68 -0
  86. package/dist/prd/scoping-prompt.d.ts.map +1 -0
  87. package/dist/prd/scoping-prompt.js +86 -0
  88. package/dist/prd/scoping-prompt.js.map +1 -0
  89. package/dist/prompt/prompt-contradictions.d.ts +20 -1
  90. package/dist/prompt/prompt-contradictions.d.ts.map +1 -1
  91. package/dist/prompt/prompt-contradictions.js +35 -0
  92. package/dist/prompt/prompt-contradictions.js.map +1 -1
  93. package/dist/prompt/team-prompt-base.d.ts +18 -0
  94. package/dist/prompt/team-prompt-base.d.ts.map +1 -1
  95. package/dist/prompt/team-prompt-base.js +56 -11
  96. package/dist/prompt/team-prompt-base.js.map +1 -1
  97. package/dist/prompt-sections/persona-sections.d.ts +36 -13
  98. package/dist/prompt-sections/persona-sections.d.ts.map +1 -1
  99. package/dist/prompt-sections/persona-sections.js +93 -16
  100. package/dist/prompt-sections/persona-sections.js.map +1 -1
  101. package/dist/prompt-sections/scoping-sections.d.ts +19 -5
  102. package/dist/prompt-sections/scoping-sections.d.ts.map +1 -1
  103. package/dist/prompt-sections/scoping-sections.js +45 -38
  104. package/dist/prompt-sections/scoping-sections.js.map +1 -1
  105. package/dist/prompt-sections/shared.d.ts +8 -0
  106. package/dist/prompt-sections/shared.d.ts.map +1 -1
  107. package/dist/prompt-sections/shared.js.map +1 -1
  108. package/dist/queries/delivery-gate-state.js +1 -1
  109. package/dist/queries/focus-criteria-standing.d.ts +170 -7
  110. package/dist/queries/focus-criteria-standing.d.ts.map +1 -1
  111. package/dist/queries/focus-criteria-standing.js +143 -8
  112. package/dist/queries/focus-criteria-standing.js.map +1 -1
  113. package/dist/queries/focus-ratify-release.d.ts +43 -0
  114. package/dist/queries/focus-ratify-release.d.ts.map +1 -0
  115. package/dist/queries/focus-ratify-release.js +45 -0
  116. package/dist/queries/focus-ratify-release.js.map +1 -0
  117. package/dist/queries/focuses.d.ts +0 -10
  118. package/dist/queries/focuses.d.ts.map +1 -1
  119. package/dist/queries/focuses.js +2 -15
  120. package/dist/queries/focuses.js.map +1 -1
  121. package/dist/queries/prd.d.ts +31 -0
  122. package/dist/queries/prd.d.ts.map +1 -1
  123. package/dist/queries/prd.js +26 -1
  124. package/dist/queries/prd.js.map +1 -1
  125. package/dist/queries/shared.js +1 -1
  126. package/dist/resolvers/focus-criteria-standing.d.ts.map +1 -1
  127. package/dist/resolvers/focus-criteria-standing.js +324 -25
  128. package/dist/resolvers/focus-criteria-standing.js.map +1 -1
  129. package/dist/resolvers/shared/review-window-commits.d.ts.map +1 -1
  130. package/dist/resolvers/shared/review-window-commits.js +2 -1
  131. package/dist/resolvers/shared/review-window-commits.js.map +1 -1
  132. package/dist/security/security-auto-inject.d.ts +51 -0
  133. package/dist/security/security-auto-inject.d.ts.map +1 -1
  134. package/dist/security/security-auto-inject.js +101 -11
  135. package/dist/security/security-auto-inject.js.map +1 -1
  136. package/dist/security/security-scan-engine.d.ts +4 -4
  137. package/dist/security/security-scan-engine.d.ts.map +1 -1
  138. package/dist/security/security-scan-engine.js +6 -0
  139. package/dist/security/security-scan-engine.js.map +1 -1
  140. package/dist/session/session-lineage.d.ts.map +1 -1
  141. package/dist/session/session-lineage.js +2 -0
  142. package/dist/session/session-lineage.js.map +1 -1
  143. package/dist/shell/constants.d.ts +5 -0
  144. package/dist/shell/constants.d.ts.map +1 -1
  145. package/dist/shell/constants.js +5 -0
  146. package/dist/shell/constants.js.map +1 -1
  147. package/dist/shell/daemon-instance.d.ts +74 -64
  148. package/dist/shell/daemon-instance.d.ts.map +1 -1
  149. package/dist/shell/daemon-instance.js +16 -121
  150. package/dist/shell/daemon-instance.js.map +1 -1
  151. package/dist/shell/health-events.js +1 -1
  152. package/dist/shell/health-events.js.map +1 -1
  153. package/dist/shell/instance-liveness.d.ts +112 -0
  154. package/dist/shell/instance-liveness.d.ts.map +1 -0
  155. package/dist/shell/instance-liveness.js +205 -0
  156. package/dist/shell/instance-liveness.js.map +1 -0
  157. package/dist/shell/schema-version-gate.d.ts +22 -0
  158. package/dist/shell/schema-version-gate.d.ts.map +1 -1
  159. package/dist/shell/schema-version-gate.js +116 -6
  160. package/dist/shell/schema-version-gate.js.map +1 -1
  161. package/dist/shell/worker-pidfile.d.ts +21 -8
  162. package/dist/shell/worker-pidfile.d.ts.map +1 -1
  163. package/dist/shell/worker-pidfile.js +38 -9
  164. package/dist/shell/worker-pidfile.js.map +1 -1
  165. package/dist/spawn/lead-launch.d.ts.map +1 -1
  166. package/dist/spawn/lead-launch.js +2 -1
  167. package/dist/spawn/lead-launch.js.map +1 -1
  168. package/dist/spawn/one-shot-scoping-spawn.d.ts +51 -0
  169. package/dist/spawn/one-shot-scoping-spawn.d.ts.map +1 -0
  170. package/dist/spawn/one-shot-scoping-spawn.js +156 -0
  171. package/dist/spawn/one-shot-scoping-spawn.js.map +1 -0
  172. package/dist/spawn/process-spawn.d.ts +12 -0
  173. package/dist/spawn/process-spawn.d.ts.map +1 -1
  174. package/dist/spawn/process-spawn.js +1 -1
  175. package/dist/spawn/process-spawn.js.map +1 -1
  176. package/dist/spawn/prompt-assembly.d.ts +8 -0
  177. package/dist/spawn/prompt-assembly.d.ts.map +1 -1
  178. package/dist/spawn/prompt-assembly.js +15 -3
  179. package/dist/spawn/prompt-assembly.js.map +1 -1
  180. package/dist/spawn/worktree-session.d.ts +24 -6
  181. package/dist/spawn/worktree-session.d.ts.map +1 -1
  182. package/dist/spawn/worktree-session.js +37 -14
  183. package/dist/spawn/worktree-session.js.map +1 -1
  184. package/dist/testing/arm-coverage-model.d.ts +75 -0
  185. package/dist/testing/arm-coverage-model.d.ts.map +1 -0
  186. package/dist/testing/arm-coverage-model.js +114 -0
  187. package/dist/testing/arm-coverage-model.js.map +1 -0
  188. package/dist/testing/fixtures/index.js +1 -1
  189. package/dist/types/index.js +1 -1
  190. package/dist/verify/commit-gate-configured.d.ts.map +1 -1
  191. package/dist/verify/commit-gate-configured.js +1 -1
  192. package/dist/verify/commit-gate-configured.js.map +1 -1
  193. package/dist/verify/commit-verdict-pull.d.ts +48 -0
  194. package/dist/verify/commit-verdict-pull.d.ts.map +1 -0
  195. package/dist/verify/commit-verdict-pull.js +148 -0
  196. package/dist/verify/commit-verdict-pull.js.map +1 -0
  197. package/dist/verify/commit-verdict-record.js +1 -1
  198. package/dist/verify/credit-rearm.js +1 -1
  199. package/dist/verify/credit-rearm.js.map +1 -1
  200. package/dist/verify/default-on-guards.d.ts +74 -0
  201. package/dist/verify/default-on-guards.d.ts.map +1 -0
  202. package/dist/verify/default-on-guards.js +305 -0
  203. package/dist/verify/default-on-guards.js.map +1 -0
  204. package/dist/verify/explicit-rearm.d.ts.map +1 -1
  205. package/dist/verify/explicit-rearm.js +1 -0
  206. package/dist/verify/explicit-rearm.js.map +1 -1
  207. package/dist/verify/gate-run-registry.d.ts.map +1 -1
  208. package/dist/verify/gate-run-registry.js +1 -0
  209. package/dist/verify/gate-run-registry.js.map +1 -1
  210. package/dist/verify/judged-ancestor.d.ts +41 -0
  211. package/dist/verify/judged-ancestor.d.ts.map +1 -0
  212. package/dist/verify/judged-ancestor.js +101 -0
  213. package/dist/verify/judged-ancestor.js.map +1 -0
  214. package/dist/verify/no-own-delta-verdict.d.ts +7 -2
  215. package/dist/verify/no-own-delta-verdict.d.ts.map +1 -1
  216. package/dist/verify/no-own-delta-verdict.js +14 -17
  217. package/dist/verify/no-own-delta-verdict.js.map +1 -1
  218. package/dist/verify/rework-attribution.d.ts +71 -0
  219. package/dist/verify/rework-attribution.d.ts.map +1 -0
  220. package/dist/verify/rework-attribution.js +263 -0
  221. package/dist/verify/rework-attribution.js.map +1 -0
  222. package/dist/verify/shortfall-rulings.d.ts.map +1 -1
  223. package/dist/verify/shortfall-rulings.js +3 -2
  224. package/dist/verify/shortfall-rulings.js.map +1 -1
  225. package/dist/verify/verification-boundary-env.d.ts +70 -17
  226. package/dist/verify/verification-boundary-env.d.ts.map +1 -1
  227. package/dist/verify/verification-boundary-env.js +88 -14
  228. package/dist/verify/verification-boundary-env.js.map +1 -1
  229. package/dist/verify/verification-commit-sharing.d.ts.map +1 -1
  230. package/dist/verify/verification-commit-sharing.js +2 -1
  231. package/dist/verify/verification-commit-sharing.js.map +1 -1
  232. package/dist/verify/verification-config.d.ts.map +1 -1
  233. package/dist/verify/verification-config.js +1 -0
  234. package/dist/verify/verification-config.js.map +1 -1
  235. package/dist/verify/verification-default-on.d.ts +0 -32
  236. package/dist/verify/verification-default-on.d.ts.map +1 -1
  237. package/dist/verify/verification-default-on.js +10 -234
  238. package/dist/verify/verification-default-on.js.map +1 -1
  239. package/dist/verify/verification-deps-default.d.ts.map +1 -1
  240. package/dist/verify/verification-deps-default.js +9 -0
  241. package/dist/verify/verification-deps-default.js.map +1 -1
  242. package/dist/verify/verification-engine.d.ts +2 -1
  243. package/dist/verify/verification-engine.d.ts.map +1 -1
  244. package/dist/verify/verification-engine.js +12 -4
  245. package/dist/verify/verification-engine.js.map +1 -1
  246. package/dist/verify/verification-feedback.d.ts +1 -1
  247. package/dist/verify/verification-feedback.d.ts.map +1 -1
  248. package/dist/verify/verification-feedback.js +5 -0
  249. package/dist/verify/verification-feedback.js.map +1 -1
  250. package/dist/verify/verification-rework-issue.d.ts +48 -7
  251. package/dist/verify/verification-rework-issue.d.ts.map +1 -1
  252. package/dist/verify/verification-rework-issue.js +111 -9
  253. package/dist/verify/verification-rework-issue.js.map +1 -1
  254. package/package.json +2 -2
@@ -1,42 +1,19 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
- // Pinned by: none -- no test imports this module directly (baselined; see lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/nexus/nexus-intake-arm-covers-stated-effects.test.ts,
3
+ // packages/daemon/src/spawn/one-shot-scoping-spawn.test.ts
3
4
  // PINNED-BY-END
5
+ import { SCOPING_AGENT_TIMEOUT_MS, spawnOneShotScopingAgent, } from '../spawn/one-shot-scoping-spawn.js';
6
+ import { renderContractRules, renderObservationSection, renderScopingSteps, } from './intake-prompt-sections.js';
7
+ /** Logger module tag for this caller's scoping-agent lines. */
8
+ const LOG_MODULE = 'nexus-intake';
4
9
  /**
5
- * Nexus intake scoping-agent spawn.
10
+ * Kill the scoping agent if it has not exited within this window (15 minutes).
6
11
  *
7
- * Spawns a short-lived, single-purpose Claude Code agent that authors a focus
8
- * from an accepted cross-product request -- the work the materialize edge
9
- * handler structurally could not do. The agent is seeded with the request + its
10
- * acceptanceContract and the role UUID to assign; its sole job is:
11
- *
12
- * 1. telora_product_focus create -- a per-request focus named from the request,
13
- * then assign it the intake role so the spawn loop picks it up.
14
- * 2. telora_reality_tree create + author nodes/edges -- the acceptanceContract
15
- * becomes the goal / desired-effect the tree drives toward.
16
- * 3. telora_product_delivery create -- injection-anchored deliveries.
17
- * 4. telora_product_request materialize -- stamp the new focus (+ a
18
- * representative delivery) back on the request so it leaves the
19
- * intake-pending set and advances accepted -> in_progress.
20
- * 5. exit.
21
- *
22
- * Mirrors spawn/lifecycle.ts spawnResolutionAgent (the merge-conflict resolution agent): a
23
- * one-shot `--print` Claude Code process, prompt passed as a CLI arg, cleaned
24
- * env, a kill timeout, no team mode and no streaming. It makes NO git changes
25
- * (MCP calls only), so it runs in the product repo (config.repoPath) where the
26
- * per-product .mcp.json + CLAUDE.md live -- no isolated worktree required.
27
- *
28
- * FIRE-AND-FORGET: the scoping agent runs for minutes; spawnScopingAgent resolves
29
- * the moment the process has spawned (the 'spawn' event), NOT on close, so the
30
- * daemon poll loop is never blocked. The close/error handlers only log; the
31
- * intake_scoping_started_at stamp (written by the caller before this spawn) is
32
- * the in-flight guard that prevents a re-spawn until the staleness window.
12
+ * An alias of the shared one-shot timeout, kept under its original name because
13
+ * DEFAULT_INTAKE_STALE_MS is documented and tested as strictly greater than it
14
+ * (`nexus-intake.test.ts`) -- the relation is intake's, the number is shared.
33
15
  */
34
- import { spawn } from 'node:child_process';
35
- import { stripClaudeCodeEnvVars } from '@telora/daemon-core';
36
- import { createLogger } from '../shell/log.js';
37
- const log = createLogger({ module: 'nexus-intake' });
38
- /** Kill the scoping agent if it has not exited within this window (15 minutes). */
39
- export const INTAKE_SCOPING_TIMEOUT_MS = 15 * 60 * 1000;
16
+ export const INTAKE_SCOPING_TIMEOUT_MS = SCOPING_AGENT_TIMEOUT_MS;
40
17
  /**
41
18
  * Build the scoping prompt seeded with the request + acceptanceContract + the
42
19
  * role to assign. Pure (string) so it is unit-tested without spawning a process.
@@ -45,119 +22,65 @@ export function buildIntakeScopingPrompt(req, roleId) {
45
22
  const title = req.title ?? '(untitled request)';
46
23
  const acceptanceContract = req.acceptanceContract ?? '(no acceptance contract supplied)';
47
24
  const description = req.description ?? '(no description supplied)';
25
+ const targetProductId = req.targetProductId ?? '(unknown)';
26
+ const observation = req.observation ?? null;
27
+ const hasObservation = observation !== null;
48
28
  // Stable marker embedded in the focus description so a re-spawn (after a
49
29
  // crashed prior run) can find and REUSE the focus this request already
50
30
  // authored instead of creating a duplicate.
51
31
  const marker = `Nexus request: ${req.id}`;
52
- return [
32
+ const sections = [
53
33
  `You are the nexus-intake SCOPING agent for an accepted cross-product (Nexus) request.`,
54
34
  `Your SOLE job is to author a per-request focus for this product's team to execute, then exit.`,
55
35
  `You author intent + structure via the telora_* MCP tools only -- you write NO application code here.`,
56
36
  ``,
57
37
  `## The accepted request`,
58
38
  `- requestId: ${req.id}`,
59
- `- targetProductId (THIS product -- author the focus here): ${req.targetProductId ?? '(unknown)'}`,
39
+ `- targetProductId (THIS product -- author the focus here): ${targetProductId}`,
60
40
  `- title: ${title}`,
61
41
  `- description: ${description}`,
62
42
  ``,
63
- `## Acceptance contract (the goal / definition of done -- this seeds the focus reality tree)`,
43
+ // Renders nothing at all when the request carries no observation.
44
+ renderObservationSection(observation),
45
+ hasObservation
46
+ ? `## Acceptance contract (the BAR your derived future must clear -- NOT the tree to build)`
47
+ : `## Acceptance contract (the goal / definition of done)`,
64
48
  acceptanceContract,
65
49
  ``,
66
50
  `## IDEMPOTENCY (read first -- a previous scoping run for this request may have crashed)`,
67
51
  `Before creating anything, telora_product_focus list (productId = ${req.targetProductId ?? '<targetProductId>'}) and look for a focus whose description carries the marker "${marker}".`,
68
- `- If one EXISTS, a prior run already created it. REUSE it: skip step 1 (create), and resume from whichever later step is unfinished (role assigned? materialized? tree built? deliveries scoped?). Do NOT create a second focus.`,
52
+ `- If one EXISTS, a prior run already created it. REUSE it: skip step 1 (create), and resume from whichever later step is unfinished, checking them IN ORDER (materialized? tree built? deliveries created + second materialize?). The LAST unfinished step to check for is the ARM: a marked focus with assignedAgentRoleId still null is a run that crashed before arming -- finish every earlier step first, then arm. Do NOT create a second focus.`,
69
53
  `- If none exists, start at step 1.`,
70
54
  ``,
71
- `## Steps (do these in order, verifying each with a follow-up read)`,
72
- `1. telora_product_focus create -- name the focus from the request title ("${title}"), productId = ${req.targetProductId ?? '<targetProductId>'}. The description MUST include, verbatim, the marker line "${marker}" AND the full acceptance contract above (so any follow-up team has the goal even if the tree is not yet built).`,
73
- ` Then telora_product_focus update to set assignedAgentRoleId = ${roleId} so the spawn loop will pick the focus up (no dead-letter). Arming here is NOT the tail of your scoping -- it is the human go-signal that the accepted intake request DURABLY DELEGATED to this flow (accepting the request IS the go-signal). Declare it in the same call: pass armNote = "durably-delegated arm: accepted intake request ${req.id}".`,
74
- `2. telora_product_request materialize -- requestId = ${req.id}, materializedFocusId = <the focus id you created>. Do this NOW, immediately after the focus exists and is role-assigned -- BEFORE building the tree or deliveries. This stamps the focus back on the request (accepted -> in_progress) so it leaves the intake-pending set and a second scoping agent can never be spawned for it. If your run crashes after this point, the per-request focus already exists and the normal loop finishes scoping it; if it crashed before this point, the idempotency check above reuses the focus.`,
75
- `3. telora_reality_tree create on the focus, then author the CRT: capture the current undesired effects, and set the FRT goal / desired-effect FROM the acceptance contract above. Build at least one injection that drives the tree toward that goal.`,
76
- `4. telora_product_delivery create -- decompose the work into one or more deliveries, EACH anchored to an injection (injectionNodeId) and carrying a workFacing label ("outward" for new ground / a capability not had before, "inward" for improving existing ground). Scope deliveries by the phases the work naturally has. Create deliveries LAST: a queued delivery is the signal that arms the normal spawn loop, so leaving it until the tree is built avoids the loop picking up a half-scoped focus.`,
77
- ` Then call telora_product_request materialize ONCE MORE with the SAME materializedFocusId plus materializedDeliveryId = <the representative delivery id>. The request is already in_progress at this point, which is fine -- materialize is idempotent for the same focus and just records the delivery the return-path loop watches to resolve this request when it reaches done.`,
78
- `5. Stop. Do NOT begin implementing the deliveries -- the role-assigned focus runs the normal differential loop after you exit.`,
55
+ renderScopingSteps({
56
+ requestId: req.id,
57
+ title,
58
+ targetProductId,
59
+ roleId,
60
+ marker,
61
+ hasObservation,
62
+ }),
79
63
  ``,
64
+ renderContractRules(req.id, hasObservation),
80
65
  `Refer to focuses/deliveries/issues by title in any prose, never by UUID. Follow CLAUDE.md.`,
81
- ].join('\n');
66
+ ];
67
+ // A section that rendered to nothing leaves an empty string in place; joining
68
+ // and collapsing runs of blank lines is what makes its absence invisible --
69
+ // no gap a reader could mistake for a heading that failed to render.
70
+ return sections.join('\n').replace(/\n{3,}/g, '\n\n');
82
71
  }
83
- const defaultSeam = {
84
- spawnProcess: (command, args, cwd, env) => spawn(command, args, { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] }),
85
- };
86
72
  /**
87
73
  * Spawn the intake scoping agent for one accepted request. Resolves once the
88
74
  * process has SPAWNED (fire-and-forget -- the agent runs for minutes); rejects
89
- * only if the process fails to spawn. The close/error handlers log the outcome
90
- * and the kill timeout bounds a hung agent.
75
+ * only if the process fails to spawn. The shared seam logs the outcome and its
76
+ * kill timeout bounds a hung agent.
91
77
  */
92
- export function spawnScopingAgent(config, req, roleId, seam = defaultSeam) {
93
- const prompt = buildIntakeScopingPrompt(req, roleId);
94
- const args = [
95
- '--print',
96
- '--dangerously-skip-permissions',
97
- '--setting-sources', 'project,local',
98
- prompt,
99
- ];
100
- const env = stripClaudeCodeEnvVars(process.env);
101
- const cwd = config.repoPath ?? process.cwd();
102
- return new Promise((resolve, reject) => {
103
- let settled = false;
104
- let proc;
105
- try {
106
- proc = seam.spawnProcess(config.claudeCodePath, args, cwd, env);
107
- }
108
- catch (err) {
109
- reject(err instanceof Error ? err : new Error(String(err)));
110
- return;
111
- }
112
- // Prompt is a CLI arg; close stdin immediately.
113
- proc.stdin?.end?.();
114
- const timeout = setTimeout(() => {
115
- log.warn(`scoping agent for request ${req.id} timed out after ${INTAKE_SCOPING_TIMEOUT_MS / 1000}s, killing`);
116
- if (proc.pid) {
117
- try {
118
- process.kill(proc.pid, 'SIGTERM');
119
- }
120
- catch { /* ignore */ }
121
- setTimeout(() => {
122
- if (proc.pid) {
123
- try {
124
- process.kill(proc.pid, 'SIGKILL');
125
- }
126
- catch { /* ignore */ }
127
- }
128
- }, 10_000);
129
- }
130
- }, INTAKE_SCOPING_TIMEOUT_MS);
131
- // Do not let the kill timer keep the daemon event loop alive.
132
- timeout.unref?.();
133
- proc.on('spawn', () => {
134
- // Process is up -- the daemon poll continues; the agent runs to completion
135
- // in the background.
136
- log.info(`scoping agent spawned for request ${req.id} (PID: ${proc.pid ?? '?'})`);
137
- if (!settled) {
138
- settled = true;
139
- resolve();
140
- }
141
- });
142
- proc.on('close', (code) => {
143
- clearTimeout(timeout);
144
- log.info(`scoping agent for request ${req.id} exited (code: ${code ?? '?'})`);
145
- // If 'spawn' never fired (very early exit), still resolve -- the stamp guard
146
- // already prevents an immediate re-spawn.
147
- if (!settled) {
148
- settled = true;
149
- resolve();
150
- }
151
- });
152
- proc.on('error', (err) => {
153
- clearTimeout(timeout);
154
- const message = err instanceof Error ? err.message : String(err);
155
- log.error(`scoping agent spawn error for request ${req.id}: ${message}`);
156
- if (!settled) {
157
- settled = true;
158
- reject(new Error(message));
159
- }
160
- });
161
- });
78
+ export function spawnScopingAgent(config, req, roleId, seam) {
79
+ return spawnOneShotScopingAgent(config, {
80
+ label: `request ${req.id}`,
81
+ prompt: buildIntakeScopingPrompt(req, roleId),
82
+ logModule: LOG_MODULE,
83
+ timeoutMs: INTAKE_SCOPING_TIMEOUT_MS,
84
+ }, seam);
162
85
  }
163
86
  //# sourceMappingURL=intake-spawn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"intake-spawn.js","sourceRoot":"","sources":["../../src/nexus/intake-spawn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intake-spawn.js","sourceRoot":"","sources":["../../src/nexus/intake-spawn.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,uFAAuF;AACvF,6DAA6D;AAC7D,gBAAgB;AA2ChB,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GAEzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AAErC,+DAA+D;AAC/D,MAAM,UAAU,GAAG,cAAc,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAMlE;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAyB,EAAE,MAAc;IAChF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,oBAAoB,CAAC;IAChD,MAAM,kBAAkB,GAAG,GAAG,CAAC,kBAAkB,IAAI,mCAAmC,CAAC;IACzF,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,2BAA2B,CAAC;IACnE,MAAM,eAAe,GAAG,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;IAC3D,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC;IAC5C,MAAM,cAAc,GAAG,WAAW,KAAK,IAAI,CAAC;IAC5C,yEAAyE;IACzE,uEAAuE;IACvE,4CAA4C;IAC5C,MAAM,MAAM,GAAG,kBAAkB,GAAG,CAAC,EAAE,EAAE,CAAC;IAE1C,MAAM,QAAQ,GAAG;QACf,uFAAuF;QACvF,+FAA+F;QAC/F,sGAAsG;QACtG,EAAE;QACF,yBAAyB;QACzB,gBAAgB,GAAG,CAAC,EAAE,EAAE;QACxB,8DAA8D,eAAe,EAAE;QAC/E,YAAY,KAAK,EAAE;QACnB,kBAAkB,WAAW,EAAE;QAC/B,EAAE;QACF,kEAAkE;QAClE,wBAAwB,CAAC,WAAW,CAAC;QACrC,cAAc;YACZ,CAAC,CAAC,0FAA0F;YAC5F,CAAC,CAAC,wDAAwD;QAC5D,kBAAkB;QAClB,EAAE;QACF,yFAAyF;QACzF,oEAAoE,GAAG,CAAC,eAAe,IAAI,mBAAmB,gEAAgE,MAAM,IAAI;QACxL,wbAAwb;QACxb,oCAAoC;QACpC,EAAE;QACF,kBAAkB,CAAC;YACjB,SAAS,EAAE,GAAG,CAAC,EAAE;YACjB,KAAK;YACL,eAAe;YACf,MAAM;YACN,MAAM;YACN,cAAc;SACf,CAAC;QACF,EAAE;QACF,mBAAmB,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC;QAC3C,4FAA4F;KAC7F,CAAC;IACF,8EAA8E;IAC9E,4EAA4E;IAC5E,qEAAqE;IACrE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoB,EACpB,GAAyB,EACzB,MAAc,EACd,IAAuB;IAEvB,OAAO,wBAAwB,CAC7B,MAAM,EACN;QACE,KAAK,EAAE,WAAW,GAAG,CAAC,EAAE,EAAE;QAC1B,MAAM,EAAE,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC;QAC7C,SAAS,EAAE,UAAU;QACrB,SAAS,EAAE,yBAAyB;KACrC,EACD,IAAI,CACL,CAAC;AACJ,CAAC"}
@@ -68,6 +68,29 @@ export declare const MAX_INTAKE_SPAWNS_PER_CYCLE = 5;
68
68
  * Minimal shape of an intake-pending product_request (camelCase from the edge
69
69
  * fn). Defensive: the daemon must not assume any optional field is present.
70
70
  */
71
+ /** One node of the observation fragment, as product-api serves it. */
72
+ export interface IntakeObservationNode {
73
+ nodeId: string;
74
+ seq: number;
75
+ nodeType: string;
76
+ statement: string;
77
+ evidence: string | null;
78
+ frtStatement: string | null;
79
+ }
80
+ /**
81
+ * What the REQUESTER observed, carried on the request: the undesired effect the
82
+ * request asks to be cleared, plus its upstream causes and their evidence. This
83
+ * is the material the target's intake authors its own CRT from -- without it,
84
+ * the only thing intake has to build from is the acceptance contract, and a
85
+ * contract is a statement of the desired FUTURE, so building downward from it
86
+ * produces a tree of the requester's mechanism and never reaches the cause.
87
+ */
88
+ export interface IntakeObservation {
89
+ sourceNode: IntakeObservationNode;
90
+ upstreamCauses: IntakeObservationNode[];
91
+ /** True when a cap stopped the walk -- the fragment is partial and says so. */
92
+ truncated: boolean;
93
+ }
71
94
  export interface IntakePendingRequest {
72
95
  id: string;
73
96
  targetProductId?: string | null;
@@ -77,7 +100,39 @@ export interface IntakePendingRequest {
77
100
  title?: string | null;
78
101
  description?: string | null;
79
102
  acceptanceContract?: string | null;
103
+ /** The UDE in the requester's tree this request is born from, when it has one. */
104
+ sourceNodeId?: string | null;
105
+ /**
106
+ * The SNAPSHOT stored on the request at create, carried by the list page the
107
+ * poll already fetches -- no second read per request, and no walk of the
108
+ * requester's tree from here at all.
109
+ *
110
+ * Absent -- not an empty fragment -- for an endpoint-typed request or one
111
+ * raised before requests carried one, so the prompt renders nothing rather
112
+ * than a placeholder that reads as content. Absent ALONGSIDE a sourceNodeId
113
+ * is a different thing entirely, and never scoped: see `isScopable`.
114
+ */
115
+ observation?: IntakeObservation | null;
80
116
  }
117
+ /**
118
+ * Why this request cannot be scoped from its observation, or null if it can.
119
+ *
120
+ * Only source-backed requests are judged. An endpoint-typed request carries no
121
+ * observation BY DESIGN and scopes from its contract; so does a request raised
122
+ * before requests carried one. Neither is a defect, and neither is held.
123
+ *
124
+ * A source-backed request is different in kind. Its contract was DERIVED from a
125
+ * node, the prompt tells the agent to build its CRT from that node's evidence
126
+ * and to mirror the effect, and the materialize gate then judges the plan
127
+ * against the mirror. Hand that agent the contract alone and every one of those
128
+ * steps is missing -- which is the precise shape this focus exists to delete, so
129
+ * it is not something to arrive at by falling back.
130
+ *
131
+ * The check is deliberately shallow: the fields the prompt actually renders.
132
+ * Validating more would reject rows the prompt could use; validating less would
133
+ * spawn an agent to read an empty heading.
134
+ */
135
+ export declare function observationDefect(req: IntakePendingRequest): string | null;
81
136
  /** What the gate decides for one request. */
82
137
  export type IntakeDecision = 'spawn' | 'in_flight' | 'skip';
83
138
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../src/nexus/intake.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAStD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAC5C,eAAe,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAC7C,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAC/C,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBxB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,QAAiB,CAAC;AAEtD;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,oBAAoB,EACzB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAAgC,GACxC,cAAc,CAShB;AAED,MAAM,WAAW,eAAe;IAC9B,4FAA4F;IAC5F,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC1E;;;;;;OAMG;IACH,mBAAmB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD,wFAAwF;IACxF,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,gFAAgF;IAChF,iBAAiB,EAAE,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAwC5E;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,eAAgD,EACtD,OAAO,GAAE,MAAgC,GACxC,OAAO,CAAC,IAAI,CAAC,CA4Df"}
1
+ {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../src/nexus/intake.ts"],"names":[],"mappings":"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"}
@@ -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: none -- no test imports this module directly (baselined; see lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/nexus/nexus-intake-arm-covers-stated-effects.test.ts,
3
+ // packages/daemon/src/spawn/one-shot-scoping-spawn.test.ts
3
4
  // PINNED-BY-END
4
5
  import { callApi } from '../queries/shared.js';
5
6
  import { getAgentRoles } from '../queries/roles.js';
@@ -65,6 +66,47 @@ export const DEFAULT_INTAKE_STALE_MS = 20 * 60 * 1000;
65
66
  * rate-limited. Surfaced via a log line so the cap is never silent.
66
67
  */
67
68
  export const MAX_INTAKE_SPAWNS_PER_CYCLE = 5;
69
+ /** A usable observation node: both fields the prompt renders must be real text. */
70
+ function isObservationNode(value) {
71
+ if (typeof value !== 'object' || value === null)
72
+ return false;
73
+ const n = value;
74
+ return typeof n.nodeId === 'string' && n.nodeId !== ''
75
+ && typeof n.statement === 'string' && n.statement !== '';
76
+ }
77
+ /**
78
+ * Why this request cannot be scoped from its observation, or null if it can.
79
+ *
80
+ * Only source-backed requests are judged. An endpoint-typed request carries no
81
+ * observation BY DESIGN and scopes from its contract; so does a request raised
82
+ * before requests carried one. Neither is a defect, and neither is held.
83
+ *
84
+ * A source-backed request is different in kind. Its contract was DERIVED from a
85
+ * node, the prompt tells the agent to build its CRT from that node's evidence
86
+ * and to mirror the effect, and the materialize gate then judges the plan
87
+ * against the mirror. Hand that agent the contract alone and every one of those
88
+ * steps is missing -- which is the precise shape this focus exists to delete, so
89
+ * it is not something to arrive at by falling back.
90
+ *
91
+ * The check is deliberately shallow: the fields the prompt actually renders.
92
+ * Validating more would reject rows the prompt could use; validating less would
93
+ * spawn an agent to read an empty heading.
94
+ */
95
+ export function observationDefect(req) {
96
+ if (!req.sourceNodeId)
97
+ return null;
98
+ const obs = req.observation;
99
+ if (obs === null || obs === undefined) {
100
+ return 'it carries no observation snapshot';
101
+ }
102
+ if (!isObservationNode(obs.sourceNode)) {
103
+ return 'its observation has no readable source node';
104
+ }
105
+ if (!Array.isArray(obs.upstreamCauses) || !obs.upstreamCauses.every(isObservationNode)) {
106
+ return 'its observation has a malformed upstream cause';
107
+ }
108
+ return null;
109
+ }
68
110
  /**
69
111
  * Pure intake gate. A request needs a scoping spawn when it is accepted, not yet
70
112
  * materialized, and either has never been spawned or its last spawn is stale.
@@ -178,6 +220,25 @@ export async function checkIntakePendingRequests(config, deps = defaultNexusInta
178
220
  return;
179
221
  }
180
222
  for (const req of batch) {
223
+ // A source-backed request whose observation is missing or malformed is NOT
224
+ // scoped, and nothing about it is stamped. Degrading to the no-observation
225
+ // prompt was the old behaviour and it is unrecoverable: the prompt's first
226
+ // materialize moves the request to in_progress, which removes it from the
227
+ // intake-pending set forever, and the second materialize is then held for a
228
+ // mirror the agent was never told to create. One transient read, and the
229
+ // request is permanently stuck in exactly the contract-seeded,
230
+ // observation-free shape this whole focus exists to delete.
231
+ //
232
+ // Skipping leaves the request retryable BY CONSTRUCTION: it stays accepted
233
+ // with no materialized focus, so it is intake-pending again on the very
234
+ // next tick, with no stale stamp to wait out.
235
+ const defect = observationDefect(req);
236
+ if (defect) {
237
+ log(`[nexus-intake] NOT scoping request ${req.id} (product ${productId}): ${defect}. ` +
238
+ `It names a source node, so it must be scoped from its observation -- ` +
239
+ `left intake-pending for the next tick.`);
240
+ continue;
241
+ }
181
242
  try {
182
243
  // Stamp BEFORE the spawn so a slow/failed spawn does not re-fire next tick;
183
244
  // a stale stamp re-arms it after staleMs.
@@ -1 +1 @@
1
- {"version":3,"file":"intake.js","sourceRoot":"","sources":["../../src/nexus/intake.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intake.js","sourceRoot":"","sources":["../../src/nexus/intake.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /** A delivery as this check reads it. */
2
+ export interface ArmReadinessDelivery {
3
+ id: string;
4
+ name: string;
5
+ /**
6
+ * The delivery's execution status. Nullable on the wire; a null status is
7
+ * NOT 'cancelled', so it counts as live -- the bar below turns on the anchor
8
+ * and the restatements, and a missing status must not silently drop a
9
+ * delivery out of the evidence.
10
+ */
11
+ executionStatus: string | null;
12
+ /** The injection the delivery is anchored to, or null when unanchored. */
13
+ injectionId: string | null;
14
+ }
15
+ /**
16
+ * One effect an injection promises to flip: the node id, and the restatement
17
+ * declared on it (`frt_statement`), or null when none was declared.
18
+ */
19
+ export interface ArmReadinessTarget {
20
+ nodeId: string;
21
+ frtStatement: string | null;
22
+ }
23
+ /** The answer, with the reason it came out that way (logged, never escalated). */
24
+ export interface FocusArmReadiness {
25
+ ready: boolean;
26
+ /** Human-readable why -- goes straight into the daemon log line. */
27
+ reason: string;
28
+ /** The anchored deliveries that met the bar (empty when not ready). */
29
+ readyDeliveryIds: string[];
30
+ }
31
+ /**
32
+ * The bar, PURE. `targetsByInjectionId` maps each anchored delivery's injection
33
+ * to the effects it promises to flip.
34
+ *
35
+ * A delivery is COUNTED when it is anchored, not cancelled, and its injection's
36
+ * targets all carry a restatement. An injection with NO targets is not counted:
37
+ * "every target carries a restatement" is vacuously true of an empty set, and
38
+ * an arm over an empty set is precisely the zero-effect arm this check refuses.
39
+ */
40
+ export declare function assessArmReadiness(deliveries: ArmReadinessDelivery[], targetsByInjectionId: Map<string, ArmReadinessTarget[]>): FocusArmReadiness;
41
+ /** The reads this check needs (injected so it is testable without the API). */
42
+ export interface ArmReadinessDeps {
43
+ loadDeliveries?: (focusId: string) => Promise<ArmReadinessDelivery[]>;
44
+ loadTargetsByInjectionId?: (injectionIds: string[]) => Promise<Map<string, ArmReadinessTarget[]>>;
45
+ }
46
+ /**
47
+ * Read a focus's arm readiness. NEVER throws: an unreadable input answers "not
48
+ * ready" with the failure as its reason, and the caller logs it and re-tries on
49
+ * a later tick. Nothing is escalated -- an unscoped focus is a waiting state,
50
+ * not an incident.
51
+ */
52
+ export declare function readFocusArmReadiness(focusId: string, deps?: ArmReadinessDeps): Promise<FocusArmReadiness>;
53
+ /**
54
+ * What a live read of the focus's covered effects says about its bar.
55
+ *
56
+ * `readable` is carried separately from `statesABar` on purpose: "the tree says
57
+ * this focus states nothing" and "I could not read the tree" are the same
58
+ * DECISION (hold) and completely different FACTS. A caller that records the
59
+ * first as an operator-facing refusal must not record the second as one.
60
+ */
61
+ export interface FocusBarStanding {
62
+ /** True only when the covered set holds >= 1 effect and none is unstated. */
63
+ statesABar: boolean;
64
+ /** False when a read failed; the verdict is then a hold, not a finding. */
65
+ readable: boolean;
66
+ /** Human-readable why -- goes straight into a log line or a record. */
67
+ reason: string;
68
+ /** Covered undesired effects, however they stand. */
69
+ coveredEffectCount: number;
70
+ /** The covered effects whose `frt_statement` is null or blank. */
71
+ unstatedNodeIds: string[];
72
+ }
73
+ /**
74
+ * The database's rule, PURE, over the same inputs `assessArmReadiness` reads.
75
+ *
76
+ * Mirrors `stamp_focus_arm_baseline()` / `focus_arm_baseline_snapshot()`: the
77
+ * covered set is the union of every non-cancelled anchored delivery's injection
78
+ * targets (the injection-context read's `nowTargets`, which reports the
79
+ * UNDESIRED EFFECT targets -- the same node type the trigger counts), it must be
80
+ * non-empty, and every member must carry a non-blank restatement.
81
+ *
82
+ * It is a PRE-CHECK, never the authority: the trigger derives its own answer at
83
+ * the instant of the write, and the two are read seconds apart. A caller still
84
+ * handles the refusal arriving anyway.
85
+ */
86
+ export declare function assessFocusStatesABar(deliveries: ArmReadinessDelivery[], targetsByInjectionId: Map<string, ArmReadinessTarget[]>): FocusBarStanding;
87
+ /**
88
+ * Read whether a focus states a bar, live. NEVER throws: an unreadable input
89
+ * answers `{ statesABar: false, readable: false }` with the failure as its
90
+ * reason, so the caller holds rather than crossing on an unproven bar.
91
+ */
92
+ export declare function readFocusStatesABar(focusId: string, deps?: ArmReadinessDeps): Promise<FocusBarStanding>;
93
+ //# sourceMappingURL=arm-readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arm-readiness.d.ts","sourceRoot":"","sources":["../../src/prd/arm-readiness.ts"],"names":[],"mappings":"AAoEA,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,0EAA0E;IAC1E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAQD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,oBAAoB,EAAE,EAClC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,GACtD,iBAAiB,CA8BnB;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACtE,wBAAwB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;CACnG;AAyCD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAoB5B;AAKD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,UAAU,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,oBAAoB,EAAE,EAClC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,GACtD,gBAAgB,CA0ClB;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAsB3B"}