opencode-swarm 7.107.3 → 7.107.4

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 (61) hide show
  1. package/.opencode/skills/consult/SKILL.md +10 -0
  2. package/.opencode/skills/council/SKILL.md +10 -0
  3. package/.opencode/skills/engineering-conventions/SKILL.md +20 -0
  4. package/README.md +2 -2
  5. package/dist/agents/agent-output-schema.d.ts +1 -1
  6. package/dist/cli/{config-doctor-cntnpyvj.js → config-doctor-kdq3vae4.js} +3 -2
  7. package/dist/cli/{curator-llm-factory-x9tk7e6m.js → curator-llm-factory-abw56kg0.js} +16 -11
  8. package/dist/cli/{curator-1nr4qszq.js → curator-rb05fjjk.js} +16 -11
  9. package/dist/cli/{dispatch-e4ejrsz8.js → dispatch-anmxxhen.js} +56 -13
  10. package/dist/cli/{evidence-summary-service-9r28ds8t.js → evidence-summary-service-nwdfnbz1.js} +2 -2
  11. package/dist/cli/gate-evidence-ywys9vfs.js +1 -1
  12. package/dist/cli/{guardrail-explain-etdrhd4d.js → guardrail-explain-dayy7zw4.js} +17 -12
  13. package/dist/cli/{guardrail-log-2rns4g6d.js → guardrail-log-fjypsmek.js} +4 -3
  14. package/dist/cli/{hive-promoter-j4e6rfa6.js → hive-promoter-34bdmw1w.js} +16 -11
  15. package/dist/cli/{index-502f6np6.js → index-19vxtwa6.js} +21 -16
  16. package/dist/cli/{index-tgtmbf3r.js → index-4vsgp5a8.js} +1 -1
  17. package/dist/cli/index-bfwt3abw.js +14 -0
  18. package/dist/cli/{index-9wstcavp.js → index-bpgqbwmf.js} +115 -1019
  19. package/dist/cli/index-bq8kd9r9.js +199 -0
  20. package/dist/cli/index-dfdg4ws5.js +741 -0
  21. package/dist/cli/{index-w15984gg.js → index-f45hbd5x.js} +2 -2
  22. package/dist/cli/{index-cyzzdbvw.js → index-gyzxeza3.js} +354 -116
  23. package/dist/cli/index-kxm3bdjh.js +631 -0
  24. package/dist/cli/index-n1sptn1w.js +147 -0
  25. package/dist/cli/{index-2560cctg.js → index-pchpahdf.js} +11 -0
  26. package/dist/cli/{index-esg1554h.js → index-wvxhynxq.js} +1 -1
  27. package/dist/cli/{index-8w4d325g.js → index-xg18az81.js} +61 -22
  28. package/dist/cli/{index-f7nma02k.js → index-xmarctsf.js} +137 -175
  29. package/dist/cli/{index-m1xjr58n.js → index-zej8cy0j.js} +1 -1
  30. package/dist/cli/index.js +17 -12
  31. package/dist/cli/knowledge-escalator-3sgwrgy9.js +32 -0
  32. package/dist/cli/knowledge-events-kfc6xmkw.js +62 -0
  33. package/dist/cli/{knowledge-store-tsa8ezka.js → knowledge-store-kyacem71.js} +3 -1
  34. package/dist/cli/knowledge-validator-ez3ws8ef.js +57 -0
  35. package/dist/cli/{pr-subscriptions-0dpn4epk.js → pr-subscriptions-bpvazmsw.js} +2 -2
  36. package/dist/cli/{schema-vw2ffhe9.js → schema-x0ekqzvs.js} +2 -1
  37. package/dist/cli/{skill-generator-y6mmq8n5.js → skill-generator-x83re96d.js} +6 -2
  38. package/dist/commands/knowledge.d.ts +5 -1
  39. package/dist/commands/registry.d.ts +2 -2
  40. package/dist/config/evidence-schema.d.ts +9 -9
  41. package/dist/config/schema.d.ts +42 -12
  42. package/dist/hooks/knowledge-curator.d.ts +27 -0
  43. package/dist/hooks/knowledge-escalator.d.ts +16 -0
  44. package/dist/hooks/knowledge-events.d.ts +11 -0
  45. package/dist/hooks/knowledge-reader.d.ts +0 -17
  46. package/dist/hooks/knowledge-store.d.ts +16 -1
  47. package/dist/hooks/knowledge-types.d.ts +85 -0
  48. package/dist/hooks/knowledge-validator.d.ts +15 -0
  49. package/dist/hooks/skill-usage-log.d.ts +3 -0
  50. package/dist/index.js +307 -305
  51. package/dist/memory/consolidation.d.ts +1 -1
  52. package/dist/memory/schema.d.ts +4 -4
  53. package/dist/sast/rules/rust.d.ts +6 -0
  54. package/dist/tools/knowledge-archive.d.ts +6 -2
  55. package/dist/tools/lint.d.ts +2 -2
  56. package/dist/tools/secretscan.d.ts +16 -0
  57. package/dist/tools/test-runner.d.ts +1 -1
  58. package/package.json +1 -1
  59. package/dist/cli/{index-hkpw4wwa.js → index-4r5z8sgw.js} +3 -3
  60. package/dist/cli/{index-kzfkggjx.js → index-9b7a6agd.js} +3 -3
  61. package/dist/cli/{pending-delegations-ws51m1e1.js → pending-delegations-vfnpm8zt.js} +3 -3
