opencode-swarm 7.88.3 → 7.89.0

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 (49) hide show
  1. package/dist/agents/agent-output-schema.d.ts +1 -1
  2. package/dist/agents/curator-agent.d.ts +1 -1
  3. package/dist/agents/explorer.d.ts +1 -0
  4. package/dist/cli/{config-doctor-jzbgpbdh.js → config-doctor-g04wdz19.js} +2 -2
  5. package/dist/cli/{explorer-gz70sm9b.js → explorer-h2fnj343.js} +4 -2
  6. package/dist/cli/{guardrail-explain-eqypvw60.js → guardrail-explain-hy0zz0p6.js} +8 -8
  7. package/dist/cli/{guardrail-log-c7egm5km.js → guardrail-log-m3285thy.js} +3 -3
  8. package/dist/cli/{index-0asbrmdx.js → index-123s7kjc.js} +88 -2
  9. package/dist/cli/{index-32axfg6h.js → index-1ccnwh54.js} +98 -25
  10. package/dist/cli/{index-ds057q5k.js → index-6k31ysgd.js} +2 -2
  11. package/dist/cli/{index-g00qm2gf.js → index-6tnmt41c.js} +1 -1
  12. package/dist/cli/{index-g6f4tt38.js → index-9w07ye9b.js} +906 -431
  13. package/dist/cli/{index-e8pk68cc.js → index-axwxkbdd.js} +166 -23
  14. package/dist/cli/{index-yhsmmv2z.js → index-bm4f0nme.js} +25 -1
  15. package/dist/cli/{index-819xp49y.js → index-bywt2171.js} +1 -1
  16. package/dist/cli/{index-0rt5aamg.js → index-dprk5c5f.js} +13 -9
  17. package/dist/cli/{index-vjsr9bqt.js → index-gg589mfw.js} +1 -1
  18. package/dist/cli/index.js +7 -7
  19. package/dist/cli/{knowledge-store-n4x6zyk7.js → knowledge-store-gsy6p46z.js} +1 -1
  20. package/dist/cli/{schema-vb6jkxgg.js → schema-t9th7frq.js} +1 -1
  21. package/dist/cli/{skill-generator-kz4q8e49.js → skill-generator-1hzfyhth.js} +2 -2
  22. package/dist/commands/index.d.ts +2 -0
  23. package/dist/commands/link.d.ts +19 -0
  24. package/dist/commands/memory.d.ts +1 -0
  25. package/dist/commands/registry.d.ts +31 -0
  26. package/dist/commands/unlink.d.ts +13 -0
  27. package/dist/config/agent-names.d.ts +2 -2
  28. package/dist/config/schema.d.ts +60 -0
  29. package/dist/hooks/curator-llm-factory.d.ts +1 -1
  30. package/dist/hooks/knowledge-events.d.ts +3 -3
  31. package/dist/hooks/knowledge-link.d.ts +82 -0
  32. package/dist/hooks/knowledge-validator.d.ts +1 -1
  33. package/dist/index.js +3177 -1765
  34. package/dist/knowledge/identity.d.ts +9 -0
  35. package/dist/memory/config.d.ts +35 -0
  36. package/dist/memory/consolidation-log.d.ts +29 -0
  37. package/dist/memory/consolidation.d.ts +124 -0
  38. package/dist/memory/decay.d.ts +24 -0
  39. package/dist/memory/gateway.d.ts +14 -2
  40. package/dist/memory/maintenance.d.ts +18 -0
  41. package/dist/memory/run-log.d.ts +8 -1
  42. package/dist/memory/schema.d.ts +3 -3
  43. package/dist/memory/scoring.d.ts +45 -0
  44. package/dist/memory/sentinel.d.ts +15 -0
  45. package/dist/services/memory-consolidation.d.ts +32 -0
  46. package/dist/services/skill-generator.d.ts +8 -1
  47. package/dist/session/worktree-link-suggestion.d.ts +27 -0
  48. package/dist/state.d.ts +4 -2
  49. package/package.json +1 -1
