opencode-swarm 7.159.3 → 7.160.1

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/.opencode/skills/swarm-pr-review/SKILL.md +28 -29
  2. package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +21 -5
  3. package/dist/background/delegation-health.d.ts +1 -1
  4. package/dist/background/pending-delegations.d.ts +46 -1
  5. package/dist/background/pr-review-contract.d.ts +245 -2
  6. package/dist/cli/{coder-settlement-50p7dsya.js → coder-settlement-678ccmnf.js} +11 -10
  7. package/dist/cli/{config-doctor-a7drgs33.js → config-doctor-fr8dfrt2.js} +3 -3
  8. package/dist/cli/{core-madqgdsc.js → core-4j1hbhey.js} +2 -2
  9. package/dist/cli/{curation-policy-ray8h55z.js → curation-policy-47przjwg.js} +6 -6
  10. package/dist/cli/{curator-3sz7refy.js → curator-85d97240.js} +33 -32
  11. package/dist/cli/curator-llm-factory-s9s4s0q3.js +67 -0
  12. package/dist/cli/{evidence-summary-service-cwyjkdsa.js → evidence-summary-service-9dyt2kzh.js} +15 -14
  13. package/dist/cli/{gate-evidence-95k5ap1z.js → gate-evidence-a6paafg8.js} +7 -7
  14. package/dist/cli/guardrail-explain-4a2xdtew.js +68 -0
  15. package/dist/cli/{guardrail-log-nerqk9qb.js → guardrail-log-27nkntrx.js} +9 -6
  16. package/dist/cli/{guardrail-reset-chbc0mep.js → guardrail-reset-xn7k3hn8.js} +33 -32
  17. package/dist/cli/{hive-promoter-4rtxhw7n.js → hive-promoter-k57j3kp6.js} +33 -32
  18. package/dist/cli/{index-515nwvdp.js → index-497a3hhj.js} +19 -10
  19. package/dist/cli/{index-h96xp4t0.js → index-61c3d769.js} +875 -37
  20. package/dist/cli/{index-ve0xj03m.js → index-7ezv5j23.js} +4 -4
  21. package/dist/cli/{index-0zerbq1v.js → index-7h2armwf.js} +23 -14
  22. package/dist/cli/{index-ebxmfr4j.js → index-7npz9n4s.js} +5 -4
  23. package/dist/cli/{index-m9m3emns.js → index-7v0ex0jt.js} +2 -2
  24. package/dist/cli/{index-ebz97mks.js → index-8c9qzpy7.js} +1 -0
  25. package/dist/cli/{index-5hfqc3h3.js → index-98jmggma.js} +24 -7
  26. package/dist/cli/{index-8fyebh3w.js → index-awjx0wgk.js} +1 -1
  27. package/dist/cli/{index-av3gnekk.js → index-b5adxpy6.js} +1 -1
  28. package/dist/cli/{index-t3wk7q51.js → index-bqxffayb.js} +1 -1
  29. package/dist/cli/{index-yt75r1er.js → index-c9zp4xwc.js} +13 -2
  30. package/dist/cli/{index-9qw4sbg1.js → index-dh5q6z7y.js} +7 -7
  31. package/dist/cli/{index-prknc0xn.js → index-dke4wzkn.js} +108 -44
  32. package/dist/cli/{index-nvz4mp5w.js → index-dq93ar40.js} +6 -6
  33. package/dist/cli/{index-zswy6xgb.js → index-drqvph47.js} +7 -7
  34. package/dist/cli/{index-sn6mtxxc.js → index-e1ygmd4q.js} +35 -34
  35. package/dist/cli/{index-6jp5yxye.js → index-f72612zc.js} +16 -2
  36. package/dist/cli/{index-y2d381ce.js → index-gjx53y3c.js} +1 -1
  37. package/dist/cli/{index-xs32znyz.js → index-j3ss86kf.js} +1 -1
  38. package/dist/cli/{index-p3ym3y8b.js → index-jszabr0r.js} +4 -4
  39. package/dist/cli/{index-wwpe4am7.js → index-m1cw9fsh.js} +8 -8
  40. package/dist/cli/{index-8zw60wya.js → index-m84z3aa8.js} +13 -4
  41. package/dist/cli/index-mmr96pwr.js +785 -0
  42. package/dist/cli/{index-gk6gpe7r.js → index-nk498mx6.js} +2 -2
  43. package/dist/cli/{index-2jzmg2km.js → index-nnzdayvk.js} +6 -6
  44. package/dist/cli/{index-fnxmg8sz.js → index-ny0g8fdg.js} +5 -5
  45. package/dist/cli/{index-40t6s98s.js → index-pkz91fwm.js} +3 -3
  46. package/dist/cli/{index-bxpqq9th.js → index-pqjcyj0p.js} +3 -3
  47. package/dist/cli/{index-nhhek8yw.js → index-prv20xq6.js} +1 -1
  48. package/dist/cli/{index-mqfs5f8a.js → index-qc53dfzh.js} +2 -2
  49. package/dist/cli/{index-xqjhbfbx.js → index-v8dsmee1.js} +4 -4
  50. package/dist/cli/{index-qxpfmryw.js → index-wccdm7jv.js} +5 -5
  51. package/dist/cli/{index-rq4jcw64.js → index-z0bxbb9g.js} +4 -4
  52. package/dist/cli/{index-txwx9p21.js → index-zdv914xa.js} +585 -471
  53. package/dist/cli/{index-2fq4a3vk.js → index-znf683sm.js} +1 -1
  54. package/dist/cli/{index-v3ybemb1.js → index-zpzvpybn.js} +2 -2
  55. package/dist/cli/index.js +33 -32
  56. package/dist/cli/{knowledge-escalator-f80n84ch.js → knowledge-escalator-3q2x34cg.js} +14 -13
  57. package/dist/cli/{knowledge-events-1d7v2krw.js → knowledge-events-5y34w84b.js} +12 -11
  58. package/dist/cli/{knowledge-link-vm4caewt.js → knowledge-link-xezm8hr3.js} +5 -5
  59. package/dist/cli/{knowledge-store-66yxeet7.js → knowledge-store-fqv89q5k.js} +6 -6
  60. package/dist/cli/{knowledge-validator-p0xcx7jx.js → knowledge-validator-fsdx14tk.js} +8 -8
  61. package/dist/cli/{model-preflight-w85ecyxh.js → model-preflight-yqqchzjn.js} +1 -1
  62. package/dist/cli/{pending-delegations-vad1z71d.js → pending-delegations-6ae7wy5q.js} +7 -3
  63. package/dist/cli/{pr-review-reentry-authorization-kn3nny7h.js → pr-review-reentry-authorization-986tk381.js} +35 -33
  64. package/dist/cli/{pr-subscriptions-482gzvt6.js → pr-subscriptions-asjevc5p.js} +5 -4
  65. package/dist/cli/{runner-sn7a6zd0.js → runner-wsdcy2d6.js} +6 -6
  66. package/dist/cli/{scan-cursor-2v7995nb.js → scan-cursor-shn926r6.js} +7 -7
  67. package/dist/cli/{schema-dy8fqycb.js → schema-98tdb9h0.js} +4 -2
  68. package/dist/cli/{scope-persistence-baty62vx.js → scope-persistence-cn34xnwr.js} +10 -9
  69. package/dist/cli/{skill-generator-nwrvtqbz.js → skill-generator-kck7087c.js} +16 -15
  70. package/dist/cli/{telemetry-3rh94wv3.js → telemetry-gpr9s3sm.js} +3 -1
  71. package/dist/cli/{worktree-collision-ownership-cy24p5mr.js → worktree-collision-ownership-6b3kshcv.js} +6 -5
  72. package/dist/cli/{worktree-isolation-8jbx0s8d.js → worktree-isolation-he01qhss.js} +33 -32
  73. package/dist/config/constants.d.ts +8 -0
  74. package/dist/config/context-window.d.ts +11 -4
  75. package/dist/config/evidence-schema.d.ts +9 -6
  76. package/dist/config/schema.d.ts +8 -0
  77. package/dist/context-map/telemetry.d.ts +1 -1
  78. package/dist/health/learning-health.d.ts +356 -0
  79. package/dist/hooks/context-budget.d.ts +10 -1
  80. package/dist/hooks/curator.d.ts +2 -0
  81. package/dist/hooks/final-context-accounting.d.ts +2 -0
  82. package/dist/hooks/model-limits.d.ts +56 -25
  83. package/dist/hooks/pr-workflow-gate.d.ts +25 -1
  84. package/dist/hooks/skill-usage-pending.d.ts +1 -1
  85. package/dist/index.js +623 -609
  86. package/dist/observability/catalog.d.ts +2 -2
  87. package/dist/observability/ids.d.ts +17 -0
  88. package/dist/prm/trajectory-store.d.ts +1 -1
  89. package/dist/services/diagnose-service.d.ts +7 -0
  90. package/dist/services/status-service.d.ts +18 -0
  91. package/dist/telemetry.d.ts +52 -1
  92. package/dist/tools/context-status.d.ts +15 -1
  93. package/dist/tools/dispatch-lanes.d.ts +27 -3
  94. package/dist/tools/index.d.ts +1 -0
  95. package/dist/tools/manifest.d.ts +1 -0
  96. package/dist/tools/repo-graph/ontology.d.ts +6 -0
  97. package/dist/tools/repo-graph/pack-query.d.ts +36 -0
  98. package/dist/tools/repo-graph/types.d.ts +198 -1
  99. package/dist/tools/repo-graph.d.ts +5 -3
  100. package/dist/tools/sast-baseline.d.ts +2 -0
  101. package/dist/tools/sast-scan.d.ts +2 -2
  102. package/dist/tools/submit-pr-review-result.d.ts +5 -0
  103. package/dist/tools/tool-metadata.d.ts +8 -0
  104. package/opencode-swarm.schema.json +4 -0
  105. package/package.json +1 -1
  106. package/dist/cli/curator-llm-factory-pyp5kmra.js +0 -66
  107. package/dist/cli/guardrail-explain-a13kbmrt.js +0 -67