@@ -0,0 +1,57 @@
1
+ // @bun
2
+ import {
3
+ ACTIONABLE_LIST_MAX,
4
+ ACTIONABLE_STRING_MAX,
5
+ ALLOWED_SKILL_PATH_PREFIXES,
6
+ DANGEROUS_COMMAND_ERROR_PATTERNS,
7
+ DANGEROUS_COMMAND_PATTERNS,
8
+ DANGEROUS_COMMAND_WARNING_PATTERNS,
9
+ INJECTION_PATTERNS,
10
+ INVISIBLE_FORMAT_CHARS,
11
+ SECURITY_DEGRADING_PATTERNS,
12
+ _internals,
13
+ appendUnactionable,
14
+ auditEntryHealth,
15
+ quarantineEntry,
16
+ resolveUnactionablePath,
17
+ restoreEntry,
18
+ unarchiveEntry,
19
+ validateActionability,
20
+ validateActionableFields,
21
+ validateLesson,
22
+ validateSkillCandidatePath,
23
+ validateSkillPath
24
+ } from "./index-dfdg4ws5.js";
25
+ import"./index-xmarctsf.js";
26
+ import"./index-n1sptn1w.js";
27
+ import"./index-bfwt3abw.js";
28
+ import"./index-9b7qp18e.js";
29
+ import"./index-jtqkh8jf.js";
30
+ import"./index-zgwm4ryv.js";
31
+ import"./index-3naa2ajc.js";
32
+ import"./index-b9v501fr.js";
33
+ import"./index-vn263hqt.js";
34
+ import"./index-a76rekgs.js";
35
+ export {
36
+ validateSkillPath,
37
+ validateSkillCandidatePath,
38
+ validateLesson,
39
+ validateActionableFields,
40
+ validateActionability,
41
+ unarchiveEntry,
42
+ restoreEntry,
43
+ resolveUnactionablePath,
44
+ quarantineEntry,
45
+ auditEntryHealth,
46
+ appendUnactionable,
47
+ _internals,
48
+ SECURITY_DEGRADING_PATTERNS,
49
+ INVISIBLE_FORMAT_CHARS,
50
+ INJECTION_PATTERNS,
51
+ DANGEROUS_COMMAND_WARNING_PATTERNS,
52
+ DANGEROUS_COMMAND_PATTERNS,
53
+ DANGEROUS_COMMAND_ERROR_PATTERNS,
54
+ ALLOWED_SKILL_PATH_PREFIXES,
55
+ ACTIONABLE_STRING_MAX,
56
+ ACTIONABLE_LIST_MAX
57
+ };
@@ -9,14 +9,14 @@ import {
9
9
  sweepStale,
10
10
  unsubscribe,
11
11
  updateSnapshot
12
- } from "./index-hkpw4wwa.js";
12
+ } from "./index-4r5z8sgw.js";
13
13
  import"./index-57ymmh7h.js";
14
14
  import"./index-5e4e2hvv.js";
15
15
  import"./index-p0arc26j.js";
16
16
  import"./index-jtqkh8jf.js";
17
17
  import"./index-zgwm4ryv.js";
18
- import"./index-3naa2ajc.js";
19
18
  import"./index-293f68mj.js";
19
+ import"./index-3naa2ajc.js";
20
20
  import"./index-b9v501fr.js";
21
21
  import"./index-vn263hqt.js";
22
22
  import"./index-a76rekgs.js";
@@ -85,7 +85,8 @@ import {
85
85
  resolveGeneratedAgentRole,
86
86
  resolveGuardrailsConfig,
87
87
  stripKnownSwarmPrefix
88
- } from "./index-2560cctg.js";
88
+ } from "./index-pchpahdf.js";
89
+ import"./index-bfwt3abw.js";
89
90
  import"./index-p0arc26j.js";
90
91
  import"./index-293f68mj.js";
91
92
  import"./index-a76rekgs.js";
@@ -27,8 +27,12 @@ import {
27
27
  retireSkill,
28
28
  sanitizeSlug,
29
29
  selectCandidateEntries
30
- } from "./index-9wstcavp.js";
31
- import"./index-f7nma02k.js";
30
+ } from "./index-bpgqbwmf.js";
31
+ import"./index-dfdg4ws5.js";
32
+ import"./index-kxm3bdjh.js";
33
+ import"./index-xmarctsf.js";
34
+ import"./index-n1sptn1w.js";
35
+ import"./index-bfwt3abw.js";
32
36
  import"./index-9b7qp18e.js";
33
37
  import"./index-jtqkh8jf.js";
34
38
  import"./index-zgwm4ryv.js";
@@ -6,7 +6,11 @@
6
6
  export declare function handleKnowledgeQuarantineCommand(directory: string, args: string[]): Promise<string>;
7
7
  /**
8
8
  * Handles /swarm knowledge restore <id> command.
9
- * Restores a quarantined knowledge entry.
9
+ * Restores a quarantined OR archived knowledge entry.
10
+ * - If the matched entry is `archived` in `knowledge.jsonl`, calls
11
+ * `unarchiveEntry` (G6 #1716) to restore it to its pre-archive status.
12
+ * - Otherwise falls through to the quarantine path: reads
13
+ * `knowledge-quarantined.jsonl` and calls `restoreEntry`.
10
14
  * Accepts a full ID or a unique prefix.
11
15
  */