@@ -12,7 +12,6 @@ export declare const AgentOutputMemorySchema: z.ZodObject<{
12
12
  }>;
13
13
  kind: z.ZodOptional<z.ZodEnum<{
14
14
  evidence: "evidence";
15
- todo: "todo";
16
15
  user_preference: "user_preference";
17
16
  project_fact: "project_fact";
18
17
  architecture_decision: "architecture_decision";
@@ -22,6 +21,7 @@ export declare const AgentOutputMemorySchema: z.ZodObject<{
22
21
  test_pattern: "test_pattern";
23
22
  failure_pattern: "failure_pattern";
24
23
  security_note: "security_note";
24
+ todo: "todo";
25
25
  scratch: "scratch";
26
26
  }>>;
27
27
  text: z.ZodOptional<z.ZodString>;
@@ -1,5 +1,5 @@
1
1
  import type { AgentDefinition } from './architect';
2
- export type CuratorRole = 'curator_init' | 'curator_phase' | 'curator_postmortem';
2
+ export type CuratorRole = 'curator_init' | 'curator_phase' | 'curator_postmortem' | 'curator_consolidation';
3
3
  /**
4
4
  * Create a Curator agent definition for the given role.
5
5
  *
@@ -3,4 +3,5 @@ export declare const EXPLORER_PROMPT = "## IDENTITY\nYou are Explorer. You analy
3
3
  export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Note contradictions (knowledge says X, project state shows Y)\n- Observe where lessons could be tighter or stale\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- Memory proposals are for concise durable facts only. Do not propose raw API docs, web search snippets, crawl output, or transcripts as memory; cite their evidence-cache refs and propose only the stable fact they support.\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
4
4
  export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Observe workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Report knowledge update candidates with observable evidence: entries that appear promoted, archived, rewritten, or contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- OBSERVATIONS should not contain directives \u2014 report what is observed, do not instruct the architect what to do\n- Extend the digest, never replace it\n- Memory proposals are for concise durable facts only. Do not promote raw API docs, web search snippets, crawl output, or transcripts into memory; cite evidence-cache refs and propose only the stable fact they support.\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type] observed: [description] (or \"No deviations observed\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n\n## V3 ACTIONABILITY ENRICHMENT (overrides the format above when triggered)\nWhen the input asks you to \"Convert this prose lesson into an actionable knowledge directive\", ignore the PHASE_DIGEST output format entirely and output ONLY a single JSON object \u2014 no fences, no commentary, no digest.\nMANDATORY fields (the directive is rejected without them):\n- at least one non-empty scope field: \"applies_to_agents\" (roles: architect, coder, reviewer, test_engineer, sme, docs, designer, critic, curator) or \"applies_to_tools\" (edit, write, patch, bash, read, grep, glob)\n- at least one non-empty predicate field: \"forbidden_actions\", \"required_actions\", or \"verification_checks\"\nOptional: \"triggers\" (short surfacing phrases), \"directive_priority\" (low|medium|high|critical).\nExample output:\n{\"applies_to_agents\":[\"coder\"],\"forbidden_actions\":[\"use async iterators in hot paths\"],\"required_actions\":[\"use a plain for loop in hot paths\"],\"triggers\":[\"hot path\",\"async iterator\"],\"directive_priority\":\"high\"}\n";
5
5
  export declare const CURATOR_POSTMORTEM_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_POSTMORTEM mode. You synthesize a project-end post-mortem from structured .swarm/ evidence.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\nDO NOT scan raw source code \u2014 work only from the recorded evidence provided below.\n\nINPUT FORMAT:\nTASK: CURATOR_POSTMORTEM [plan_id]\nPLAN_SUMMARY: [plan phases, task counts, completion status]\nCURATOR_DIGESTS: [running digest from curator_phase across all phases]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nKNOWLEDGE_EVENTS_SUMMARY: [aggregated violation/applied/ignored counts per entry]\nPENDING_PROPOSALS: [skill/motif proposals awaiting triage]\nUNACTIONABLE_QUARANTINE: [entries flagged unactionable with retry status]\nDRIFT_REPORTS: [per-phase alignment/drift scores if available]\nRETROSPECTIVES: [any session retrospectives found]\n\nACTIONS:\n1. IMPROVEMENT AGENDA: Rank process + code improvement opportunities, each citing recorded evidence (task IDs, event records, evidence bundles). Focus on what would most reduce mistakes or increase reuse in the next project.\n2. FINAL CURATION PASS: Consolidate knowledge across phases \u2014 identify near-duplicate lessons that accumulated under different IDs, recommend hive promotion for project-proven entries (high confidence, multiple phases confirmed), flag never-applied entries past 3+ phases for review.\n3. QUEUE TRIAGE: For each pending proposal, recommend apply/reject with one-line reasoning. Surface unactionable-quarantine counts and retry candidates.\n4. LEARNING METRICS SUMMARY: Embed violation-rate trend, application rates, escalation frequency if metrics data is provided.\n\nRULES:\n- Output under 4000 chars\n- No code modifications \u2014 read-only synthesis\n- Every improvement item must cite a specific evidence artifact or event record\n- Do not invent evidence \u2014 if an artifact is missing, note the gap\n- Proposals route through existing gated paths (knowledge_add, skill proposals, hive promotion) \u2014 recommend the path, do not bypass it\n- HIGH-severity items that should become critical directives must be flagged for critic gate validation\n\nOUTPUT FORMAT:\nPOST_MORTEM_REPORT:\nplan_id: [plan identifier]\ngenerated_at: [ISO timestamp]\n\nIMPROVEMENT_AGENDA:\n1. [priority] [description] \u2014 evidence: [artifact/event ref]\n2. ...\n\nCURATION_RECOMMENDATIONS:\n- merge: [entry_a UUID] + [entry_b UUID] \u2014 [reason]\n- promote_to_hive: [entry UUID] \u2014 [evidence of cross-phase confirmation]\n- flag_stale: [entry UUID] \u2014 [never applied in N phases]\n- rewrite: [entry UUID] \u2014 [what's verbose/outdated]\n\nQUEUE_TRIAGE:\n- [proposal_id]: APPLY|REJECT \u2014 [one-line reasoning]\n\nLEARNING_METRICS:\n[3-line summary of trends if data available, or \"metrics data not provided\"]\n\nSUMMARY:\n[3-line executive summary for architect briefing]\n";
6
+ export declare const CURATOR_CONSOLIDATION_PROMPT = "## IDENTITY\nYou are Curator in CONSOLIDATION mode. You distill clusters of raw episodic memory into a small set of durable semantic facts.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\nDO NOT scan raw source code \u2014 work only from the episodic events and existing memories provided in the prompt.\n\nINPUT FORMAT:\n- A cluster of verbatim episodic events.\n- A list of existing durable memories (each prefixed with its mem_ id) for dedup and contradiction detection.\n\nACTIONS:\n1. Identify durable, reusable facts that are DIRECTLY supported by the cited episodic evidence.\n2. Detect contradictions with the listed existing memories; when a new fact conflicts with one, set contradictsMemoryId to that memory's id.\n3. Skip anything speculative, transient, or already captured by an existing memory.\n\nRULES:\n- Only emit facts directly supported by the cited evidence. If uncertain, omit the fact (fewer facts, or an empty array, is correct).\n- Use durable kinds only (user_preference, project_fact, architecture_decision, repo_convention, code_pattern, test_pattern, failure_pattern, security_note).\n- Keep each fact concise (under 500 characters).\n- Never include the literal text \"## Retrieved Swarm Memory\".\n- Output STRICT JSON only, no prose.\n\nOUTPUT FORMAT:\n{\"facts\":[{\"text\":\"...\",\"kind\":\"project_fact\",\"confidence\":0.8,\"contradictsMemoryId\":\"mem_0123456789abcdef\"}]}\n";
6
7
  export declare function createExplorerAgent(model: string, customPrompt?: string, customAppendPrompt?: string): AgentDefinition;
@@ -12,8 +12,8 @@ import {
12
12
  shouldRunOnStartup,
13
13
  writeBackupArtifact,
14
14
  writeDoctorArtifact
15
- } from "./index-819xp49y.js";
16
- import"./index-0asbrmdx.js";
15
+ } from "./index-bywt2171.js";
16
+ import"./index-123s7kjc.js";
17
17
  import"./index-5e4e2hvv.js";
18
18
  import"./index-p0arc26j.js";
19
19
  import"./index-zgwm4ryv.js";
@@ -1,16 +1,18 @@
1
1
  // @bun
2
2
  import {
3
+ CURATOR_CONSOLIDATION_PROMPT,
3
4
  CURATOR_INIT_PROMPT,
4
5
  CURATOR_PHASE_PROMPT,
5
6
  CURATOR_POSTMORTEM_PROMPT,
6
7
  EXPLORER_PROMPT,
7
8
  createExplorerAgent
8
- } from "./index-yhsmmv2z.js";
9
+ } from "./index-bm4f0nme.js";
9
10
  import"./index-a76rekgs.js";
10
11
  export {
11
12
  createExplorerAgent,
12
13
  EXPLORER_PROMPT,
13
14
  CURATOR_POSTMORTEM_PROMPT,
14
15
  CURATOR_PHASE_PROMPT,
15
- CURATOR_INIT_PROMPT
16
+ CURATOR_INIT_PROMPT,
17
+ CURATOR_CONSOLIDATION_PROMPT
16
18
  };
@@ -1,14 +1,14 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-ds057q5k.js";
5
- import"./index-g6f4tt38.js";
6
- import"./index-g00qm2gf.js";
7
- import"./index-yhsmmv2z.js";
8
- import"./index-32axfg6h.js";
9
- import"./index-e8pk68cc.js";
10
- import"./index-819xp49y.js";
11
- import"./index-0asbrmdx.js";
4
+ } from "./index-6k31ysgd.js";
5
+ import"./index-9w07ye9b.js";
6
+ import"./index-6tnmt41c.js";
7
+ import"./index-bm4f0nme.js";
8
+ import"./index-1ccnwh54.js";
9
+ import"./index-axwxkbdd.js";
10
+ import"./index-bywt2171.js";
11
+ import"./index-123s7kjc.js";
12
12
  import"./index-8y7qetpg.js";
13
13
  import"./index-adz3nk9b.js";
14
14
  import"./index-v4fcn4tr.js";
@@ -1,9 +1,9 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailLog
4
- } from "./index-vjsr9bqt.js";
5
- import"./index-g00qm2gf.js";
6
- import"./index-0asbrmdx.js";
4
+ } from "./index-gg589mfw.js";
5
+ import"./index-6tnmt41c.js";
6
+ import"./index-123s7kjc.js";
7
7
  import"./index-5e4e2hvv.js";
8
8
  import"./index-p0arc26j.js";
9
9
  import"./index-zgwm4ryv.js";
@@ -20,6 +20,7 @@ var ALL_SUBAGENT_NAMES = [
20
20
  "curator_init",
21
21
  "curator_phase",
22
22
  "curator_postmortem",
23
+ "curator_consolidation",
23
24
  "council_generalist",
24
25
  "council_skeptic",
25
26
  "council_domain_expert",
@@ -892,6 +893,10 @@ var DEFAULT_AGENT_CONFIGS = {
892
893
  model: "opencode/gpt-5-nano",
893
894
  fallback_models: ["opencode/big-pickle"]
894
895
  },
896
+ curator_consolidation: {
897
+ model: "opencode/gpt-5-nano",
898
+ fallback_models: ["opencode/big-pickle"]
899
+ },
895
900
  skill_improver: {
896
901
  model: "opencode/big-pickle",
897
902
  fallback_models: ["opencode/gpt-5-nano"]
@@ -1505,10 +1510,91 @@ var MemoryConfigSchema = exports_external.object({
1505
1510
  }).default({ rejectDurableSecrets: true }),
1506
1511
  maintenance: exports_external.object({
1507
1512
  lowUtilityMaxConfidence: exports_external.number().min(0).max(1).default(0.45),
1508
- lowUtilityMinAgeDays: exports_external.number().int().min(1).max(3650).default(30)
1513
+ lowUtilityMinAgeDays: exports_external.number().int().min(1).max(3650).default(30),
1514
+ importance: exports_external.object({
1515
+ wRecency: exports_external.number().min(0).max(1).default(0.2),
1516
+ wFrequency: exports_external.number().min(0).max(1).default(0.2),
1517
+ wFreshness: exports_external.number().min(0).max(1).default(0.15),
1518
+ wConfidence: exports_external.number().min(0).max(1).default(0.25),
1519
+ lambda: exports_external.number().min(0).max(10).default(0.05),
1520
+ mu: exports_external.number().min(0).max(10).default(0.01),
1521
+ n: exports_external.number().int().min(1).max(1e5).default(50),
1522
+ threshold: exports_external.number().min(0).max(1).default(0.2)
1523
+ }).default({
1524
+ wRecency: 0.2,
1525
+ wFrequency: 0.2,
1526
+ wFreshness: 0.15,
1527
+ wConfidence: 0.25,
1528
+ lambda: 0.05,
1529
+ mu: 0.01,
1530
+ n: 50,
1531
+ threshold: 0.2
1532
+ })
1509
1533
  }).default({
1510
1534
  lowUtilityMaxConfidence: 0.45,
1511
- lowUtilityMinAgeDays: 30
1535
+ lowUtilityMinAgeDays: 30,
1536
+ importance: {
1537
+ wRecency: 0.2,
1538
+ wFrequency: 0.2,
1539
+ wFreshness: 0.15,
1540
+ wConfidence: 0.25,
1541
+ lambda: 0.05,
1542
+ mu: 0.01,
1543
+ n: 50,
1544
+ threshold: 0.2
1545
+ }
1546
+ }),
1547
+ consolidation: exports_external.object({
1548
+ enabled: exports_external.boolean().default(false),
1549
+ maxClustersPerPass: exports_external.number().int().min(1).max(100).default(10),
1550
+ jaccardThreshold: exports_external.number().min(0).max(1).default(0.3),
1551
+ autoApplyMinConfidence: exports_external.number().min(0).max(1).default(0.6),
1552
+ decayHalfLifeDays: exports_external.object({
1553
+ user_preference: exports_external.number().int().min(0).max(36500).default(0),
1554
+ project_fact: exports_external.number().int().min(0).max(36500).default(0),
1555
+ architecture_decision: exports_external.number().int().min(0).max(36500).default(0),
1556
+ repo_convention: exports_external.number().int().min(0).max(36500).default(0),
1557
+ api_finding: exports_external.number().int().min(0).max(36500).default(180),
1558
+ code_pattern: exports_external.number().int().min(0).max(36500).default(90),
1559
+ test_pattern: exports_external.number().int().min(0).max(36500).default(90),
1560
+ failure_pattern: exports_external.number().int().min(0).max(36500).default(90),
1561
+ security_note: exports_external.number().int().min(0).max(36500).default(0),
1562
+ evidence: exports_external.number().int().min(0).max(36500).default(180),
1563
+ todo: exports_external.number().int().min(0).max(36500).default(30),
1564
+ scratch: exports_external.number().int().min(0).max(36500).default(7)
1565
+ }).default({
1566
+ user_preference: 0,
1567
+ project_fact: 0,
1568
+ architecture_decision: 0,
1569
+ repo_convention: 0,
1570
+ api_finding: 180,
1571
+ code_pattern: 90,
1572
+ test_pattern: 90,
1573
+ failure_pattern: 90,
1574
+ security_note: 0,
1575
+ evidence: 180,
1576
+ todo: 30,
1577
+ scratch: 7
1578
+ })
1579
+ }).default({
1580
+ enabled: false,
1581
+ maxClustersPerPass: 10,
1582
+ jaccardThreshold: 0.3,
1583
+ autoApplyMinConfidence: 0.6,
1584
+ decayHalfLifeDays: {
1585
+ user_preference: 0,
1586
+ project_fact: 0,
1587
+ architecture_decision: 0,
1588
+ repo_convention: 0,
1589
+ api_finding: 180,
1590
+ code_pattern: 90,
1591
+ test_pattern: 90,
1592
+ failure_pattern: 90,
1593
+ security_note: 0,
1594
+ evidence: 180,
1595
+ todo: 30,
1596
+ scratch: 7
1597
+ }
1512
1598
  }),
1513
1599
  hardDelete: exports_external.boolean().default(false)
1514
1600
  });
@@ -5,10 +5,12 @@ import {
5
5
  inferTags,
6
6
  readKnowledge,
7
7
  resolveHiveKnowledgePath,
8
+ resolveKnowledgeStoreDir,
8
9
  resolveSwarmKnowledgePath,
10
+ resolveSwarmRejectedPath,
9
11
  rewriteKnowledge,
10
12
  transactKnowledge
11
- } from "./index-e8pk68cc.js";
13
+ } from "./index-axwxkbdd.js";
12
14
  import {
13
15
  atomicWriteFile
14
16
  } from "./index-fjwwrwr5.js";
@@ -47,13 +49,13 @@ var RECEIPT_EVENT_TYPES = new Set([
47
49
  "override"
48
50
  ]);
49
51
  function resolveKnowledgeEventsPath(directory) {
50
- return path.join(directory, ".swarm", "knowledge-events.jsonl");
52
+ return path.join(resolveKnowledgeStoreDir(directory), "knowledge-events.jsonl");
51
53
  }
52
54
  function resolveKnowledgeCounterBaselinePath(directory) {
53
- return path.join(directory, ".swarm", "knowledge-counter-baseline.json");
55
+ return path.join(resolveKnowledgeStoreDir(directory), "knowledge-counter-baseline.json");
54
56
  }
55
57
  function resolveLegacyApplicationLogPath(directory) {
56
- return path.join(directory, ".swarm", "knowledge-application.jsonl");
58
+ return path.join(resolveKnowledgeStoreDir(directory), "knowledge-application.jsonl");
57
59
  }
58
60
  async function readKnowledgeEvents(directory, maxEvents) {
59
61
  const filePath = resolveKnowledgeEventsPath(directory);
@@ -770,7 +772,7 @@ function validateActionability(entry) {
770
772
  return { actionable: false, reason };
771
773
  }
772
774
  function resolveUnactionablePath(directory) {
773
- return path2.join(directory, ".swarm", "knowledge-unactionable.jsonl");
775
+ return path2.join(resolveKnowledgeStoreDir(directory), "knowledge-unactionable.jsonl");
774
776
  }
775
777
  async function appendUnactionable(directory, entry, reason) {
776
778
  const filePath = resolveUnactionablePath(directory);
@@ -808,10 +810,10 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
808
810
  return;
809
811
  }
810
812
  const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
811
- const knowledgePath = path2.join(directory, ".swarm", "knowledge.jsonl");
812
- const quarantinePath = path2.join(directory, ".swarm", "knowledge-quarantined.jsonl");
813
- const rejectedPath = path2.join(directory, ".swarm", "knowledge-rejected.jsonl");
814
- const swarmDir = path2.join(directory, ".swarm");
813
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
814
+ const quarantinePath = path2.join(resolveKnowledgeStoreDir(directory), "knowledge-quarantined.jsonl");
815
+ const rejectedPath = resolveSwarmRejectedPath(directory);
816
+ const swarmDir = resolveKnowledgeStoreDir(directory);
815
817
  await mkdir2(swarmDir, { recursive: true });
816
818
  let release;
817
819
  try {
@@ -872,10 +874,11 @@ async function restoreEntry(directory, entryId) {
872
874
  warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
873
875
  return;
874
876
  }
875
- const knowledgePath = path2.join(directory, ".swarm", "knowledge.jsonl");
876
- const quarantinePath = path2.join(directory, ".swarm", "knowledge-quarantined.jsonl");
877
- const rejectedPath = path2.join(directory, ".swarm", "knowledge-rejected.jsonl");
878
- const swarmDir = path2.join(directory, ".swarm");
877
+ const storeDir = resolveKnowledgeStoreDir(directory);
878
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
879
+ const quarantinePath = path2.join(storeDir, "knowledge-quarantined.jsonl");
880
+ const rejectedPath = resolveSwarmRejectedPath(directory);
881
+ const swarmDir = storeDir;
879
882
  await mkdir2(swarmDir, { recursive: true });
880
883
  let release;
881
884
  try {
@@ -1654,7 +1657,7 @@ async function generateSkills(req) {
1654
1657
  continue;
1655
1658
  }
1656
1659
  }
1657
- const content = renderSkillMarkdown(cluster, req.mode);
1660
+ let content = renderSkillMarkdown(cluster, req.mode);
1658
1661
  if (await isRejectedSkillContent(req.directory, cluster.slug, content)) {
1659
1662
  result.skipped.push({
1660
1663
  slug: cluster.slug,
@@ -1696,54 +1699,124 @@ async function generateSkills(req) {
1696
1699
  continue;
1697
1700
  }
1698
1701
  }
1699
- await atomicWrite2(targetPath, content);
1702
+ let missingSourceIds = [];
1700
1703
  if (req.mode === "active") {
1701
- await stampSourceEntries(req.directory, cluster.slug, cluster.entries.map((e) => e.id));
1704
+ const idsToStamp = req.sourceKnowledgeIds?.length ? req.sourceKnowledgeIds : cluster.entries.map((e) => e.id);
1705
+ const { missing } = await stampSourceEntries(req.directory, cluster.slug, idsToStamp);
1706
+ missingSourceIds = missing;
1707
+ if (missingSourceIds.length > 0) {
1708
+ content = injectMissingIdsIntoFrontmatter(content, missingSourceIds);
1709
+ }
1702
1710
  }
1711
+ await atomicWrite2(targetPath, content);
1703
1712
  result.written.push({
1704
1713
  slug: cluster.slug,
1705
1714
  path: targetPath,
1706
1715
  mode: req.mode,
1707
1716
  sourceKnowledgeIds: cluster.entries.map((e) => e.id),
1717
+ missingSourceKnowledgeIds: missingSourceIds,
1708
1718
  preserved,
1709
1719
  evaluation
1710
1720
  });
1711
1721
  }
1712
1722
  return result;
1713
1723
  }
1724
+ function injectMissingIdsIntoFrontmatter(content, missingIds) {
1725
+ if (missingIds.length === 0)
1726
+ return content;
1727
+ const stripped = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
1728
+ const openFence = stripped.match(/^---[ \t]*\r?\n/);
1729
+ if (!openFence)
1730
+ return content;
1731
+ const fenceLen = openFence[0].length;
1732
+ const closeFence = stripped.slice(fenceLen).match(/\n---[ \t]*(\r?\n|$)/);
1733
+ if (!closeFence)
1734
+ return content;
1735
+ const closeStart = fenceLen + (closeFence.index ?? 0);
1736
+ const body = stripped.slice(fenceLen, closeStart).replace(/\r\n/g, `
1737
+ `);
1738
+ const sourceIdx = body.indexOf("source_knowledge_ids:");
1739
+ if (sourceIdx === -1)
1740
+ return content;
1741
+ const afterLabel = body.indexOf(`
1742
+ `, sourceIdx);
1743
+ const listStart = afterLabel === -1 ? body.length : afterLabel + 1;
1744
+ const lines = body.split(`
1745
+ `);
1746
+ let insertIdx = -1;
1747
+ for (let i = 0;i < lines.length; i++) {
1748
+ if (lines[i].length === 0)
1749
+ continue;
1750
+ const relativePos = body.indexOf(lines[i], listStart);
1751
+ if (relativePos >= 0 && relativePos < listStart + 2)
1752
+ continue;
1753
+ if (body.slice(listStart, body.indexOf(lines[i], listStart)).match(/^\s+-/)) {
1754
+ continue;
1755
+ }
1756
+ insertIdx = body.indexOf(lines[i], listStart);
1757
+ break;
1758
+ }
1759
+ if (insertIdx === -1)
1760
+ insertIdx = body.length;
1761
+ const missingBlock = [
1762
+ "missing_source_knowledge_ids:",
1763
+ ...missingIds.map((id) => ` - ${id}`),
1764
+ ""
1765
+ ].join(`
1766
+ `);
1767
+ const newBody = body.slice(0, insertIdx) + missingBlock + body.slice(insertIdx);
1768
+ const prefix = stripped.slice(0, fenceLen);
1769
+ const suffix = stripped.slice(closeStart);
1770
+ return prefix + newBody + suffix;
1771
+ }
1714
1772
  async function stampSourceEntries(directory, slug, ids) {
1715
1773
  if (!ids || ids.length === 0)
1716
- return;
1774
+ return { stamped: [], missing: [] };
1717
1775
  const swarmPath = resolveSwarmKnowledgePath(directory);
1718
1776
  const swarm = await readKnowledge(swarmPath);
1719
1777
  const idSet = new Set(ids);
1720
- let touched = false;
1778
+ const stamped = [];
1779
+ const missing = [];
1780
+ const found = new Set;
1721
1781
  const repoRel = activeRepoRelativePath(slug);
1722
1782
  for (const e of swarm) {
1723
1783
  if (!idSet.has(e.id))
1724
1784
  continue;
1785
+ found.add(e.id);
1725
1786
  e.generated_skill_slug = slug;
1726
1787
  e.generated_skill_path = repoRel;
1727
1788
  e.updated_at = new Date().toISOString();
1728
- touched = true;
1729
1789
  }
1730
- if (touched)
1790
+ if (found.size > 0)
1731
1791
  await rewriteKnowledge(swarmPath, swarm);
1792
+ stamped.push(...found);
1732
1793
  const hivePath = resolveHiveKnowledgePath();
1733
- if (!existsSync3(hivePath))
1734
- return;
1794
+ if (!existsSync3(hivePath)) {
1795
+ for (const id of ids) {
1796
+ if (!found.has(id))
1797
+ missing.push(id);
1798
+ }
1799
+ return { stamped, missing };
1800
+ }
1735
1801
  const hive = await readKnowledge(hivePath);
1736
- let touchedHive = false;
1802
+ const foundHive = new Set;
1737
1803
  for (const e of hive) {
1738
1804
  if (!idSet.has(e.id))
1739
1805
  continue;
1806
+ foundHive.add(e.id);
1740
1807
  e.generated_skill_slug = slug;
1741
1808
  e.generated_skill_path = repoRel;
1742
1809
  e.updated_at = new Date().toISOString();
1743
- touchedHive = true;
1744
1810
  }
1745
- if (touchedHive)
1811
+ if (foundHive.size > 0)
1746
1812
  await rewriteKnowledge(hivePath, hive);
1813
+ stamped.push(...foundHive);
1814
+ const allFound = new Set([...found, ...foundHive]);
1815
+ for (const id of ids) {
1816
+ if (!allFound.has(id))
1817
+ missing.push(id);
1818
+ }
1819
+ return { stamped, missing };
1747
1820
  }
1748
1821
  function parseDraftFrontmatter(content) {
1749
1822
  const stripped = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
@@ -12,14 +12,14 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-g6f4tt38.js";
15
+ } from "./index-9w07ye9b.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
19
19
  isInDeclaredScope,
20
20
  redactPath,
21
21
  redactShellCommand
22
- } from "./index-g00qm2gf.js";
22
+ } from "./index-6tnmt41c.js";
23
23
 
24
24
  // src/services/guardrail-explain-service.ts
25
25
  import path from "path";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  stripKnownSwarmPrefix
4
- } from "./index-0asbrmdx.js";
4
+ } from "./index-123s7kjc.js";
5
5
  import {
6
6
  init_logger,
7
7
  warn