@@ -6,11 +6,11 @@ import {
6
6
  WORKTREE_PROVISIONING_OWNER_LEASE_MS,
7
7
  removeWorktreeProvisioningOwner,
8
8
  scanWorktreeProvisioningOwnersForRecovery
9
- } from "./index-8fyebh3w.js";
9
+ } from "./index-awjx0wgk.js";
10
10
  import {
11
11
  scanDelegationFallbacksForRecovery,
12
12
  scanDelegationsForRecovery
13
- } from "./index-h96xp4t0.js";
13
+ } from "./index-61c3d769.js";
14
14
  import"./index-ddszzne4.js";
15
15
  import"./index-dtn0pne5.js";
16
16
  import"./index-z6xqpmqg.js";
@@ -22,11 +22,12 @@ import {
22
22
  resolveGitExecutable
23
23
  } from "./index-9e6fdz2h.js";
24
24
  import"./index-4rhhvd1a.js";
25
+ import"./index-mmr96pwr.js";
25
26
  import"./index-zjygnfay.js";
26
- import"./index-9qw4sbg1.js";
27
- import"./index-av3gnekk.js";
27
+ import"./index-b5adxpy6.js";
28
+ import"./index-dh5q6z7y.js";
28
29
  import"./index-ed5ykebp.js";