12
16
  export declare function handleKnowledgeRestoreCommand(directory: string, args: string[]): Promise<string>;
@@ -739,9 +739,9 @@ export declare const COMMAND_REGISTRY: {
739
739
  };
740
740
  readonly 'knowledge restore': {
741
741
  readonly handler: (ctx: CommandContext) => Promise<string>;
742
- readonly description: "Restore a quarantined knowledge entry <id>";
742
+ readonly description: "Restore a quarantined or archived knowledge entry <id>";
743
743
  readonly subcommandOf: "knowledge";
744
- readonly details: "Restores a quarantined knowledge entry back to the active knowledge store by ID. Validates entry ID format (1-64 alphanumeric/hyphen/underscore). Entry must currently be in quarantine state.";
744
+ readonly details: "Restores a quarantined or archived knowledge entry back to the active knowledge store by ID. Dispatches by current status: an 'archived' entry is restored to its pre-archive status; a 'quarantined' entry is restored from the quarantine sidecar. Validates entry ID format (1-64 alphanumeric/hyphen/underscore).";
745
745
  readonly args: "<entry-id>";
746
746
  readonly category: "utility";
747
747
  };
@@ -220,11 +220,11 @@ export declare const RetrospectiveEvidenceSchema: z.ZodObject<{
220
220
  user_directives: z.ZodDefault<z.ZodArray<z.ZodObject<{
221
221
  directive: z.ZodString;
222
222
  category: z.ZodEnum<{
223
- tooling: "tooling";
224
- code_style: "code_style";
225
- architecture: "architecture";
226
223
  process: "process";
224
+ architecture: "architecture";
225
+ tooling: "tooling";
227
226
  other: "other";
227
+ code_style: "code_style";
228
228
  }>;
229
229
  scope: z.ZodEnum<{
230
230
  global: "global";
@@ -738,11 +738,11 @@ export declare const EvidenceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
738
738
  user_directives: z.ZodDefault<z.ZodArray<z.ZodObject<{
739
739
  directive: z.ZodString;
740
740
  category: z.ZodEnum<{
741
- tooling: "tooling";
742
- code_style: "code_style";
743
- architecture: "architecture";
744
741
  process: "process";
742
+ architecture: "architecture";
743
+ tooling: "tooling";
745
744
  other: "other";
745
+ code_style: "code_style";
746
746
  }>;
747
747
  scope: z.ZodEnum<{
748
748
  global: "global";
@@ -1223,11 +1223,11 @@ export declare const EvidenceBundleSchema: z.ZodObject<{
1223
1223
  user_directives: z.ZodDefault<z.ZodArray<z.ZodObject<{
1224
1224
  directive: z.ZodString;
1225
1225
  category: z.ZodEnum<{
1226
- tooling: "tooling";
1227
- code_style: "code_style";
1228
- architecture: "architecture";
1229
1226
  process: "process";
1227
+ architecture: "architecture";
1228
+ tooling: "tooling";
1230
1229
  other: "other";
1230
+ code_style: "code_style";
1231
1231
  }>;
1232
1232
  scope: z.ZodEnum<{
1233
1233
  global: "global";
@@ -328,8 +328,8 @@ export declare const PhaseCompleteConfigSchema: z.ZodObject<{
328
328
  }>>>;
329
329
  require_docs: z.ZodDefault<z.ZodBoolean>;
330
330
  policy: z.ZodDefault<z.ZodEnum<{
331
- enforce: "enforce";
332
331
  warn: "warn";
332
+ enforce: "enforce";
333
333
  }>>;
334
334
  regression_sweep: z.ZodOptional<z.ZodObject<{
335
335
  enforce: z.ZodDefault<z.ZodBoolean>;
@@ -600,6 +600,21 @@ export declare const KnowledgeConfigSchema: z.ZodObject<{
600
600
  default_max_phases: z.ZodDefault<z.ZodNumber>;
601
601
  todo_max_phases: z.ZodDefault<z.ZodNumber>;
602
602
  sweep_enabled: z.ZodDefault<z.ZodBoolean>;
603
+ confidence_floor_action: z.ZodDefault<z.ZodEnum<{
604
+ none: "none";
605
+ demote: "demote";
606
+ quarantine: "quarantine";
607
+ }>>;
608
+ confidence_floor_min_outcomes: z.ZodDefault<z.ZodNumber>;
609
+ confidence_floor_signal_threshold: z.ZodDefault<z.ZodNumber>;
610
+ contradiction_threshold_action: z.ZodDefault<z.ZodEnum<{
611
+ quarantine: "quarantine";
612
+ tag_only: "tag_only";
613
+ }>>;
614
+ contradiction_quarantine_threshold: z.ZodDefault<z.ZodNumber>;
615
+ contradiction_quarantine_window_days: z.ZodDefault<z.ZodNumber>;
616
+ promoted_demotion_min_negative_phases: z.ZodDefault<z.ZodNumber>;
617
+ promoted_demotion_signal_threshold: z.ZodDefault<z.ZodNumber>;
603
618
  realtime_learning_nudge: z.ZodDefault<z.ZodObject<{
604
619
  enabled: z.ZodDefault<z.ZodBoolean>;
605
620
  first_after_tool_calls: z.ZodDefault<z.ZodNumber>;
@@ -781,8 +796,8 @@ export type ArchitecturalSupervisionConfig = z.infer<typeof ArchitecturalSupervi
781
796
  export declare const KnowledgeApplicationConfigSchema: z.ZodObject<{
782
797
  enabled: z.ZodDefault<z.ZodBoolean>;
783
798
  mode: z.ZodDefault<z.ZodEnum<{
784
- enforce: "enforce";
785
799
  warn: "warn";
800
+ enforce: "enforce";
786
801
  }>>;
787
802
  min_confidence: z.ZodDefault<z.ZodNumber>;
788
803
  critical_requires_ack: z.ZodDefault<z.ZodBoolean>;
@@ -1284,12 +1299,12 @@ export declare const ExternalSkillCandidateSourceTypeSchema: z.ZodEnum<{
1284
1299
  export type ExternalSkillCandidateSourceType = z.infer<typeof ExternalSkillCandidateSourceTypeSchema>;
1285
1300
  /** Evaluation verdict for an external skill candidate. */
1286
1301
  export declare const ExternalSkillCandidateEvaluationVerdictSchema: z.ZodEnum<{
1302
+ promoted: "promoted";
1303
+ quarantined: "quarantined";
1287
1304
  pending: "pending";
1288
1305
  in_review: "in_review";
1289
- quarantined: "quarantined";
1290
1306
  passed: "passed";
1291
1307
  rejected: "rejected";
1292
- promoted: "promoted";
1293
1308
  revoked: "revoked";
1294
1309
  }>;
1295
1310
  export type ExternalSkillCandidateEvaluationVerdict = z.infer<typeof ExternalSkillCandidateEvaluationVerdictSchema>;
@@ -1331,22 +1346,22 @@ export declare const ExternalSkillCandidateSchema: z.ZodObject<{
1331
1346
  skill_body: z.ZodString;
1332
1347
  risk_flags: z.ZodDefault<z.ZodArray<z.ZodString>>;
1333
1348
  evaluation_verdict: z.ZodDefault<z.ZodEnum<{
1349
+ promoted: "promoted";
1350
+ quarantined: "quarantined";
1334
1351
  pending: "pending";
1335
1352
  in_review: "in_review";
1336
- quarantined: "quarantined";
1337
1353
  passed: "passed";
1338
1354
  rejected: "rejected";
1339
- promoted: "promoted";
1340
1355
  revoked: "revoked";
1341
1356
  }>>;
1342
1357
  evaluation_history: z.ZodDefault<z.ZodArray<z.ZodObject<{
1343
1358
  verdict: z.ZodEnum<{
1359
+ promoted: "promoted";
1360
+ quarantined: "quarantined";
1344
1361
  pending: "pending";
1345
1362
  in_review: "in_review";
1346
- quarantined: "quarantined";
1347
1363
  passed: "passed";
1348
1364
  rejected: "rejected";
1349
- promoted: "promoted";
1350
1365
  revoked: "revoked";
1351
1366
  }>;
1352
1367
  timestamp: z.ZodString;
@@ -1354,12 +1369,12 @@ export declare const ExternalSkillCandidateSchema: z.ZodObject<{
1354
1369
  reason: z.ZodOptional<z.ZodString>;
1355
1370
  candidate_id: z.ZodOptional<z.ZodString>;
1356
1371
  original_verdict: z.ZodOptional<z.ZodEnum<{
1372
+ promoted: "promoted";
1373
+ quarantined: "quarantined";
1357
1374
  pending: "pending";
1358
1375
  in_review: "in_review";
1359
- quarantined: "quarantined";
1360
1376
  passed: "passed";
1361
1377
  rejected: "rejected";
1362
- promoted: "promoted";
1363
1378
  revoked: "revoked";
1364
1379
  }>>;
1365
1380
  gate_results: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -1496,8 +1511,8 @@ export declare const PluginConfigSchema: z.ZodObject<{
1496
1511
  }>>>;
1497
1512
  require_docs: z.ZodDefault<z.ZodBoolean>;
1498
1513
  policy: z.ZodDefault<z.ZodEnum<{
1499
- enforce: "enforce";
1500
1514
  warn: "warn";
1515
+ enforce: "enforce";
1501
1516
  }>>;
1502
1517
  regression_sweep: z.ZodOptional<z.ZodObject<{
1503
1518
  enforce: z.ZodDefault<z.ZodBoolean>;
@@ -1820,6 +1835,21 @@ export declare const PluginConfigSchema: z.ZodObject<{
1820
1835
  default_max_phases: z.ZodDefault<z.ZodNumber>;
1821
1836
  todo_max_phases: z.ZodDefault<z.ZodNumber>;
1822
1837
  sweep_enabled: z.ZodDefault<z.ZodBoolean>;
1838
+ confidence_floor_action: z.ZodDefault<z.ZodEnum<{
1839
+ none: "none";
1840
+ demote: "demote";
1841
+ quarantine: "quarantine";
1842
+ }>>;
1843
+ confidence_floor_min_outcomes: z.ZodDefault<z.ZodNumber>;
1844
+ confidence_floor_signal_threshold: z.ZodDefault<z.ZodNumber>;
1845
+ contradiction_threshold_action: z.ZodDefault<z.ZodEnum<{
1846
+ quarantine: "quarantine";
1847
+ tag_only: "tag_only";
1848
+ }>>;
1849
+ contradiction_quarantine_threshold: z.ZodDefault<z.ZodNumber>;
1850
+ contradiction_quarantine_window_days: z.ZodDefault<z.ZodNumber>;
1851
+ promoted_demotion_min_negative_phases: z.ZodDefault<z.ZodNumber>;
1852
+ promoted_demotion_signal_threshold: z.ZodDefault<z.ZodNumber>;
1823
1853
  realtime_learning_nudge: z.ZodDefault<z.ZodObject<{
1824
1854
  enabled: z.ZodDefault<z.ZodBoolean>;
1825
1855
  first_after_tool_calls: z.ZodDefault<z.ZodNumber>;
@@ -1989,8 +2019,8 @@ export declare const PluginConfigSchema: z.ZodObject<{
1989
2019
  knowledge_application: z.ZodOptional<z.ZodObject<{
1990
2020
  enabled: z.ZodDefault<z.ZodBoolean>;
1991
2021
  mode: z.ZodDefault<z.ZodEnum<{
1992
- enforce: "enforce";
1993
2022
  warn: "warn";
2023
+ enforce: "enforce";
1994
2024
  }>>;
1995
2025
  min_confidence: z.ZodDefault<z.ZodNumber>;
1996
2026
  critical_requires_ack: z.ZodDefault<z.ZodBoolean>;
@@ -95,6 +95,32 @@ export declare function curateAndStoreSwarm(lessons: string[], projectName: stri
95
95
  * Auto-promote swarm entries based on phase confirmations and age.
96
96
  */
97
97
  export declare function runAutoPromotion(directory: string, config: KnowledgeConfig): Promise<void>;
98
+ /**
99
+ * G7 (#1716): Auto-demote swarm entries that have sustained a net-negative
100
+ * outcome signal over consecutive phase EVALUATIONS (i.e. consecutive
101
+ * `runAutoDemotion` invocations with distinct phase numbers — a skipped phase
102
+ * in between still counts, matching the issue's "≥3 consecutive" intent as
103
+ * implemented against evaluation cadence, not wall-clock phase contiguity).
104
+ *
105
+ * Companion to {@link runAutoPromotion}. For each `promoted` entry:
106
+ * 1. Dedupe by phase: if `entry.last_demotion_phase === phaseNumber`, this
107
+ * entry has already been processed for this phase (handles the case where
108
+ * `curateAndStoreSwarm` is invoked multiple times in the same logical
109
+ * phase — e.g. phase-complete + close). Skip the counter update.
110
+ * 2. Otherwise compute the outcome signal. If at/below
111
+ * `config.promoted_demotion_signal_threshold`, increment
112
+ * `recent_negative_phase_count`; else reset it to 0.
113
+ * 3. Set `entry.last_demotion_phase = phaseNumber`.
114
+ * 4. If `recent_negative_phase_count >= config.promoted_demotion_min_negative_phases`,
115
+ * demote to `established`: clear `hive_eligible`, clear the G2
116
+ * `confidence_floor_demoted` flag (the demotion is the stronger signal),
117
+ * and reset the counter.
118
+ *
119
+ * Only `promoted` entries are touched. The `phaseInfo.phase_number > 0` gate
120
+ * at the call site ensures this runs only at phase-complete (not close-time
121
+ * curation, which hardcodes `phase_number: 0`).
122
+ */
123
+ export declare function runAutoDemotion(directory: string, config: KnowledgeConfig, phaseNumber: number): Promise<void>;
98
124
  /**
99
125
  * Create the knowledge curator hook.
100
126
  * Watches for writes to .swarm/plan.md and extracts lessons from the retrospective section.
@@ -108,6 +134,7 @@ export declare const _internals: {
108
134
  isWriteToEvidenceFile: typeof isWriteToEvidenceFile;
109
135
  curateAndStoreSwarm: typeof curateAndStoreSwarm;
110
136
  runAutoPromotion: typeof runAutoPromotion;
137
+ runAutoDemotion: typeof runAutoDemotion;
111
138
  createKnowledgeCuratorHook: typeof createKnowledgeCuratorHook;
112
139
  seenRetroSections: typeof seenRetroSections;
113
140
  recordSeenRetroSection: typeof recordSeenRetroSection;
@@ -48,3 +48,19 @@ export declare function readRecentEscalations(directory: string, windowDays?: nu
48
48
  export declare function buildEscalationBriefing(escalations: RecentEscalation[], windowDays?: number): string | null;
49
49
  /** Run the escalator for several entry IDs (deduped). Never throws. */
50
50
  export declare function escalateViolatedEntries(directory: string, entryIds: string[], now?: Date): Promise<EscalationResult[]>;
51
+ export interface ContradictionQuarantineResult {
52
+ quarantined: boolean;
53
+ entryId: string;
54
+ contradictionsInWindow?: number;
55
+ /** True when the entry was already quarantined/archived (no-op, idempotent). */
56
+ alreadyInactive?: boolean;
57
+ }
58
+ /**
59
+ * G3 (#1715): if an entry's `contradicted` count within `windowDays` crosses
60
+ * `threshold`, auto-quarantine it. Mirrors {@link maybeEscalateOnViolation}
61
+ * (counts from the RAW event log via {@link countEntryContradictionsInWindow}
62
+ * — NOT the rollup cache, which is mtime-keyed and can be stale immediately
63
+ * after an append). Idempotent: already-quarantined/archived entries are
64
+ * skipped. Never throws.
65
+ */
66
+ export declare function maybeQuarantineOnContradiction(directory: string, entryId: string, threshold: number, windowDays: number, now?: Date): Promise<ContradictionQuarantineResult>;
@@ -19,6 +19,7 @@
19
19
  * `directory` argument injected by `createSwarmTool` / hook constructors — never
20
20
  * from the process working directory.
21
21
  */
22
+ import type { ConfidenceFloorOptions } from './knowledge-store.js';
22
23
  import type { KnowledgeApplicationRecord, RetrievalOutcome } from './knowledge-types.js';
23
24
  /** Current event-log record schema version. Bump when the on-disk shape changes. */
24
25
  export declare const KNOWLEDGE_EVENT_SCHEMA_VERSION = 1;
@@ -285,6 +286,14 @@ export declare function countViolationsInWindow(timestamps: string[], windowDays
285
286
  * with more in-window violations). Fail-open: returns 0 on error.
286
287
  */
287
288
  export declare function countEntryViolationsInWindow(directory: string, entryId: string, windowDays: number, now?: Date): Promise<number>;
289
+ /**
290
+ * G3 (#1715): count `contradicted` events for an entry within a window, reading
291
+ * from the RAW event log (NOT the rollup cache — `recomputeCounters` is mtime-
292
+ * keyed and can be stale immediately after an append, mirroring the
293
+ * `countEntryViolationsInWindow` discipline above). No legacy-record fold:
294
+ * contradicted has no legacy counterpart (unlike violated). Fail-open: returns 0.
295
+ */
296
+ export declare function countEntryContradictionsInWindow(directory: string, entryId: string, windowDays: number, now?: Date): Promise<number>;
288
297
  /**
289
298
  * Fail-open rollup reader for hot paths. Search and promotion use this instead
290
299
  * of stale persisted counters so `knowledge_receipt` feedback affects ranking
@@ -307,6 +316,8 @@ export declare function effectiveRetrievalOutcomes(stored: RetrievalOutcome | un
307
316
  export declare function applyKnowledgeVerdictFeedback(directory: string, options?: {
308
317
  sinceTimestamp?: string;
309
318
  sinceEventId?: string;
319
+ /** G2: forwarded to bumpKnowledgeConfidenceBatch. */
320
+ floorOptions?: ConfidenceFloorOptions;
310
321
  }): Promise<{
311
322
  processed: number;
312
323
  bumps: number;
@@ -2,12 +2,7 @@
2
2
  * Merges swarm + hive knowledge, deduplicates (hive wins), ranks by composite score,
3
3
  * and provides utility tracking.
4
4
  */
5
- import { existsSync } from 'node:fs';
6
- import { readFile } from 'node:fs/promises';
7
- import { atomicWriteFile } from '../evidence/task-file.js';
8
- import { warn } from '../utils/logger.js';
9
5
  import { recordKnowledgeEvent } from './knowledge-events.js';
10
- import { jaccardBigram, normalize, readKnowledge, readRetractionRecords, resolveHiveKnowledgePath, resolveSwarmKnowledgePath, transactFile, wordBigrams } from './knowledge-store.js';
11
6
  import type { KnowledgeConfig, KnowledgeEntryBase, KnowledgeRetrievalContext } from './knowledge-types.js';
12
7
  export interface ProjectContext {
13
8
  projectName: string;
@@ -42,18 +37,6 @@ export declare const _internals: {
42
37
  updateRetrievalOutcome: typeof updateRetrievalOutcome;
43
38
  scoreDirectiveAgainstContext: typeof scoreDirectiveAgainstContext;
44
39
  transactShownFile: typeof transactShownFile;
45
- existsSync: typeof existsSync;
46
- readFile: typeof readFile;
47
- atomicWriteFile: typeof atomicWriteFile;
48
- transactFile: typeof transactFile;
49
- warn: typeof warn;
50
- readKnowledge: typeof readKnowledge;
51
- readRetractionRecords: typeof readRetractionRecords;
52
- resolveHiveKnowledgePath: typeof resolveHiveKnowledgePath;
53
- resolveSwarmKnowledgePath: typeof resolveSwarmKnowledgePath;
54
- jaccardBigram: typeof jaccardBigram;
55
- normalize: typeof normalize;
56
- wordBigrams: typeof wordBigrams;
57
40
  recordKnowledgeEvent: typeof recordKnowledgeEvent;
58
41
  };
59
42
  export {};
@@ -69,7 +69,22 @@ export declare function inferTags(lesson: string): string[];
69
69
  export declare function bumpKnowledgeConfidenceBatch(directory: string, deltas: Array<{
70
70
  id: string;
71
71
  delta: number;
72
- }>): Promise<void>;
72
+ }>, options?: ConfidenceFloorOptions): Promise<void>;
73
+ /** Options for the G2 confidence-floor action in bumpKnowledgeConfidenceBatch. */
74
+ export interface ConfidenceFloorOptions {
75
+ /** Action when a just-bumped entry sits at the confidence floor with a
76
+ * net-negative outcome signal. `'none'` preserves the legacy dead-end
77
+ * behavior. Default `'demote'`. */
78
+ floorAction?: 'none' | 'demote' | 'quarantine';
79
+ /** Minimum total outcome-evidence count required before acting on a
80
+ * floor entry. Avoids demoting brand-new entries with one stray negative.
81
+ * Default 3. */
82
+ floorMinOutcomes?: number;
83
+ /** Outcome-signal threshold below which a floor entry is acted on
84
+ * (`computeOutcomeSignal` returns (-1, 1); net-negative is `< 0`).
85
+ * Default 0. */
86
+ floorSignalThreshold?: number;
87
+ }
73
88
  export declare const _internals: {
74
89
  getPlatformConfigDir: typeof getPlatformConfigDir;
75
90
  resolveSwarmKnowledgePath: typeof resolveSwarmKnowledgePath;
@@ -126,9 +126,74 @@ export interface KnowledgeEntryBase extends ActionableDirectiveFields {
126
126
  auto_generated?: boolean;
127
127
  phases_alive?: number;
128
128
  max_phases?: number;
129
+ /** G2 (#1715): set when the confidence-floor action fired (demote).
130
+ * Suppresses `statusBoost` in retrieval so a floor-clamped entry sinks to
131
+ * the bottom of ranking without introducing a new retrieval-leaking status.
132
+ * Cleared if confidence recovers above the floor. */
133
+ confidence_floor_demoted?: boolean;
134
+ /** G6 (#1716): recorded at archive time so `unarchiveEntry` can restore the
135
+ * entry to its prior status. Set by all three archive producers (tool,
136
+ * curator recommendation, TTL sweep). Absent on entries archived before
137
+ * this field existed; `unarchiveEntry` falls back to `'candidate'`. */
138
+ archived_from?: KnowledgeEntryBase['status'];
139
+ /** G6 (#1716): ISO 8601 timestamp of archival. */
140
+ archived_at?: string;
141
+ /** G7 (#1716): consecutive-net-negative-phase counter, incremented by
142
+ * `runAutoDemotion` when a promoted entry's outcome signal is at/below
143
+ * `promoted_demotion_signal_threshold`. Reset on a non-negative phase and on
144
+ * demotion. Used with `last_demotion_phase` to demote at
145
+ * `promoted_demotion_min_negative_phases` consecutive net-negative phases. */
146
+ recent_negative_phase_count?: number;
147
+ /** G7 (#1716): the `phase_number` of the most recent `runAutoDemotion`
148
+ * counter update. Prevents double-counting when `curateAndStoreSwarm` runs
149
+ * multiple times in the same logical phase (e.g. phase-complete + close). */
150
+ last_demotion_phase?: number;
129
151
  }
130
152
  /** v2 schema marker. v1 entries are still parseable and normalized in-memory by knowledge-store.normalizeEntry. */
131
153
  export declare const KNOWLEDGE_SCHEMA_VERSION = 2;
154
+ /**
155
+ * The single canonical set of inactive (non-retrieval) knowledge statuses.
156
+ * Every retrieval/filter consumer MUST go through {@link isActiveStatus} rather
157
+ * than re-deriving its own literal list — the G4 drift (issue #1716) was caused
158
+ * by exactly that pattern.
159
+ *
160
+ * Note: `archived`, `quarantined`, and `quarantined_unactionable` are all
161
+ * considered inactive. The remaining statuses (`candidate`, `established`,
162
+ * `promoted`) plus the "unknown" cases (`undefined`/`null`/any future string)
163
+ * are considered active — the unknown-status case is intentional and preserves
164
+ * the #828 regression-guard behavior (entries with missing status after
165
+ * migration are not silently dropped from retrieval).
166
+ */
167
+ export declare const INACTIVE_STATUSES: ReadonlySet<string>;
168
+ /**
169
+ * Outcome-signal threshold at or below which a knowledge entry is considered to
170
+ * have a clearly negative track record (negatives clearly outweigh positives,
171
+ * with enough corroborating evidence to act on). Tuned against
172
+ * `computeOutcomeSignal`'s Laplace smoothing so a lone ignore/contradiction
173
+ * does not trip it.
174
+ *
175
+ * G7 (#1716): the canonical home for this value. Previously a module-local
176
+ * const in `knowledge-curator.ts`; lifted here so the config default
177
+ * (`promoted_demotion_signal_threshold`) can reference the same value without
178
+ * a schema→curator import cycle. Both the promotion block and the demotion
179
+ * threshold share this single source of truth.
180
+ */
181
+ export declare const OUTCOME_BLOCK_THRESHOLD = -0.3;
182
+ /**
183
+ * Returns `true` for retrieval-active statuses. Returns `true` for
184
+ * `undefined`/`null`/unknown strings (preserves the #828 deny-list intent:
185
+ * entries with unexpected status values are not silently dropped). Returns
186
+ * `false` only for the three known inactive statuses.
187
+ *
188
+ * PRR-009 / design note: issue #1716's G4 section literally requested an
189
+ * allow-list ("future statuses default to excluded"). We deliberately use a
190
+ * deny-list here to preserve the #828 regression-guard intent (entries with
191
+ * missing/unknown status after migration are not silently dropped from
192
+ * retrieval). The known-inactive leak the issue cares about (the 3 statuses
193
+ * above) is closed; the hypothetical-future-status robustness is the tradeoff.
194
+ * Switching to an allow-list would re-introduce #828.
195
+ */
196
+ export declare function isActiveStatus(status: string | undefined | null): boolean;
132
197
  export interface SwarmKnowledgeEntry extends KnowledgeEntryBase {
133
198
  tier: 'swarm';
134
199
  confirmed_by: PhaseConfirmationRecord[];
@@ -207,6 +272,26 @@ export interface KnowledgeConfig {
207
272
  todo_max_phases: number;
208
273
  /** Enable age-based sweep of knowledge entries. Default: true */
209
274
  sweep_enabled: boolean;
275
+ /** G2 (#1715): action when an entry sits at the confidence floor with a
276
+ * net-negative outcome signal. Default: 'demote'. */
277
+ confidence_floor_action: 'none' | 'demote' | 'quarantine';
278
+ /** G2: minimum total outcome-evidence count required before acting. Default: 3. */
279
+ confidence_floor_min_outcomes: number;
280
+ /** G2: outcome-signal threshold below which a floor entry is acted on. Default: 0. */
281
+ confidence_floor_signal_threshold: number;
282
+ /** G3 (#1715): action when contradicted count crosses the threshold. Default: 'quarantine'. */
283
+ contradiction_threshold_action: 'tag_only' | 'quarantine';
284
+ /** G3: contradicted-event count in window to trigger the action. Default: 3. */
285
+ contradiction_quarantine_threshold: number;
286
+ /** G3: window in days for counting contradicted events. Default: 30. */
287
+ contradiction_quarantine_window_days: number;
288
+ /** G7 (#1716): consecutive net-negative phase evaluations required to demote
289
+ * a `promoted` entry to `established`. Default: 3. */
290
+ promoted_demotion_min_negative_phases: number;
291
+ /** G7 (#1716): outcome-signal threshold at or below which a promoted entry's
292
+ * demotion counter increments for the current phase. Default: -0.3 (matches
293
+ * `OUTCOME_BLOCK_THRESHOLD`). */
294
+ promoted_demotion_signal_threshold: number;
210
295
  /** Change 5: retrieval-upgrade tuning (MMR / cold-start / synonyms). */
211
296
  retrieval?: {
212
297
  mmr_lambda?: number;
@@ -99,11 +99,26 @@ export interface EntryHealthResult {
99
99
  export declare function auditEntryHealth(entry: KnowledgeEntryBase): EntryHealthResult;
100
100
  export declare function quarantineEntry(directory: string, entryId: string, reason: string, reportedBy: 'architect' | 'user' | 'auto'): Promise<void>;
101
101
  export declare function restoreEntry(directory: string, entryId: string): Promise<void>;
102
+ export interface UnarchiveResult {
103
+ restored: boolean;
104
+ restored_to?: string;
105
+ reason?: 'not_found' | 'not_archived' | 'invalid_lesson';
106
+ }
107
+ /**
108
+ * G6 (#1716): restore an `archived`-status entry from `knowledge.jsonl` to its
109
+ * pre-archive status (`archived_from` if recorded, else `'candidate'`). Swarm-only
110
+ * — matches `quarantineEntry`'s scope. Uses the same lock + atomicWrite pattern
111
+ * as `restoreEntry`. Also resets G7 demotion counters so a restored entry
112
+ * (especially one restored to `promoted`) is not demoted almost immediately
113
+ * under the new demotion window.
114
+ */
115
+ export declare function unarchiveEntry(directory: string, entryId: string): Promise<UnarchiveResult>;
102
116
  export declare const _internals: {
103
117
  validateLesson: typeof validateLesson;
104
118
  auditEntryHealth: typeof auditEntryHealth;
105
119
  quarantineEntry: typeof quarantineEntry;
106
120
  restoreEntry: typeof restoreEntry;
121
+ unarchiveEntry: typeof unarchiveEntry;
107
122
  extractContextWords: typeof extractContextWords;
108
123
  hasSignificantOverlap: typeof hasSignificantOverlap;
109
124
  };
@@ -5,6 +5,7 @@
5
5
  * Follows the same append-only JSONL pattern as knowledge-application.jsonl.
6
6
  */
7
7
  import * as fs from 'node:fs';
8
+ import type { ConfidenceFloorOptions } from './knowledge-store.js';
8
9
  /** Single entry in the skill-usage audit log. */
9
10
  export interface SkillUsageEntry {
10
11
  /** Auto-generated unique identifier (UUID v4). */
@@ -179,6 +180,8 @@ declare function parseGeneratedFromKnowledge(content: string): string[];
179
180
  */
180
181
  export declare function applySkillUsageFeedback(directory: string, options?: {
181
182
  sinceTimestamp?: string;
183
+ /** G2: forwarded to bumpKnowledgeConfidenceBatch. */
184
+ floorOptions?: ConfidenceFloorOptions;
182
185
  }): Promise<{
183
186
  processed: number;
184
187
  bumps: number;