29
- import"./index-prknc0xn.js";
30
+ import"./index-dke4wzkn.js";
30
31
  import"./index-7g4c7s5r.js";
31
32
  import"./index-bpmtbmy9.js";
32
33
  import"./index-zgwm4ryv.js";
@@ -21,64 +21,65 @@ import {
21
21
  sanitizeWorktreeTaskId,
22
22
  standardWorktreeByCallID,
23
23
  standardWorktreeSerializationSessions
24
- } from "./index-txwx9p21.js";
25
- import"./index-xs32znyz.js";
26
- import"./index-8zw60wya.js";
27
- import"./index-6jp5yxye.js";
28
- import"./index-wwpe4am7.js";
29
- import"./index-gk6gpe7r.js";
24
+ } from "./index-zdv914xa.js";
25
+ import"./index-j3ss86kf.js";
26
+ import"./index-m84z3aa8.js";
27
+ import"./index-f72612zc.js";
28
+ import"./index-m1cw9fsh.js";
29
+ import"./index-nk498mx6.js";
30
30
  import"./index-txdagbh7.js";
31
31
  import"./index-134d35c1.js";
32
32
  import"./index-nj6rmyeh.js";
33
- import"./index-xqjhbfbx.js";
34
- import"./index-fnxmg8sz.js";
35
- import"./index-m9m3emns.js";
33
+ import"./index-v8dsmee1.js";
34
+ import"./index-ny0g8fdg.js";
35
+ import"./index-7v0ex0jt.js";
36
36
  import"./index-70ha9e09.js";
37
37
  import"./index-c8s9a3zh.js";
38
38
  import"./index-9ss2m4rs.js";
39
- import"./index-515nwvdp.js";
39
+ import"./index-497a3hhj.js";
40
40
  import"./index-zsrtt42s.js";
41
- import"./index-nvz4mp5w.js";
41
+ import"./index-dq93ar40.js";
42
42
  import"./index-3f7hqtgg.js";
43
- import"./index-8fyebh3w.js";
44
- import"./index-p3ym3y8b.js";
45
- import"./index-2fq4a3vk.js";
43
+ import"./index-awjx0wgk.js";
44
+ import"./index-jszabr0r.js";
45
+ import"./index-znf683sm.js";
46
46
  import"./index-rtry5xyf.js";
47
- import"./index-rq4jcw64.js";
48
- import"./index-mqfs5f8a.js";
49
- import"./index-h96xp4t0.js";
47
+ import"./index-z0bxbb9g.js";
48
+ import"./index-qc53dfzh.js";
49
+ import"./index-61c3d769.js";
50
50
  import"./index-ddszzne4.js";
51
- import"./index-zswy6xgb.js";
52
- import"./index-bxpqq9th.js";
53
- import"./index-0zerbq1v.js";
51
+ import"./index-drqvph47.js";
52
+ import"./index-pqjcyj0p.js";
53
+ import"./index-7h2armwf.js";
54
54
  import"./index-556ja8an.js";
55
55
  import"./index-4fwbbad3.js";
56
56
  import"./index-b43rt5ph.js";
57
57
  import"./index-q7sjgr1y.js";
58
- import"./index-2jzmg2km.js";
59
- import"./index-5hfqc3h3.js";
58
+ import"./index-nnzdayvk.js";
59
+ import"./index-98jmggma.js";
60
60
  import {
61
61
  resolveWorktreeIsolationConfig
62
- } from "./index-40t6s98s.js";
63
- import"./index-ebz97mks.js";
62
+ } from "./index-pkz91fwm.js";
63
+ import"./index-8c9qzpy7.js";
64
64
  import"./index-n832052r.js";
65
65
  import"./index-dtn0pne5.js";
66
66
  import"./index-z6xqpmqg.js";
67
67
  import"./index-r3mvsbtq.js";
68
- import"./index-t3wk7q51.js";
69
- import"./index-ebxmfr4j.js";
68
+ import"./index-bqxffayb.js";
69
+ import"./index-7npz9n4s.js";
70
70
  import"./index-9e6fdz2h.js";
71
71
  import"./index-4rhhvd1a.js";
72
- import"./index-yt75r1er.js";
72
+ import"./index-mmr96pwr.js";
73
+ import"./index-c9zp4xwc.js";
73
74
  import"./index-zjygnfay.js";
74
75
  import"./index-ae75rja9.js";
75
- import"./index-nhhek8yw.js";
76
- import"./index-ve0xj03m.js";
76
+ import"./index-prv20xq6.js";
77
+ import"./index-7ezv5j23.js";
77
78
  import"./index-bk5tah7q.js";
78
- import"./index-9qw4sbg1.js";
79
- import"./index-av3gnekk.js";
79
+ import"./index-b5adxpy6.js";
80
+ import"./index-dh5q6z7y.js";
80
81
  import"./index-ed5ykebp.js";
81
- import"./index-prknc0xn.js";
82
+ import"./index-dke4wzkn.js";
82
83
  import"./index-7g4c7s5r.js";
83
84
  import"./index-bpmtbmy9.js";
84
85
  import"./index-zgwm4ryv.js";
@@ -17,6 +17,14 @@ export declare const TURBO_TOOL_NAMES: readonly ["lean_turbo_plan_lanes", "lean_
17
17
  export declare const TURBO_AGENT_TOOL_MAP: Partial<Record<AgentName, ToolName[]>>;
18
18
  export declare const SKILL_TOOL_NAMES: readonly ["skill_generate", "skill_list", "skill_apply", "skill_inspect", "skill_regenerate", "skill_retire", "skill_improve"];
19
19
  export declare const SKILL_AGENT_TOOL_MAP: Partial<Record<AgentName, ToolName[]>>;
20
+ export declare const PR_REVIEW_CHILD_TOOL_NAMES: readonly ["submit_pr_review_result"];
21
+ /**
22
+ * This map documents the role ownership required by the registry invariant.
23
+ * It is deliberately consumed only by dispatch_lanes' base/micro child tool
24
+ * overlay; merging it into ordinary agent configs would expose the submission
25
+ * capability outside an exact controller-bound delegation.
26
+ */
27
+ export declare const PR_REVIEW_CHILD_AGENT_TOOL_MAP: Partial<Record<AgentName, ToolName[]>>;
20
28
  /**
21
29
  * Human-readable descriptions for tools shown in the architect Available Tools block.
22
30
  * Used to generate the Available Tools section of the architect prompt at construction time.
@@ -100,7 +100,7 @@ export declare const DEFAULT_MODEL_CONTEXT_TOKENS = 128000;
100
100
  */
101
101
  export declare const MIN_PLAUSIBLE_CONTEXT_TOKENS = 1000;
102
102
  /** Which rung of the resolution order produced the value. */
103
- export type ContextWindowSource = 'user_provider_model' | 'user_model' | 'user_default' | 'live_model_limit' | 'static_table' | 'static_default';
103
+ export type ContextWindowSource = 'user_provider_model' | 'user_model' | 'user_default' | 'live_model_limit' | 'static_provider_cap' | 'static_native' | 'static_default';
104
104
  export interface ContextWindowResolution {
105
105
  /**
106
106
  * The resolved denominator, in tokens. Always a finite integer ≥ 1, so it is
@@ -135,10 +135,17 @@ export interface ContextWindowInputs {
135
135
  liveContextLimit?: unknown;
136
136
  /**
137
137
  * Last-resort static lookup. Injected rather than imported so this module
138
- * stays free of any dependency on `src/hooks/`. Returning `undefined` means
139
- * "no opinion" and falls through to `DEFAULT_MODEL_CONTEXT_TOKENS`.
138
+ * stays free of any dependency on `src/hooks/`. The lookup must say WHICH
139
+ * static table matched (`provider_cap` vs `native`) so the resolution source
140
+ * stays honest (#2044): the two tables have different staleness profiles and
141
+ * downstream provenance consumers (the `context_status` tool, the
142
+ * model-limit-fallback health alarm) distinguish them. Returning `undefined`
143
+ * means "no opinion" and falls through to `DEFAULT_MODEL_CONTEXT_TOKENS`.
140
144
  */
141
- fallbackLookup?: ((modelID?: string, providerID?: string) => number | undefined) | undefined;
145
+ fallbackLookup?: ((modelID?: string, providerID?: string) => {
146
+ tokens: number;
147
+ table: 'provider_cap' | 'native';
148
+ } | undefined) | undefined;
142
149
  }
143
150
  /**
144
151
  * True when `value` can be used as a divisor at all: a finite number strictly
@@ -227,9 +227,9 @@ export declare const RetrospectiveEvidenceSchema: z.ZodObject<{
227
227
  code_style: "code_style";
228
228
  }>;
229
229
  scope: z.ZodEnum<{
230
- global: "global";
231
- project: "project";
232
230
  session: "session";
231
+ project: "project";
232
+ global: "global";
233
233
  }>;
234
234
  }, z.core.$strip>>>;
235
235
  approaches_tried: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -424,6 +424,7 @@ export declare const SastEvidenceSchema: z.ZodObject<{
424
424
  remediation: z.ZodOptional<z.ZodString>;
425
425
  }, z.core.$strip>>>;
426
426
  baseline_used: z.ZodOptional<z.ZodBoolean>;
427
+ truncated_pre_existing: z.ZodOptional<z.ZodBoolean>;
427
428
  truncated_moved_findings: z.ZodOptional<z.ZodBoolean>;
428
429
  }, z.core.$strip>;
429
430
  export type SastEvidence = z.infer<typeof SastEvidenceSchema>;
@@ -767,9 +768,9 @@ export declare const EvidenceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
767
768
  code_style: "code_style";
768
769
  }>;
769
770
  scope: z.ZodEnum<{
770
- global: "global";
771
- project: "project";
772
771
  session: "session";
772
+ project: "project";
773
+ global: "global";
773
774
  }>;
774
775
  }, z.core.$strip>>>;
775
776
  approaches_tried: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -942,6 +943,7 @@ export declare const EvidenceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
942
943
  remediation: z.ZodOptional<z.ZodString>;
943
944
  }, z.core.$strip>>>;
944
945
  baseline_used: z.ZodOptional<z.ZodBoolean>;
946
+ truncated_pre_existing: z.ZodOptional<z.ZodBoolean>;
945
947
  truncated_moved_findings: z.ZodOptional<z.ZodBoolean>;
946
948
  }, z.core.$strip>, z.ZodObject<{
947
949
  task_id: z.ZodString;
@@ -1274,9 +1276,9 @@ export declare const EvidenceBundleSchema: z.ZodObject<{
1274
1276
  code_style: "code_style";
1275
1277
  }>;
1276
1278
  scope: z.ZodEnum<{
1277
- global: "global";
1278
- project: "project";
1279
1279
  session: "session";
1280
+ project: "project";
1281
+ global: "global";
1280
1282
  }>;
1281
1283
  }, z.core.$strip>>>;
1282
1284
  approaches_tried: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -1449,6 +1451,7 @@ export declare const EvidenceBundleSchema: z.ZodObject<{
1449
1451
  remediation: z.ZodOptional<z.ZodString>;
1450
1452
  }, z.core.$strip>>>;
1451
1453
  baseline_used: z.ZodOptional<z.ZodBoolean>;
1454
+ truncated_pre_existing: z.ZodOptional<z.ZodBoolean>;
1452
1455
  truncated_moved_findings: z.ZodOptional<z.ZodBoolean>;
1453
1456
  }, z.core.$strip>, z.ZodObject<{
1454
1457
  task_id: z.ZodString;
@@ -1813,6 +1813,13 @@ export declare const PrReviewResilienceConfigSchema: z.ZodObject<{
1813
1813
  max_retry_attempts_after_initial: z.ZodDefault<z.ZodNumber>;
1814
1814
  circuit_open_duration_ms: z.ZodDefault<z.ZodNumber>;
1815
1815
  }, z.core.$strict>;
1816
+ /**
1817
+ * Issue #2384: deprecated transcript-row settlement for Profile A PR-review
1818
+ * base/micro discovery lanes is an explicit compatibility opt-in. Omitted
1819
+ * config resolves false in consumers; legacy transcript parsing remains a
1820
+ * migration-only path rather than the default authority.
1821
+ */
1822
+ export declare const DEFAULT_PR_REVIEW_LEGACY_TRANSCRIPT_COMPATIBILITY = false;
1816
1823
  export declare const PluginConfigSchema: z.ZodObject<{
1817
1824
  $schema: z.ZodCatch<z.ZodOptional<z.ZodString>>;
1818
1825
  config_format_version: z.ZodDefault<z.ZodNumber>;
@@ -1911,6 +1918,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
1911
1918
  max_retry_attempts_after_initial: z.ZodDefault<z.ZodNumber>;
1912
1919
  circuit_open_duration_ms: z.ZodDefault<z.ZodNumber>;
1913
1920
  }, z.core.$strict>>;
1921
+ pr_review_legacy_transcript_compatibility: z.ZodOptional<z.ZodBoolean>;
1914
1922
  gates: z.ZodOptional<z.ZodObject<{
1915
1923
  syntax_check: z.ZodDefault<z.ZodObject<{
1916
1924
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -246,7 +246,7 @@ export declare function getTelemetrySummary(directory: string): TelemetrySummary
246
246
  * @param directory - Project root directory
247
247
  */
248
248
  export declare function finalizeContextTelemetry(directory: string): void;
249
- declare function emitContextTelemetryHealth(_directory: string, payload: {
249
+ declare function emitContextTelemetryHealth(directory: string, payload: {
250
250
  trigger: 'compaction' | 'close';
251
251
  accepted: number;
252
252
  compacted: number;
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Learning/operations health — bounded-window alarm registry (issue #2044).
3
+ *
4
+ * Lives in `src/health/`, NOT `src/observability/`: this module performs
5
+ * bounded artifact I/O (`.swarm/learning-health.json`) and imports telemetry,
6
+ * both of which the observability directory's zero-I/O contract forbids
7
+ * (enforced by `tests/unit/observability/no-io.test.ts`).
8
+ *
9
+ * This module owns the eight alarm families the observability series assigned
10
+ * to PR 16:
11
+ *
12
+ * 1. `headroom_dead_streak` — repeated zero/negative effective headroom
13
+ * 2. `model_limit_fallback` — context-limit resolution fell back off the
14
+ * host/live or user-override rungs
15
+ * 3. `retrieval_outcome_liveness` — retrieval → terminal receipt → application
16
+ * outcome chain stalled
17
+ * 4. `role_participation` — eligible workflow roles not participating
18
+ * 5. `promoted_fixture_share` — promoted-tier evidence dominated by
19
+ * non-field (fixture/synthetic-class) sources
20
+ * 6. `archive_activity_mismatch` — close archive empty/invalid while recorded
21
+ * activity predicted content
22
+ * 7. `recovery_ledger_pressure` — background delegation recovery ledger near
23
+ * its 4 MiB bound
24
+ * 8. `compaction_drop_coverage` — store compaction dropping/corrupting
25
+ * records across the six audited stores
26
+ *
27
+ * ## Contracts (issue #2044 items 5-10)
28
+ *
29
+ * - **Bounded windows with cooldown + hysteresis.** Every alarm raises only on
30
+ * its per-family condition inside a bounded window, re-emits at most once per
31
+ * cooldown interval (`sustained`), and recovers explicitly. Duplicate facts
32
+ * (same kind + timestamp) and late/out-of-order facts never storm alerts: the
33
+ * window is a monotonic append; a late fact counts but never rewinds
34
+ * `windowStartMs`.
35
+ * - **Per-canonical-project/session state with explicit eviction.** Session
36
+ * scopes are keyed `<projectRef>/<sessionRef>` when the producer knows its
37
+ * project directory and `u/<sessionRef>` when it does not (the chat-transform
38
+ * hooks receive no directory), so identical session ids under distinct
39
+ * projects never collide. Scope maps are FIFO-evicted at
40
+ * {@link MAX_HEALTH_SCOPES}; fact rings at {@link MAX_FACTS_PER_SCOPE}.
41
+ * - **No raw content.** Payloads and the persisted artifact carry counts,
42
+ * closed-vocabulary enums, booleans, millisecond timestamps, model/provider
43
+ * identity, and 16-hex salted session refs from
44
+ * `pseudonymousSessionRef` — never raw session ids, paths, queries, prompts,
45
+ * or responses (item 10).
46
+ * - **Persistence is transitions + compact per-scope counters ONLY** (item 9):
47
+ * what incident reconstruction needs. This module intentionally contains NO
48
+ * invocation-owned transient-retry or `nonTransientCircuit` state, so there is
49
+ * nothing of that class to persist or rehydrate — restarts resume health
50
+ * accumulation from the persisted counters, which is health state, not
51
+ * invocation state.
52
+ * - **Typed health-source registration, no fake sink** (item 8):
53
+ * {@link HEALTH_SOURCES} cites every real producer and reader file:line.
54
+ * There is deliberately NO `sink` source and NO "sink loss" value — issue
55
+ * #2047 / PR 19 must register its own real producer and reader.
56
+ *
57
+ * Every alarm is wired to production readers: the `/swarm status` Learning
58
+ * Health section and the `/swarm diagnose` learning-health check (both via
59
+ * {@link readLearningHealth}); `context_status` additionally exposes model-limit
60
+ * provenance directly.
61
+ */
62
+ import type { ContextWindowSource } from '../config/context-window';
63
+ /** The eight alarm families owned by this module. */
64
+ export type LearningHealthAlarmId = 'headroom_dead_streak' | 'model_limit_fallback' | 'retrieval_outcome_liveness' | 'role_participation' | 'promoted_fixture_share' | 'archive_activity_mismatch' | 'recovery_ledger_pressure' | 'compaction_drop_coverage';
65
+ export type LearningHealthTransition = 'raised' | 'sustained' | 'recovered';
66
+ export type LearningHealthSeverity = 'warning' | 'critical';
67
+ export type LearningHealthScopeClass = 'session' | 'identity' | 'project';
68
+ /** Identifier of a producer subsystem feeding alarms (typed registration). */
69
+ export type HealthSourceId = 'context_budget' | 'model_limits' | 'knowledge_receipts' | 'curator_compliance' | 'promotion_evidence' | 'close_archive' | 'delegation_ledger' | 'store_health_events';
70
+ export interface HealthSourceRegistration {
71
+ /** file:line of the live producer call site. */
72
+ readonly producer: string;
73
+ /** file:line of every live reader of this source's data. */
74
+ readonly readers: readonly string[];
75
+ /** Alarms this source feeds. */
76
+ readonly alarms: readonly LearningHealthAlarmId[];
77
+ }
78
+ export declare const HEALTH_SOURCES: Readonly<Record<HealthSourceId, HealthSourceRegistration>>;
79
+ /** Per-family thresholds. Documented constants, deliberately not user config. */
80
+ export declare const LEARNING_HEALTH_ALARM_CONFIG: Readonly<{
81
+ headroom_dead_streak: Readonly<{
82
+ windowMs: 600000;
83
+ raiseFacts: 3;
84
+ cooldownMs: 1800000;
85
+ severity: LearningHealthSeverity;
86
+ }>;
87
+ model_limit_fallback: Readonly<{
88
+ windowMs: 1800000;
89
+ cooldownMs: 3600000;
90
+ severity: LearningHealthSeverity;
91
+ }>;
92
+ retrieval_outcome_liveness: Readonly<{
93
+ windowMs: 1800000;
94
+ cooldownMs: 900000;
95
+ severity: LearningHealthSeverity;
96
+ gap2StalenessMs: 600000;
97
+ }>;
98
+ role_participation: Readonly<{
99
+ windowMs: 86400000;
100
+ raiseFacts: 2;
101
+ cooldownMs: 43200000;
102
+ severity: LearningHealthSeverity;
103
+ }>;
104
+ promoted_fixture_share: Readonly<{
105
+ windowMs: 604800000;
106
+ raiseShare: 0.5;
107
+ clearShare: 0.3;
108
+ minEvidence: 4;
109
+ cooldownMs: 86400000;
110
+ severity: LearningHealthSeverity;
111
+ }>;
112
+ archive_activity_mismatch: Readonly<{
113
+ windowMs: 0;
114
+ cooldownMs: 86400000;
115
+ severity: LearningHealthSeverity;
116
+ }>;
117
+ recovery_ledger_pressure: Readonly<{
118
+ windowMs: 900000;
119
+ raisePct: 0.8;
120
+ clearPct: 0.7;
121
+ cooldownMs: 1800000;
122
+ severity: LearningHealthSeverity;
123
+ }>;
124
+ compaction_drop_coverage: Readonly<{
125
+ windowMs: 3600000;
126
+ corruptRaise: 1;
127
+ droppedRaise: 100;
128
+ cooldownMs: 3600000;
129
+ severity: LearningHealthSeverity;
130
+ }>;
131
+ }>;
132
+ /**
133
+ * Receipt sources that count as FIELD evidence for the fixture-share alarm:
134
+ * real workflow actors in a real run. `delegate` is field-but-non-independent —
135
+ * the independence dimension belongs to the promotion gate
136
+ * (src/hooks/knowledge-types.ts:410-418) and is deliberately NOT duplicated
137
+ * here.
138
+ */
139
+ export declare const FIELD_RECEIPT_SOURCES: ReadonlySet<string>;
140
+ /**
141
+ * Receipt sources that count as NON-FIELD (fixture/synthetic-class) evidence:
142
+ * authorized overrides, manual/migration imports, administrative gate
143
+ * releases, and `unknown` (fail-closed — a forged or missing label never counts
144
+ * as field).
145
+ */
146
+ export declare const NON_FIELD_RECEIPT_SOURCES: ReadonlySet<string>;
147
+ interface PersistedTransition {
148
+ alarm: LearningHealthAlarmId;
149
+ transition: LearningHealthTransition;
150
+ severity: LearningHealthSeverity;
151
+ atMs: number;
152
+ coverageFacts: number;
153
+ }
154
+ export declare const _internals: {
155
+ now: () => number;
156
+ emitTelemetry: (payload: Record<string, unknown>) => void;
157
+ writeArtifact: (directory: string, contents: string) => Promise<void>;
158
+ readArtifact: (directory: string) => Promise<string | null>;
159
+ };
160
+ /** Alarm payload detail — counts/enums/refs only, never raw content. */
161
+ export interface AlarmEmitDetail {
162
+ sessionRef?: string;
163
+ model?: string;
164
+ provider?: string;
165
+ limitSource?: string;
166
+ denominatorFallback?: boolean;
167
+ pressurePct?: number;
168
+ band?: string;
169
+ sharePct?: number;
170
+ fieldCount?: number;
171
+ nonFieldCount?: number;
172
+ store?: string;
173
+ dropped?: number;
174
+ corrupt?: number;
175
+ retained?: number;
176
+ accepted?: number;
177
+ gapType?: 'membership_to_terminal' | 'terminal_to_application';
178
+ role?: string;
179
+ phase?: number;
180
+ reason?: string;
181
+ }
182
+ /** Serialize current health state to `.swarm/learning-health.json` (fire-and-forget). */
183
+ export declare function persistLearningHealth(directory: string): Promise<void>;
184
+ /**
185
+ * Observe one context-budget evaluation. `dead` = usagePercent ≥ 1.0
186
+ * (zero/negative effective headroom). The alarm raises after
187
+ * {@link LEARNING_HEALTH_ALARM_CONFIG.headroom_dead_streak.raiseFacts} distinct
188
+ * dead observations in the window and recovers on a healthy observation below
189
+ * the warn threshold. Attribution, not suppression: the payload always carries
190
+ * `limit_source` and `denominator_fallback` so an operator can tell real
191
+ * exhaustion from a stale static-table denominator — the "fallback hides
192
+ * dead-headroom loops" defect this alarm exists to surface.
193
+ */
194
+ export declare function observeContextHeadroom(input: {
195
+ sessionID: string;
196
+ /** Project directory when the producer knows it (threaded from the plugin
197
+ * wiring at handler construction); the chat-transform input itself carries
198
+ * none. Scopes key by `<projectRef>/<sessionRef>` when present. */
199
+ directory?: string;
200
+ usagePercent: number;
201
+ limit: number;
202
+ limitSource: string;
203
+ warnThreshold: number;
204
+ }): void;
205
+ /**
206
+ * Observe one model-limit resolution. Fallback-active when the resolution came
207
+ * from the static tables or the flat default (not host/live, not a user
208
+ * override); recovery when the same identity later resolves from host/override.
209
+ */
210
+ export declare function observeModelLimitResolution(input: {
211
+ modelID?: string;
212
+ providerID?: string;
213
+ /** Project directory when the producer knows it (threaded through
214
+ * resolveModelLimit); identity scopes key project-prefixed when present. */
215
+ directory?: string;
216
+ resolution: ContextWindowSource;
217
+ /** Which override key class matched (compound/model/default) — the alias
218
+ * provenance for user-authored limits (issue #2044 item 2). */
219
+ aliasKeyClass?: 'compound' | 'model' | 'default';
220
+ /** True when a user-authored override failed usability validation and was
221
+ * skipped (never coerced) — surfaced durably, not just as a warning. */
222
+ invalidOverride?: boolean;
223
+ }): void;
224
+ /**
225
+ * Observe one receipt-ledger transition. Called from the ledger's post-lock
226
+ * observation drain where the project directory and the observation record are
227
+ * both in hand. Gap-1: membership committed without a terminal within the
228
+ * window. Gap-2: a terminal with outcome 'applied' without an authoritative
229
+ * application closure — either an `architect_marker`-sourced application
230
+ * outcome or any gate release (the release valve is one-way, so a release MUST
231
+ * count as closure). Gap-2 opens only past the gate's staleness horizon.
232
+ */
233
+ export declare function observeReceiptTransition(input: {
234
+ directory: string;
235
+ kind: string;
236
+ traceId: string;
237
+ receiptOutcome?: string;
238
+ receiptSource?: string;
239
+ /**
240
+ * OPTIONAL membership commit time for gap-2 staleness anchoring. Intentionally
241
+ * not populated by the current ledger drain (PRR-008): anchoring gap-2
242
+ * eligibility to the TERMINAL time (the fallback when absent) is the
243
+ * conservative bound — it can only delay eligibility, never fire the alarm
244
+ * before the application gate's own staleness escalation has had its
245
+ * window. Kept as an explicit input so a future ledger observation can
246
+ * tighten the anchor without an API change.
247
+ */
248
+ membershipCommittedAtMs?: number;
249
+ atMs?: number;
250
+ }): void;
251
+ /**
252
+ * Observe one curator phase-compliance pass. `gaps` carries the compliance
253
+ * observation types counted as participation gaps; `agentsUsed` is the set of
254
+ * roles that DID participate. The structural-zero guard keeps a single review
255
+ * window with no eligible opportunity from ever raising.
256
+ */
257
+ export declare function observeCuratorCompliance(input: {
258
+ directory: string;
259
+ phase?: number;
260
+ gapTypes: readonly string[];
261
+ agentsUsed: readonly string[];
262
+ }): void;
263
+ /**
264
+ * Observe one promotion-evidence record. Classification is closed-vocabulary:
265
+ * field sources are real workflow actors; everything else (overrides, manual
266
+ * and migration imports, administrative releases, unknown) is non-field and
267
+ * `unknown` NEVER counts as field (fail-closed against forged labels).
268
+ */
269
+ export declare function observePromotionEvidence(input: {
270
+ directory: string;
271
+ receiptSource: string | undefined;
272
+ }): void;
273
+ /**
274
+ * Observe one close-archive result. Raises when the archive is empty/invalid
275
+ * while recorded activity predicted content; recovers on the next valid,
276
+ * non-empty archive. Late-arriving activity never retro-raises — the payload
277
+ * records what was known at decision time.
278
+ */
279
+ export declare function observeCloseArchive(input: {
280
+ directory: string;
281
+ archiveValid: boolean;
282
+ archiveEmpty: boolean;
283
+ activityPredictsContent: boolean;
284
+ }): void;
285
+ /**
286
+ * Observe one delegation-ledger health collection. Raises at pressure ≥ 0.8
287
+ * (near the 4 MiB recovery bound) or on the compact-overdue / fail-closed
288
+ * bands; clears below 0.7 (hysteresis). `uncertain` surfaces recovery
289
+ * observation failures as closed reason codes.
290
+ */
291
+ export declare function observeDelegationLedgerPressure(input: {
292
+ directory: string;
293
+ pressurePct: number;
294
+ band: string;
295
+ uncertain?: boolean;
296
+ }): void;
297
+ /**
298
+ * Direct, directory-bearing store-health observation (final-critic finding 3):
299
+ * the six audited stores call this at their health-event emit sites, so family
300
+ * 8 is fed from its real producers from the FIRST event — not only after an
301
+ * operator opens a status surface.
302
+ */
303
+ export declare function observeStoreHealth(input: {
304
+ directory: string;
305
+ kind: string;
306
+ payload: Record<string, unknown>;
307
+ }): void;
308
+ declare function observeStoreHealthEvent(event: string, data: Record<string, unknown>, directory?: string): void;
309
+ /**
310
+ * Idempotent no-op registration point (PR #2446 review): family 8 is fed
311
+ * DIRECTLY by all six audited stores via {@link observeStoreHealth}, so no
312
+ * telemetry listener is attached. The historical listener double-fed every
313
+ * store event (direct + listener observed the same emission into two scope
314
+ * namespaces); it was removed. This function remains as the documented
315
+ * registration seam so future feeds have one call site to wire — it performs
316
+ * no work today and never touches the plugin init path.
317
+ */
318
+ export declare function ensureLearningHealth(): void;
319
+ /**
320
+ * Test teardown: clear all in-memory health state. Never used in production
321
+ * code paths.
322
+ */
323
+ export declare function resetLearningHealthForTest(): void;
324
+ export interface ActiveLearningHealthAlarm {
325
+ alarm: LearningHealthAlarmId;
326
+ severity: LearningHealthSeverity;
327
+ scopeClass: LearningHealthScopeClass;
328
+ scopeRef: string;
329
+ ageMs: number;
330
+ coverageFacts: number;
331
+ transitionCount: number;
332
+ }
333
+ export interface LearningHealthSnapshot {
334
+ activeAlarms: readonly ActiveLearningHealthAlarm[];
335
+ totalTransitions: number;
336
+ updatedAtMs: number;
337
+ }
338
+ /**
339
+ * Read learning health for a project: rehydrate any persisted artifact,
340
+ * lazily evaluate window-based alarms (liveness gaps age into raises without a
341
+ * timer), and persist the refreshed state. Fail-open: any error yields an
342
+ * empty snapshot.
343
+ */
344
+ export declare function readLearningHealth(directory: string): Promise<LearningHealthSnapshot>;
345
+ /** All transitions in the bounded ring (newest last). Test/diagnostic accessor. */
346
+ export declare function getLearningHealthTransitions(): readonly PersistedTransition[];
347
+ /**
348
+ * Tier-0 test exports (writing-tests skill): pure-or-near-pure internals that
349
+ * tests exercise directly. `observeStoreHealthEvent` is the shared core the
350
+ * public `observeStoreHealth` wraps; tests use it to drive family-8 logic
351
+ * without constructing a directory scope.
352
+ */
353
+ export declare const _test_exports: {
354
+ observeStoreHealthEvent: typeof observeStoreHealthEvent;
355
+ };
356
+ export {};
@@ -6,6 +6,7 @@
6
6
  * to provide proactive context management guidance to the architect agent.
7
7
  */
8
8
  import type { PluginConfig } from '../config';
9
+ import { observeContextHeadroom } from '../health/learning-health';
9
10
  import { telemetry } from '../telemetry';
10
11
  interface MessageInfo {
11
12
  role: string;
@@ -34,13 +35,21 @@ interface MessageWithParts {
34
35
  }
35
36
  export declare const _internals: {
36
37
  telemetryContextPruned: typeof telemetry.contextPruned;
38
+ observeContextHeadroom: typeof observeContextHeadroom;
37
39
  };
38
40
  /**
39
41
  * Creates the experimental.chat.messages.transform hook for context budget tracking.
40
42
  * Injects warnings when context usage exceeds configured thresholds.
41
43
  * Only operates on messages for the architect agent.
42
44
  */
43
- export declare function createContextBudgetHandler(config: PluginConfig, resolveAgentModel?: (agentName: string) => string | undefined): (_input: Record<string, never>, _output: {
45
+ export declare function createContextBudgetHandler(config: PluginConfig, resolveAgentModel?: (agentName: string) => string | undefined,
46
+ /**
47
+ * Project directory (threaded from the plugin wiring at handler
48
+ * construction — the chat-transform hook input itself carries none). Used
49
+ * ONLY to scope + persist the #2044 headroom health observation; every
50
+ * budget behavior is identical without it.
51
+ */
52
+ directory?: string): (_input: Record<string, never>, _output: {
44
53
  messages?: MessageWithParts[];
45
54
  }) => Promise<void>;
46
55
  export {};