agentix-cli 0.135.0 → 0.136.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.
- package/dist/{App-4UVAI5C5.js → App-D6W6IV2L.js} +2 -2
- package/dist/{ChatApp-COO67WIR.js → ChatApp-X7TNCFGW.js} +2 -2
- package/dist/{absorb-eval-WY3YMLS4.js → absorb-eval-COPVH2M2.js} +2 -2
- package/dist/{agent-3R5NY7I3.js → agent-VCGAUBER.js} +2 -2
- package/dist/{board-dashboard-U3ZSCO62.js → board-dashboard-JZM3FQNV.js} +4 -4
- package/dist/{board-dashboard-U3ZSCO62.js.map → board-dashboard-JZM3FQNV.js.map} +1 -1
- package/dist/chunk-4ZWZ42YE.js +5 -0
- package/dist/{chunk-KXR6GVL7.js.map → chunk-4ZWZ42YE.js.map} +1 -1
- package/dist/{chunk-DYGQF3MI.js → chunk-54OORW5I.js} +2 -2
- package/dist/chunk-54OORW5I.js.map +1 -0
- package/dist/{chunk-RVEMX5MJ.js → chunk-5J5USW2O.js} +2 -2
- package/dist/{chunk-3XVST5XX.js → chunk-5X37CXJF.js} +2 -2
- package/dist/{chunk-4XMALK7X.js → chunk-66DPMVUC.js} +2 -2
- package/dist/{chunk-SSQMFHSM.js → chunk-AK3XOA5N.js} +2 -2
- package/dist/chunk-AKWBDCMU.js +4 -0
- package/dist/chunk-AKWBDCMU.js.map +1 -0
- package/dist/{chunk-6WF56ME6.js → chunk-C43E3YFT.js} +2 -2
- package/dist/{chunk-LU7GDHGD.js → chunk-EVTTAM7S.js} +2 -2
- package/dist/{chunk-K445URSN.js → chunk-FQLSV2C4.js} +2 -2
- package/dist/{chunk-FWDRBUMS.js → chunk-GL3H7XMI.js} +2 -2
- package/dist/{chunk-ZGVVYJIK.js → chunk-H2N7DOPT.js} +2 -2
- package/dist/{chunk-BQIWMQNU.js → chunk-H4NSB54D.js} +2 -2
- package/dist/{chunk-XOUO4XNA.js → chunk-HEJTE7OC.js} +2 -2
- package/dist/{chunk-EEBK4F6E.js → chunk-HH7OFAEM.js} +2 -2
- package/dist/{chunk-QDWEM4DG.js → chunk-HZZW35FY.js} +2 -2
- package/dist/{chunk-RRGITX5B.js → chunk-IPMXIPTS.js} +2 -2
- package/dist/{chunk-MI7WOGH6.js → chunk-K75LFQE3.js} +2 -2
- package/dist/{chunk-ZFRXFUP7.js → chunk-KZXQD6ZK.js} +2 -2
- package/dist/{chunk-P3I7AATX.js → chunk-M5AHI2PZ.js} +2 -2
- package/dist/{chunk-5NT44FKL.js → chunk-M5B4QG6J.js} +2 -2
- package/dist/chunk-MTX4UPNB.js +3 -0
- package/dist/chunk-MTX4UPNB.js.map +1 -0
- package/dist/chunk-MWNCS57L.js +2 -0
- package/dist/chunk-MWNCS57L.js.map +1 -0
- package/dist/chunk-OISCRNMW.js +105 -0
- package/dist/chunk-OISCRNMW.js.map +1 -0
- package/dist/{chunk-ERULJ2ZL.js → chunk-OW5EXDVY.js} +2 -2
- package/dist/chunk-OWNQ2FD4.js +3 -0
- package/dist/chunk-OWNQ2FD4.js.map +1 -0
- package/dist/chunk-PE5V2LI7.js +2 -0
- package/dist/chunk-PE5V2LI7.js.map +1 -0
- package/dist/chunk-PV623BLN.js +55 -0
- package/dist/chunk-PV623BLN.js.map +1 -0
- package/dist/{chunk-L5UGH4T4.js → chunk-QCUJTAAZ.js} +6 -6
- package/dist/{chunk-GSKJ57XY.js → chunk-QTDKNJXD.js} +216 -216
- package/dist/chunk-QTDKNJXD.js.map +1 -0
- package/dist/{chunk-RGZARSHV.js → chunk-ROLSSYXE.js} +1 -1
- package/dist/{chunk-RGZARSHV.js.map → chunk-ROLSSYXE.js.map} +1 -1
- package/dist/{chunk-YA3P77LV.js → chunk-SKSYII3K.js} +2 -2
- package/dist/chunk-U6EJ53DA.js +16 -0
- package/dist/chunk-U6EJ53DA.js.map +1 -0
- package/dist/{chunk-WEPON4FP.js → chunk-UNIXYV3U.js} +2 -2
- package/dist/{chunk-SMAI7U6H.js → chunk-VA24JS2S.js} +2 -2
- package/dist/{chunk-LUYN6RAC.js → chunk-WRJFKA43.js} +2 -2
- package/dist/{chunk-H6VWU2HN.js → chunk-ZPJVDX2U.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-NFPBE6L4.js → client-SMOWSRJY.js} +2 -2
- package/dist/{config-GHMRBRDL.js → config-OGUDWYAA.js} +2 -2
- package/dist/{config-mutate-2XV27EFV.js → config-mutate-BH27TMWK.js} +2 -2
- package/dist/config-mutator-Q62AS2TR.js +2 -0
- package/dist/{contributions-KLRJ4ZXV.js → contributions-H6T65TCY.js} +2 -2
- package/dist/{contributions-KLRJ4ZXV.js.map → contributions-H6T65TCY.js.map} +1 -1
- package/dist/{doctor-UBXVMGJG.js → doctor-ZOXHT7ZQ.js} +2 -2
- package/dist/enrich-R2LIDLPZ.js +2 -0
- package/dist/event-levels-WOYYEWSZ.js +3 -0
- package/dist/event-levels-WOYYEWSZ.js.map +1 -0
- package/dist/fact-proposals-X2O4W7VN.js +2 -0
- package/dist/{follow-up-tool-EARVITTS.js → follow-up-tool-GUBBXNEZ.js} +2 -2
- package/dist/{grants-HIFE6L5N.js → grants-CEUGZBQ4.js} +2 -2
- package/dist/hub-IIW2GBO5.js +2 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ledger-P62U3FHT.js +2 -0
- package/dist/load-LQ2I2PQI.js +2 -0
- package/dist/model-call-J7JATTMW.js +2 -0
- package/dist/{program-U3HJY7E5.js → program-WROQ55F5.js} +233 -231
- package/dist/program-WROQ55F5.js.map +1 -0
- package/dist/promote-HDLU44MX.js +2 -0
- package/dist/push-bridge-325SXDGN.js +1 -1
- package/dist/query-6G27CBZQ.js +2 -0
- package/dist/query-runs-VXS572PQ.js +6 -0
- package/dist/query-runs-VXS572PQ.js.map +1 -0
- package/dist/{query-settings-2MGUS6AY.js → query-settings-G4M75LVQ.js} +3 -3
- package/dist/registry-3RE5SG22.js +2 -0
- package/dist/{request-planner-MFAIVLUQ.js → request-planner-T3VCZVVQ.js} +2 -2
- package/dist/{review-candidates-6WMDVVIZ.js → review-candidates-C3O3CENL.js} +2 -2
- package/dist/rotation-memo-store-Z4D5KRA6.js +2 -0
- package/dist/{rotation-memo-store-A4YW6FSK.js.map → rotation-memo-store-Z4D5KRA6.js.map} +1 -1
- package/dist/{routing-OPCLHIYW.js → routing-LD35TJM5.js} +2 -2
- package/dist/rules-HUUFXQD6.js +24 -0
- package/dist/rules-HUUFXQD6.js.map +1 -0
- package/dist/schedule-tool-46TVGEYU.js +2 -0
- package/dist/{scheduler-G3WWYETY.js → scheduler-I3QB4GI3.js} +2 -2
- package/dist/score-LNJ46A67.js +3 -0
- package/dist/score-LNJ46A67.js.map +1 -0
- package/dist/{seat-3HM4J7IX.js → seat-4Y3EW3KU.js} +2 -2
- package/dist/{select-VEFE2ESF.js → select-LZKN3FER.js} +2 -2
- package/dist/{set-enabled-US5BYKFZ.js → set-enabled-WSTOHJDE.js} +2 -2
- package/dist/{tool-HUSCHORN.js → tool-AKXO2EJU.js} +2 -2
- package/dist/tool-NLMIUOHR.js +4 -0
- package/dist/tool-NLMIUOHR.js.map +1 -0
- package/dist/types-YZX46RES.js +2 -0
- package/dist/wiki-ZS6OHOWQ.js +2 -0
- package/dist/wiki-enrich-NGPFWTVA.js +2 -0
- package/dist/wiki-enrich-NGPFWTVA.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-AKLZ4YO2.js +0 -4
- package/dist/chunk-AKLZ4YO2.js.map +0 -1
- package/dist/chunk-DYGQF3MI.js.map +0 -1
- package/dist/chunk-GSKJ57XY.js.map +0 -1
- package/dist/chunk-JRS5QRZG.js +0 -2
- package/dist/chunk-JRS5QRZG.js.map +0 -1
- package/dist/chunk-JTDUTCUE.js +0 -3
- package/dist/chunk-JTDUTCUE.js.map +0 -1
- package/dist/chunk-KA2UIZXG.js +0 -3
- package/dist/chunk-KA2UIZXG.js.map +0 -1
- package/dist/chunk-KXR6GVL7.js +0 -5
- package/dist/chunk-NY7NHGVT.js +0 -105
- package/dist/chunk-NY7NHGVT.js.map +0 -1
- package/dist/chunk-WWDYDLY2.js +0 -55
- package/dist/chunk-WWDYDLY2.js.map +0 -1
- package/dist/config-mutator-6ITNU5DT.js +0 -2
- package/dist/enrich-ZB5I7KHN.js +0 -16
- package/dist/enrich-ZB5I7KHN.js.map +0 -1
- package/dist/event-levels-CQWHSLMT.js +0 -3
- package/dist/event-levels-CQWHSLMT.js.map +0 -1
- package/dist/fact-proposals-LZWS5KFO.js +0 -2
- package/dist/hub-TILTOOSS.js +0 -2
- package/dist/ledger-CH7R756S.js +0 -2
- package/dist/load-EOZUZK7U.js +0 -2
- package/dist/model-call-PKV5UAQ7.js +0 -2
- package/dist/program-U3HJY7E5.js.map +0 -1
- package/dist/promote-RHVZB2QZ.js +0 -2
- package/dist/query-OZXZVLO7.js +0 -2
- package/dist/query-runs-7VX3YAC3.js +0 -4
- package/dist/query-runs-7VX3YAC3.js.map +0 -1
- package/dist/registry-LZLIPP7N.js +0 -2
- package/dist/rotation-memo-store-A4YW6FSK.js +0 -2
- package/dist/schedule-tool-KPVTMYL3.js +0 -2
- package/dist/score-DZGPLHCL.js +0 -3
- package/dist/score-DZGPLHCL.js.map +0 -1
- package/dist/tool-XLWLXGB5.js +0 -4
- package/dist/tool-XLWLXGB5.js.map +0 -1
- package/dist/types-LJZ2YY5W.js +0 -2
- package/dist/wiki-GCRRINW3.js +0 -2
- package/dist/wiki-enrich-P5TNWACZ.js +0 -2
- /package/dist/{App-4UVAI5C5.js.map → App-D6W6IV2L.js.map} +0 -0
- /package/dist/{ChatApp-COO67WIR.js.map → ChatApp-X7TNCFGW.js.map} +0 -0
- /package/dist/{absorb-eval-WY3YMLS4.js.map → absorb-eval-COPVH2M2.js.map} +0 -0
- /package/dist/{agent-3R5NY7I3.js.map → agent-VCGAUBER.js.map} +0 -0
- /package/dist/{chunk-RVEMX5MJ.js.map → chunk-5J5USW2O.js.map} +0 -0
- /package/dist/{chunk-3XVST5XX.js.map → chunk-5X37CXJF.js.map} +0 -0
- /package/dist/{chunk-4XMALK7X.js.map → chunk-66DPMVUC.js.map} +0 -0
- /package/dist/{chunk-SSQMFHSM.js.map → chunk-AK3XOA5N.js.map} +0 -0
- /package/dist/{chunk-6WF56ME6.js.map → chunk-C43E3YFT.js.map} +0 -0
- /package/dist/{chunk-LU7GDHGD.js.map → chunk-EVTTAM7S.js.map} +0 -0
- /package/dist/{chunk-K445URSN.js.map → chunk-FQLSV2C4.js.map} +0 -0
- /package/dist/{chunk-FWDRBUMS.js.map → chunk-GL3H7XMI.js.map} +0 -0
- /package/dist/{chunk-ZGVVYJIK.js.map → chunk-H2N7DOPT.js.map} +0 -0
- /package/dist/{chunk-BQIWMQNU.js.map → chunk-H4NSB54D.js.map} +0 -0
- /package/dist/{chunk-XOUO4XNA.js.map → chunk-HEJTE7OC.js.map} +0 -0
- /package/dist/{chunk-EEBK4F6E.js.map → chunk-HH7OFAEM.js.map} +0 -0
- /package/dist/{chunk-QDWEM4DG.js.map → chunk-HZZW35FY.js.map} +0 -0
- /package/dist/{chunk-RRGITX5B.js.map → chunk-IPMXIPTS.js.map} +0 -0
- /package/dist/{chunk-MI7WOGH6.js.map → chunk-K75LFQE3.js.map} +0 -0
- /package/dist/{chunk-ZFRXFUP7.js.map → chunk-KZXQD6ZK.js.map} +0 -0
- /package/dist/{chunk-P3I7AATX.js.map → chunk-M5AHI2PZ.js.map} +0 -0
- /package/dist/{chunk-5NT44FKL.js.map → chunk-M5B4QG6J.js.map} +0 -0
- /package/dist/{chunk-ERULJ2ZL.js.map → chunk-OW5EXDVY.js.map} +0 -0
- /package/dist/{chunk-L5UGH4T4.js.map → chunk-QCUJTAAZ.js.map} +0 -0
- /package/dist/{chunk-YA3P77LV.js.map → chunk-SKSYII3K.js.map} +0 -0
- /package/dist/{chunk-WEPON4FP.js.map → chunk-UNIXYV3U.js.map} +0 -0
- /package/dist/{chunk-SMAI7U6H.js.map → chunk-VA24JS2S.js.map} +0 -0
- /package/dist/{chunk-LUYN6RAC.js.map → chunk-WRJFKA43.js.map} +0 -0
- /package/dist/{chunk-H6VWU2HN.js.map → chunk-ZPJVDX2U.js.map} +0 -0
- /package/dist/{client-NFPBE6L4.js.map → client-SMOWSRJY.js.map} +0 -0
- /package/dist/{config-GHMRBRDL.js.map → config-OGUDWYAA.js.map} +0 -0
- /package/dist/{config-mutate-2XV27EFV.js.map → config-mutate-BH27TMWK.js.map} +0 -0
- /package/dist/{config-mutator-6ITNU5DT.js.map → config-mutator-Q62AS2TR.js.map} +0 -0
- /package/dist/{doctor-UBXVMGJG.js.map → doctor-ZOXHT7ZQ.js.map} +0 -0
- /package/dist/{fact-proposals-LZWS5KFO.js.map → enrich-R2LIDLPZ.js.map} +0 -0
- /package/dist/{grants-HIFE6L5N.js.map → fact-proposals-X2O4W7VN.js.map} +0 -0
- /package/dist/{follow-up-tool-EARVITTS.js.map → follow-up-tool-GUBBXNEZ.js.map} +0 -0
- /package/dist/{hub-TILTOOSS.js.map → grants-CEUGZBQ4.js.map} +0 -0
- /package/dist/{ledger-CH7R756S.js.map → hub-IIW2GBO5.js.map} +0 -0
- /package/dist/{load-EOZUZK7U.js.map → ledger-P62U3FHT.js.map} +0 -0
- /package/dist/{model-call-PKV5UAQ7.js.map → load-LQ2I2PQI.js.map} +0 -0
- /package/dist/{promote-RHVZB2QZ.js.map → model-call-J7JATTMW.js.map} +0 -0
- /package/dist/{query-OZXZVLO7.js.map → promote-HDLU44MX.js.map} +0 -0
- /package/dist/{registry-LZLIPP7N.js.map → query-6G27CBZQ.js.map} +0 -0
- /package/dist/{query-settings-2MGUS6AY.js.map → query-settings-G4M75LVQ.js.map} +0 -0
- /package/dist/{routing-OPCLHIYW.js.map → registry-3RE5SG22.js.map} +0 -0
- /package/dist/{request-planner-MFAIVLUQ.js.map → request-planner-T3VCZVVQ.js.map} +0 -0
- /package/dist/{review-candidates-6WMDVVIZ.js.map → review-candidates-C3O3CENL.js.map} +0 -0
- /package/dist/{schedule-tool-KPVTMYL3.js.map → routing-LD35TJM5.js.map} +0 -0
- /package/dist/{scheduler-G3WWYETY.js.map → schedule-tool-46TVGEYU.js.map} +0 -0
- /package/dist/{seat-3HM4J7IX.js.map → scheduler-I3QB4GI3.js.map} +0 -0
- /package/dist/{types-LJZ2YY5W.js.map → seat-4Y3EW3KU.js.map} +0 -0
- /package/dist/{select-VEFE2ESF.js.map → select-LZKN3FER.js.map} +0 -0
- /package/dist/{set-enabled-US5BYKFZ.js.map → set-enabled-WSTOHJDE.js.map} +0 -0
- /package/dist/{tool-HUSCHORN.js.map → tool-AKXO2EJU.js.map} +0 -0
- /package/dist/{wiki-GCRRINW3.js.map → types-YZX46RES.js.map} +0 -0
- /package/dist/{wiki-enrich-P5TNWACZ.js.map → wiki-ZS6OHOWQ.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/wiki/contributions.ts"],"sourcesContent":["import { createHash } from \"crypto\"\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from \"fs\"\nimport { resolve } from \"path\"\nimport type Database from \"better-sqlite3\"\nimport { buildIndex, scoreAll } from \"@/memory/bm25\"\nimport { getTrace, listTraces } from \"@/storage/traces\"\nimport { FactLedger } from \"./facts/ledger\"\nimport { lostStructuredFacts } from \"./fact-guard\"\nimport type { WikiHub } from \"./hub\"\nimport type { WikiStore } from \"./store\"\nimport { isWikiArticleType, type WikiArticle, type WikiArticleType } from \"./types\"\n\n// --- Daily per-agent wiki contributions (#824) ---\n//\n// Only the central absorb wrote the wiki, and it missed what agents learn\n// while working: a fleet test found money and status facts weeks stale\n// although the owning agent had checked the current values that day.\n//\n// So each opted-in agent reviews its own work once a day (its chat turns\n// and its task traces, with the tool calls it ran) and proposes small,\n// sourced patches:\n//\n// add one fact line for a page\n// correct the page states an old value; give the exact old text and\n// the new value\n// create a short page for an entity that has none\n//\n// Every patch needs a source and a check date; one without is dropped.\n// There is no field for a page body, so an agent cannot rewrite a page:\n// rewrites are what lost facts in the test.\n//\n// One merge a day applies them all. Facts go through the fact ledger\n// (facts/ledger.ts), so the newest check wins and the older value stays\n// in the fact's history; pages keep every earlier body in `_versions/`.\n// A patch that removes a fact, or an edit that would lose a phone number,\n// email, role, contact marker, link or number, is held for a person.\n//\n// Storage, all skipped by the article index (`_` prefix):\n// _contributions/state.json per-agent cursor\n// _contributions/pending/<run>.json one batch per agent run\n// _contributions/merged/<run>.json batches a merge consumed\n// _contributions/reports/<time>.json what each merge did\n// _contributions/held.json patches waiting for a person\n\nexport type ContributionKind = \"add\" | \"correct\" | \"create\" | \"remove\"\n\nexport interface ContributionPatch {\n /** Stable for the same agent, page, attribute, value and check. */\n id: string\n kind: ContributionKind\n /** Title of the page the patch is about. */\n page: string\n /** For `create`: the article type. */\n pageType?: WikiArticleType\n /** For `create`: other names the subject goes by. */\n aliases?: string[]\n /** \"phone\", \"billing status\", \"main contact\"… */\n attribute?: string\n value?: string\n /** For `correct` and `remove`: the exact text on the page that is wrong. */\n previous?: string\n /** For `create`: one sentence saying what the entity is. */\n summary?: string\n /** Where the agent checked it: a system, command, URL or \"owner said\". */\n source: string\n /** When it was checked (ISO). */\n checkedAt: string\n agentId: string\n}\n\nexport interface ContributionBatch {\n id: string\n agentId: string\n runAt: string\n model: string\n /** Chat entries and task traces the run read. */\n workIds: string[]\n patches: ContributionPatch[]\n costUsd: number\n calls: number\n /** Why the run stopped before reading all of the agent's new work. */\n stoppedBy?: \"max-patches\" | \"max-cost\" | \"max-items\"\n}\n\nexport interface ContributionLimits {\n /** Patches one run may submit. */\n maxPatches: number\n /** Model spend one run may reach, in USD. Each call is capped at what\n * is left, and no call starts once it is spent. */\n maxCostUsd: number\n /** Chat entries and task traces one run reads. */\n maxItems: number\n}\n\nexport const DEFAULT_CONTRIBUTION_LIMITS: ContributionLimits = { maxPatches: 30, maxCostUsd: 0.5, maxItems: 60 }\n\n/** Work items sent to the model per call. */\nconst ITEMS_PER_CALL = 12\nconst ITEM_CHARS = 2000\nconst PAGE_CHARS = 1500\nconst PAGES_PER_CALL = 8\nconst FIELD_CHARS = 300\nconst STEPS_PER_TRACE = 12\nexport const FACTS_HEADING = \"## Checked facts\"\n\n// --- Storage -----------------------------------------------------------------\n\nexport function contributionsDir(wikiDir: string): string {\n return resolve(wikiDir, \"_contributions\")\n}\n\ninterface ContributionState {\n agents: Record<string, { lastRunAt: string; processed: string[] }>\n}\n\nfunction readJson<T>(file: string, fallback: T): T {\n if (!existsSync(file)) return fallback\n try {\n return JSON.parse(readFileSync(file, \"utf-8\")) as T\n } catch (err) {\n // A damaged file read as empty would be overwritten on the next save.\n throw new Error(`${file} is not valid JSON: ${(err as Error).message}`)\n }\n}\n\nfunction writeJson(file: string, data: unknown): void {\n mkdirSync(resolve(file, \"..\"), { recursive: true })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, `${JSON.stringify(data, null, 2)}\\n`)\n renameSync(tmp, file)\n}\n\nfunction readState(wikiDir: string): ContributionState {\n const s = readJson<ContributionState>(resolve(contributionsDir(wikiDir), \"state.json\"), { agents: {} })\n return { agents: s.agents ?? {} }\n}\n\nexport function listPendingBatches(wikiDir: string): ContributionBatch[] {\n const dir = resolve(contributionsDir(wikiDir), \"pending\")\n if (!existsSync(dir)) return []\n return readdirSync(dir).filter((f) => f.endsWith(\".json\")).sort()\n .map((f) => readJson<ContributionBatch | null>(resolve(dir, f), null))\n .filter((b): b is ContributionBatch => !!b)\n}\n\nexport interface HeldPatch {\n id: string\n patch: ContributionPatch\n reason: string\n /** Facts the change would have lost. */\n lost?: string[]\n heldAt: string\n status: \"held\" | \"approved\" | \"rejected\"\n decidedBy?: string\n decidedAt?: string\n}\n\nfunction heldFile(wikiDir: string): string {\n return resolve(contributionsDir(wikiDir), \"held.json\")\n}\n\n/** Held patches; only those still waiting unless `all`. */\nexport function listHeld(wikiDir: string, opts: { all?: boolean } = {}): HeldPatch[] {\n const list = readJson<HeldPatch[]>(heldFile(wikiDir), [])\n return opts.all ? list : list.filter((h) => h.status === \"held\")\n}\n\nexport function latestReport(wikiDir: string): MergeReport | null {\n const dir = resolve(contributionsDir(wikiDir), \"reports\")\n if (!existsSync(dir)) return null\n const last = readdirSync(dir).filter((f) => f.endsWith(\".json\")).sort().pop()\n return last ? readJson<MergeReport | null>(resolve(dir, last), null) : null\n}\n\n// --- What a run reads --------------------------------------------------------\n\n/** One piece of the agent's work: a chat turn or a task it ran. */\nexport interface WorkItem {\n id: string\n /** ISO time (or date) the work happened. */\n at: string\n kind: \"chat\" | \"task\"\n title: string\n text: string\n}\n\n/**\n * The agent's work since its last run, oldest first: its chat entries\n * from the wiki's raw pool and, given the trace database, the tasks it ran\n * with their tool calls and results. On a first run `since` (default:\n * the day before `now`) bounds the window.\n */\nexport function pendingWork(\n hub: WikiHub, wikiDir: string, agentId: string,\n opts: { db?: Database.Database; since?: string; now?: number } = {},\n): WorkItem[] {\n const state = readState(wikiDir).agents[agentId]\n const now = opts.now ?? Date.now()\n const since = opts.since ?? state?.lastRunAt ?? new Date(now - 86_400_000).toISOString()\n const sinceDay = since.slice(0, 10)\n const done = new Set(state?.processed ?? [])\n const items: WorkItem[] = []\n\n for (const e of hub.getAgentEntries(agentId)) {\n if (e.date < sinceDay || done.has(e.id)) continue\n items.push({ id: e.id, at: e.date, kind: \"chat\", title: [e.source, e.sourceContext].filter(Boolean).join(\" · \"), text: e.content })\n }\n\n if (opts.db) {\n const sinceMs = Date.parse(since)\n for (const t of listTraces(opts.db, { agentId, since: Number.isFinite(sinceMs) ? sinceMs : undefined, limit: 500 })) {\n if (t.status === \"in-flight\" || done.has(t.taskId)) continue\n const steps = getTrace(opts.db, t.taskId)?.steps ?? []\n const tools = steps\n .filter((s) => s.name === \"tool_use\" || s.action)\n .slice(0, STEPS_PER_TRACE)\n .map((s) => `- ${s.action ?? s.name}${s.inputSummary ? ` ${clip(s.inputSummary, 160)}` : \"\"}${s.outputSummary ? ` → ${clip(s.outputSummary, 240)}` : \"\"}${s.error ? ` ✗ ${clip(s.error, 120)}` : \"\"}`)\n const text = [\n `Request: ${clip(t.originalMessage ?? t.messagePreview ?? \"\", 600)}`,\n tools.length ? `Tool calls:\\n${tools.join(\"\\n\")}` : \"\",\n t.finalResponse ? `Reply: ${clip(t.finalResponse, 800)}` : \"\",\n ].filter(Boolean).join(\"\\n\")\n items.push({ id: t.taskId, at: new Date(t.startedAt).toISOString(), kind: \"task\", title: `task ${t.taskId}${t.channel ? ` · ${t.channel}` : \"\"}`, text })\n }\n }\n return items.sort((a, b) => a.at.localeCompare(b.at) || a.id.localeCompare(b.id))\n}\n\nfunction saveCursor(wikiDir: string, agentId: string, read: WorkItem[], unread: WorkItem[], now: number): void {\n const state = readState(wikiDir)\n const prev = state.agents[agentId]\n // The cursor stays on the oldest item not read yet, so a run cut short\n // by a cap picks up there tomorrow; ids read at or after it are skipped.\n const lastRunAt = unread.length ? unread[0].at : new Date(now).toISOString()\n const processed = [...new Set([...(prev?.processed ?? []), ...read.map((w) => w.id)])].slice(-5000)\n state.agents[agentId] = { lastRunAt, processed }\n writeJson(resolve(contributionsDir(wikiDir), \"state.json\"), state)\n}\n\n// --- The run -----------------------------------------------------------------\n\n/** One model call: the reply text and what it cost. `maxCostUsd` is what\n * is left of the run's cap; the call must not spend more. */\nexport type ContributionCall = (prompt: string, maxCostUsd: number) => Promise<{ text: string; costUsd?: number }>\n\nexport interface ContributeOptions extends Partial<ContributionLimits> {\n model: string\n call: ContributionCall\n db?: Database.Database\n since?: string\n now?: number\n /** Compute the batch without saving it or moving the cursor. */\n dryRun?: boolean\n}\n\n/**\n * Review an agent's work since its last run and queue sourced patches\n * for the daily merge. Stops at the patch cap, the cost cap or the item\n * cap, whichever comes first.\n */\nexport async function runContribution(hub: WikiHub, wikiDir: string, agentId: string, opts: ContributeOptions): Promise<ContributionBatch> {\n const limits: ContributionLimits = {\n maxPatches: opts.maxPatches ?? DEFAULT_CONTRIBUTION_LIMITS.maxPatches,\n maxCostUsd: opts.maxCostUsd ?? DEFAULT_CONTRIBUTION_LIMITS.maxCostUsd,\n maxItems: opts.maxItems ?? DEFAULT_CONTRIBUTION_LIMITS.maxItems,\n }\n const now = opts.now ?? Date.now()\n const all = pendingWork(hub, wikiDir, agentId, { db: opts.db, since: opts.since, now })\n const pages = all.length ? readablePages(hub, agentId) : []\n const batch: ContributionBatch = {\n id: `${new Date(now).toISOString().replace(/[:.]/g, \"-\")}-${agentId.replace(/[^\\w-]+/g, \"_\")}`,\n agentId, runAt: new Date(now).toISOString(), model: opts.model,\n workIds: [], patches: [], costUsd: 0, calls: 0,\n }\n\n const read: WorkItem[] = []\n const seen = new Set<string>()\n while (read.length < all.length) {\n if (batch.patches.length >= limits.maxPatches) { batch.stoppedBy = \"max-patches\"; break }\n if (batch.costUsd >= limits.maxCostUsd) { batch.stoppedBy = \"max-cost\"; break }\n if (read.length >= limits.maxItems) { batch.stoppedBy = \"max-items\"; break }\n const chunk = all.slice(read.length, read.length + Math.min(ITEMS_PER_CALL, limits.maxItems - read.length))\n const prompt = buildContributionPrompt(agentId, chunk, relevantPages(pages, chunk), limits.maxPatches - batch.patches.length)\n const reply = await opts.call(prompt, Math.max(0.01, limits.maxCostUsd - batch.costUsd))\n batch.calls++\n batch.costUsd += reply.costUsd ?? 0\n read.push(...chunk)\n for (const p of parseContributionPatches(reply.text, agentId, { now })) {\n if (batch.patches.length >= limits.maxPatches) break\n if (seen.has(p.id)) continue\n seen.add(p.id)\n batch.patches.push(p)\n }\n }\n batch.workIds = read.map((w) => w.id)\n batch.costUsd = Math.round(batch.costUsd * 10_000) / 10_000\n\n if (!opts.dryRun) {\n if (batch.patches.length) writeJson(resolve(contributionsDir(wikiDir), \"pending\", `${batch.id}.json`), batch)\n saveCursor(wikiDir, agentId, read, all.slice(read.length), now)\n }\n return batch\n}\n\ninterface PageRef {\n title: string\n aliases: string[]\n type?: WikiArticleType\n lastUpdated?: string\n content: string\n}\n\n/** Every page the agent may read: its own, then the shared wiki's. */\nfunction readablePages(hub: WikiHub, agentId: string): PageRef[] {\n const out: PageRef[] = []\n const add = (store: WikiStore, skip?: (p: string) => boolean) => {\n for (const a of store.listArticles(agentId)) {\n if (a.path.includes(\"/_versions/\") || skip?.(a.path)) continue\n out.push({ title: a.meta.title, aliases: a.meta.aliases ?? [], type: a.meta.type, lastUpdated: a.meta.lastUpdated, content: a.content })\n }\n }\n add(hub.getAgentWiki(agentId))\n for (const s of hub.sharedScope(agentId)) add(s.store, s.skip)\n return out\n}\n\n/**\n * Pages the work most likely touches: half by title and alias, half by\n * body. Titles alone missed a stale page whose title was worded\n * differently from the work, and the model created a duplicate instead\n * of correcting it (#824 review).\n */\nfunction relevantPages(pages: PageRef[], items: WorkItem[]): PageRef[] {\n if (pages.length === 0) return []\n const text = items.map((w) => `${w.title} ${w.text}`).join(\"\\n\")\n const byTitle = scoreAll(text, buildIndex(pages.map((p) => [p.title, ...p.aliases].join(\" \"))))\n const byBody = scoreAll(text, buildIndex(pages.map((p) => `${p.title} ${p.aliases.join(\" \")} ${clip(p.content, 4000)}`)))\n const picked: number[] = []\n const half = Math.ceil(PAGES_PER_CALL / 2)\n for (const r of byTitle.slice(0, half)) picked.push(r.docIndex)\n for (const r of byBody) {\n if (picked.length >= PAGES_PER_CALL) break\n if (!picked.includes(r.docIndex)) picked.push(r.docIndex)\n }\n for (const r of byTitle.slice(half)) {\n if (picked.length >= PAGES_PER_CALL) break\n if (!picked.includes(r.docIndex)) picked.push(r.docIndex)\n }\n return picked.map((i) => pages[i])\n}\n\nexport function buildContributionPrompt(agentId: string, items: WorkItem[], pages: PageRef[], maxPatches: number): string {\n const work = items.map((w) => `### ${w.at.slice(0, 16)} · ${w.kind} · ${w.title}\\n${clip(w.text, ITEM_CHARS)}`).join(\"\\n\\n\")\n const wiki = pages.length\n ? pages.map((p) => `### ${p.title}${p.type ? ` [${p.type}]` : \"\"}${p.lastUpdated ? ` (updated ${p.lastUpdated})` : \"\"}\\n${clip(p.content, PAGE_CHARS)}`).join(\"\\n\\n\")\n : \"(no matching pages)\"\n return `You are agent \"${agentId}\". Below is your own work since your last wiki contribution (chat turns, and tasks with the tool calls you ran and what they returned) and the wiki pages it seems to touch. Propose small, sourced patches to the shared wiki from what you actually used or checked.\n\n## Your work\n\n${work}\n\n## Current wiki pages\n\n${wiki}\n\n## Patch kinds\n\n- \"add\": a fact you used or checked that the page lacks.\n- \"correct\": the page states something your work shows is wrong or out of date. Put the exact wrong text from the page in \"previous\", and the right value in \"value\".\n- \"create\": an entity (person, organization, project, invoice, place…) you dealt with that has no page. Give a one-sentence \"summary\"; add its facts as separate \"add\" patches on the same page title.\n\n## Rules\n\n- Only facts your work shows you checked (a tool result, a system you read) or were told by someone who knows. No guesses, no inferences, nothing from general knowledge.\n- Every patch names its \"source\": the system, command, URL or person (e.g. \"invoice list in the billing app\", \"owner said in chat\"). A patch without a source is dropped.\n- \"checkedAt\" is the date and time of the work that shows the check (ISO). A patch without it is dropped.\n- One fact per patch: an \"attribute\" (\"phone\", \"role\", \"billing status\", \"due date\") and its \"value\", copied exactly.\n- Never rewrite or summarise a page, and never propose removing a fact.\n- Skip facts a page already states with the same value.\n- Put each fact on the page about its subject. If a page above is about the same thing under another name, use that page (with \"correct\" when it is out of date) instead of creating a new one. Create a page only when none of the pages above is about the subject.\n- State the fact itself, not the story of how you found it.\n- Do not record facts about the wiki, AgentX, this contribution run or your own tools, unless that is your job.\n- Skip anything you could not verify. \"Not checked\" or \"unknown\" is not a fact.\n- At most ${maxPatches} patches. Return [] when there is nothing worth adding.\n\nReturn ONLY a JSON array, no prose, no code fences:\n\n[\n {\"kind\": \"add\", \"page\": \"Exact Page Title\", \"attribute\": \"phone\", \"value\": \"+1 555 0100\", \"source\": \"contacts app\", \"checkedAt\": \"2026-01-31T10:00:00Z\"},\n {\"kind\": \"correct\", \"page\": \"Exact Page Title\", \"attribute\": \"billing status\", \"previous\": \"overdue\", \"value\": \"paid\", \"source\": \"invoice list\", \"checkedAt\": \"2026-01-31T10:00:00Z\"},\n {\"kind\": \"create\", \"page\": \"New Entity Name\", \"pageType\": \"person\", \"summary\": \"One sentence.\", \"source\": \"chat with the owner\", \"checkedAt\": \"2026-01-31T10:00:00Z\"}\n]`\n}\n\n/** Valid patches from a model reply; anything malformed is dropped. */\nexport function parseContributionPatches(raw: string, agentId: string, opts: { now?: number } = {}): ContributionPatch[] {\n const match = raw.match(/\\[[\\s\\S]*\\]/)\n if (!match) return []\n let parsed: unknown\n try { parsed = JSON.parse(match[0]) } catch { return [] }\n if (!Array.isArray(parsed)) return []\n const now = opts.now ?? Date.now()\n const out: ContributionPatch[] = []\n for (const x of parsed) {\n if (!x || typeof x !== \"object\") continue\n const r = x as Record<string, unknown>\n const kind = r.kind\n if (kind !== \"add\" && kind !== \"correct\" && kind !== \"create\" && kind !== \"remove\") continue\n const page = clean(r.page, 120)\n // The fact line adds \"checked <date> by <agent>\" itself.\n const rawSource = clean(r.source, FIELD_CHARS)\n const source = rawSource.replace(/[\\s,;(–—-]*\\bchecked\\b[^;]*$/i, \"\").replace(/[\\s,;(]+$/, \"\") || rawSource\n const checked = typeof r.checkedAt === \"string\" ? Date.parse(r.checkedAt) : NaN\n if (!page || !source || !Number.isFinite(checked)) continue\n const attribute = clean(r.attribute, 60)\n const value = clean(r.value, FIELD_CHARS)\n const previous = clean(r.previous, FIELD_CHARS)\n const summary = clean(r.summary, FIELD_CHARS)\n if ((kind === \"add\" || kind === \"correct\") && (!attribute || !value)) continue\n if (kind === \"remove\" && !attribute && !previous) continue\n if (kind === \"create\" && !summary) continue\n const aliases = Array.isArray(r.aliases) ? r.aliases.map((a) => clean(a, 120)).filter(Boolean).slice(0, 10) : []\n // A check can't be dated after the run.\n const checkedAt = new Date(Math.min(checked, now)).toISOString()\n const body = { kind, page, attribute, value, previous, summary, source, checkedAt, agentId }\n out.push({\n id: createHash(\"sha1\").update(JSON.stringify(body)).digest(\"hex\").slice(0, 12),\n kind, page, source, checkedAt, agentId,\n ...(attribute ? { attribute } : {}),\n ...(value ? { value } : {}),\n ...(previous && kind !== \"add\" && kind !== \"create\" ? { previous } : {}),\n ...(summary && kind === \"create\" ? { summary } : {}),\n ...(kind === \"create\" && isWikiArticleType(r.pageType) ? { pageType: r.pageType } : {}),\n ...(kind === \"create\" && aliases.length ? { aliases } : {}),\n })\n }\n return out\n}\n\n/** One line, trimmed, capped; \"\" for anything not a string. */\nfunction clean(v: unknown, max: number): string {\n return typeof v === \"string\" ? v.replace(/\\s+/g, \" \").trim().slice(0, max) : \"\"\n}\n\nfunction clip(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max)}…` : s\n}\n\n// --- The daily merge -----------------------------------------------------------\n\nexport interface MergeReport {\n at: string\n batches: string[]\n agents: string[]\n patches: number\n /** Facts the ledger took as new, newer or re-checked. */\n applied: Array<{ page: string; attribute: string; value: string; by: string; status: string }>\n /** Pages that got a new or changed fact. */\n pagesUpdated: string[]\n pagesCreated: string[]\n /** Patches with an older check than the wiki's: a question was raised. */\n contradictions: Array<{ page: string; attribute: string; value: string; by: string; questionId?: string }>\n held: Array<{ id: string; page: string; attribute?: string; by: string; reason: string; lost?: string[] }>\n /** Several pages for one subject: listed for a person to merge. */\n duplicates: Array<{ title: string; pages: string[] }>\n dryRun?: boolean\n}\n\ninterface PageTarget {\n agentId: string\n store: WikiStore\n path: string\n article: WikiArticle\n}\n\n/** Title or alias, without case or punctuation. */\nexport function pageKey(title: string): string {\n return (title || \"\").toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, \" \").trim()\n}\n\n/** Every page by title and alias, across agents. Copied agents are read-only here. */\nfunction pageTargets(hub: WikiHub): Map<string, PageTarget[]> {\n const targets = new Map<string, PageTarget[]>()\n for (const id of hub.listAgents()) {\n if (hub.syncedFrom(id)) continue\n const store = hub.getAgentWiki(id)\n for (const article of store.listAllArticles()) {\n if (article.path.includes(\"/_versions/\")) continue\n const keys = new Set([article.meta.title, ...(article.meta.aliases ?? [])].map(pageKey).filter(Boolean))\n for (const k of keys) {\n const list = targets.get(k) ?? []\n list.push({ agentId: id, store, path: article.path, article })\n targets.set(k, list)\n }\n }\n }\n return targets\n}\n\n/**\n * Apply every pending batch. The newest checked fact wins (the fact\n * ledger keeps the older one in its history), new pages for one subject\n * become one page, and a change that would lose a fact is held.\n */\nexport function mergeContributions(hub: WikiHub, wikiDir: string, opts: { now?: number; dryRun?: boolean; log?: (m: string) => void } = {}): MergeReport {\n const now = opts.now ?? Date.now()\n const nowIso = new Date(now).toISOString()\n const today = nowIso.slice(0, 10)\n const batches = listPendingBatches(wikiDir)\n // Oldest check first, so the ledger takes each newer value over the\n // last and keeps the older one in its history.\n const patches = batches.flatMap((b) => b.patches).sort((a, b) => a.checkedAt.localeCompare(b.checkedAt))\n const report: MergeReport = {\n at: nowIso, batches: batches.map((b) => b.id), agents: [...new Set(batches.map((b) => b.agentId))].sort(),\n patches: patches.length, applied: [], pagesUpdated: [], pagesCreated: [], contradictions: [], held: [], duplicates: [],\n ...(opts.dryRun ? { dryRun: true } : {}),\n }\n const held: HeldPatch[] = []\n const hold = (patch: ContributionPatch, reason: string, lost?: string[]) => {\n const id = `h-${patch.id}`\n held.push({ id, patch, reason, heldAt: nowIso, status: \"held\", ...(lost?.length ? { lost } : {}) })\n report.held.push({ id, page: patch.page, attribute: patch.attribute, by: patch.agentId, reason, ...(lost?.length ? { lost } : {}) })\n }\n\n const targets = pageTargets(hub)\n for (const [, list] of targets) {\n const distinct = [...new Map(list.map((t) => [`${t.agentId}:${t.path}`, t])).values()]\n const title = distinct[0]?.article.meta.title\n if (distinct.length > 1 && title && !report.duplicates.some((d) => d.title === title)) {\n report.duplicates.push({ title, pages: distinct.map((t) => `${t.agentId}/${t.path}`) })\n }\n }\n\n // New pages: one per subject, however many agents proposed it. A page\n // that already exists (by title or alias) takes the facts instead.\n const newPages = new Map<string, NewPage>()\n for (const p of patches) {\n if (p.kind !== \"create\") continue\n const key = pageKey(p.page)\n if (targets.has(key)) continue\n const draft = newPages.get(key) ?? { title: p.page, owner: p.agentId, summaries: [], sources: [], aliases: [], at: p.checkedAt }\n draft.type ??= p.pageType\n if (p.summary && !draft.summaries.includes(p.summary)) draft.summaries.push(p.summary)\n if (!draft.sources.includes(p.source)) draft.sources.push(p.source)\n for (const a of p.aliases ?? []) if (!draft.aliases.includes(a)) draft.aliases.push(a)\n newPages.set(key, draft)\n }\n for (const p of patches) {\n const key = pageKey(p.page)\n if ((p.kind === \"add\" || p.kind === \"correct\") && !targets.has(key) && !newPages.has(key)) {\n // A fact about a subject with no page and no `create`: start one.\n newPages.set(key, { title: p.page, owner: p.agentId, summaries: [], sources: [p.source], aliases: [], at: p.checkedAt })\n }\n }\n\n // A new page whose title is a near match of an existing one is probably\n // that page under a longer or shorter name; creating it is how the\n // first trial duplicated a stale page instead of correcting it.\n const existing = [...targets.values()].map((list) => list[0])\n const duplicateOf = new Map<string, string>()\n for (const [key, draft] of newPages) {\n const match = possibleDuplicate(draft.title, draft.type, existing.map((t) => ({ title: t.article.meta.title, type: t.article.meta.type, ref: `${t.agentId}/${t.path}` })))\n if (match) duplicateOf.set(key, match)\n }\n for (const key of duplicateOf.keys()) newPages.delete(key)\n\n const ledger = new FactLedger(wikiDir)\n // Keyed by the page itself, not by the name a patch used: a title patch\n // and an alias patch to one page each started from the same stored\n // body, and the second write dropped the first one's lines.\n const edits = new Map<string, PageEdit[]>()\n const editTargets = new Map<string, PageTarget>()\n const editKey = (key: string) => {\n const t = targets.get(key)?.[0]\n if (!t) return `new:${key}`\n const k = `page:${t.agentId}:${t.path}`\n editTargets.set(k, t)\n return k\n }\n for (const p of patches) {\n const key = pageKey(p.page)\n const dup = duplicateOf.get(key)\n if (dup && p.kind !== \"remove\") { hold(p, `possible duplicate of ${dup}`); continue }\n if (p.kind === \"create\") continue\n if (p.kind === \"remove\") { hold(p, \"removes a fact\"); continue }\n const target = targets.get(key)?.[0]\n if (target && !target.store.canRead(target.article.meta, p.agentId)) {\n hold(p, \"the contributing agent cannot read this page\")\n continue\n }\n const subject = target?.article.meta.title ?? newPages.get(key)!.title\n let status = \"planned\"\n let value = p.value!\n if (!opts.dryRun) {\n const r = ledger.write({ subject, attribute: p.attribute!, value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n status = r.status\n if (r.status === \"contradiction\") {\n report.contradictions.push({ page: subject, attribute: p.attribute!, value, by: p.agentId, questionId: r.questionId })\n continue\n }\n if (r.status === \"unchanged\") continue\n value = r.fact.value\n }\n report.applied.push({ page: subject, attribute: p.attribute!, value, by: p.agentId, status })\n const list = edits.get(editKey(key)) ?? []\n const previous = p.kind === \"correct\" ? p.previous : undefined\n list.push({ line: { attribute: p.attribute!, value, source: p.source, checkedAt: p.checkedAt, by: p.agentId, previous }, previous, patch: p })\n edits.set(editKey(key), list)\n }\n\n const touched = new Set<WikiStore>()\n for (const [key, list] of edits) {\n const target = editTargets.get(key)\n if (!target) continue\n const r = updatePage(target, list, { guard: true, today, dryRun: opts.dryRun })\n if (r.lost) for (const e of list) hold(e.patch, \"the change would lose facts the page has\", r.lost)\n else if (r.denied) for (const e of list) hold(e.patch, `write denied for ${target.agentId}/${target.path}`)\n else if (r.changed) {\n report.pagesUpdated.push(`${target.agentId}/${target.path}`)\n if (!opts.dryRun) touched.add(target.store)\n }\n }\n\n for (const [key, draft] of newPages) {\n const list = edits.get(`new:${key}`) ?? []\n if (!draft.summaries.length && !list.length) continue\n const store = hub.getAgentWiki(draft.owner)\n const path = newPagePath(store, draft.title, draft.type)\n report.pagesCreated.push(`${draft.owner}/${path}`)\n if (opts.dryRun) continue\n if (createPage(store, path, draft, list.map((e) => e.line), today)) touched.add(store)\n }\n\n if (!opts.dryRun) {\n for (const store of touched) {\n try { store.rebuildIndex() } catch (err) { opts.log?.(`index rebuild failed: ${(err as Error).message}`) }\n }\n const dir = contributionsDir(wikiDir)\n if (held.length) {\n const known = listHeld(wikiDir, { all: true })\n writeJson(heldFile(wikiDir), [...known, ...held.filter((h) => !known.some((k) => k.id === h.id))])\n }\n mkdirSync(resolve(dir, \"merged\"), { recursive: true })\n for (const b of batches) renameSync(resolve(dir, \"pending\", `${b.id}.json`), resolve(dir, \"merged\", `${b.id}.json`))\n writeJson(resolve(dir, \"reports\", `${nowIso.replace(/[:.]/g, \"-\")}.json`), report)\n }\n return report\n}\n\nfunction createPage(store: WikiStore, path: string, draft: NewPage, lines: FactLine[], today: string): boolean {\n const intro = draft.summaries.length ? draft.summaries.join(\" \") : `${draft.title}.`\n const { body } = applyFactLines(`${intro}\\n\\n_Sources: ${draft.sources.join(\"; \")}._`, lines)\n return store.writeArticle(path, {\n title: draft.title,\n ...(draft.type ? { type: draft.type } : {}),\n ...(draft.aliases.length ? { aliases: draft.aliases } : {}),\n tags: [],\n owner: draft.owner,\n access: \"public\",\n created: today,\n lastUpdated: today,\n sources: [contributionStamp(draft.owner, draft.at), ...lines.map((l) => contributionStamp(l.by, l.checkedAt))]\n .filter((s, i, a) => a.indexOf(s) === i),\n }, body, draft.owner)\n}\n\nconst TITLE_STOPWORDS = new Set([\"the\", \"and\", \"for\", \"with\", \"von\", \"des\", \"les\", \"der\", \"die\", \"das\", \"une\", \"pour\", \"page\", \"of\", \"de\", \"la\", \"le\", \"du\", \"et\"])\n\nfunction titleTokens(title: string): Set<string> {\n return new Set((title.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? []).filter((t) => (t.length > 2 || /\\d/.test(t)) && !TITLE_STOPWORDS.has(t)))\n}\n\n/**\n * The existing page a new title most likely means, or undefined. A match\n * shares at least two significant words and most of the shorter title's\n * words (\"Tax Payment Plan\" and \"Tax Payment Plan Engagement 4471\"). A\n * person page never matches a page of another type, and titles carrying\n * different numbers never match.\n */\nexport function possibleDuplicate(\n title: string, type: WikiArticleType | undefined,\n pages: Array<{ title: string; type?: WikiArticleType; ref: string }>,\n): string | undefined {\n const mine = titleTokens(title)\n if (mine.size < 2) return undefined\n let best: { ref: string; title: string; score: number } | undefined\n for (const p of pages) {\n if (type && p.type && (type === \"person\") !== (p.type === \"person\")) continue\n const theirs = titleTokens(p.title)\n if (theirs.size < 2) continue\n // Two numbered things (invoices, issues) with different numbers are\n // different things, however alike the rest of the title.\n const nums = (set: Set<string>) => [...set].filter((t) => /\\d/.test(t))\n const [a, b] = [nums(mine), nums(theirs)]\n if (a.length && b.length && !a.some((n) => b.includes(n))) continue\n let shared = 0\n for (const t of mine) if (theirs.has(t)) shared++\n const score = shared / Math.min(mine.size, theirs.size)\n if (shared >= 2 && score >= 0.75 && (!best || score > best.score)) best = { ref: p.ref, title: p.title, score }\n }\n return best ? `\"${best.title}\" (${best.ref})` : undefined\n}\n\ninterface NewPage {\n title: string\n type?: WikiArticleType\n owner: string\n summaries: string[]\n sources: string[]\n aliases: string[]\n /** Earliest check behind it. */\n at: string\n}\n\ninterface PageEdit {\n line: FactLine\n /** For a correction the ledger accepted: the exact wrong text to replace in place. */\n previous?: string\n patch: ContributionPatch\n}\n\n/**\n * Write a page's fact lines and in-place corrections. With `guard`, an\n * edit that would lose a structured fact is not written and the lost\n * facts are returned.\n */\nfunction updatePage(\n target: PageTarget, list: PageEdit[],\n opts: { guard: boolean; today: string; dryRun?: boolean; remove?: { attribute?: string; text?: string } },\n): { changed: boolean; lost?: string[]; denied?: boolean } {\n const before = target.article.content\n let { body, superseded } = applyFactLines(before, list.map((e) => e.line))\n for (const e of list) {\n if (!e.previous || e.previous === e.line.value) continue\n const fixed = replaceOnce(body, e.previous, e.line.value)\n if (fixed !== body) { body = fixed; superseded.push(e.previous) }\n }\n if (opts.remove) body = removeFact(body, opts.remove)\n if (body === before) return { changed: false }\n if (opts.guard) {\n const lost = lostStructuredFacts(before, body, superseded)\n if (lost.length) return { changed: false, lost }\n }\n if (opts.dryRun) return { changed: true }\n const meta = target.article.meta\n const stamps = list.map((e) => contributionStamp(e.line.by, e.line.checkedAt))\n const ok = target.store.writeArticle(target.path, {\n ...meta,\n lastUpdated: opts.today,\n sources: [...meta.sources, ...stamps].filter((s, i, a) => a.indexOf(s) === i),\n }, body, meta.owner)\n return ok ? { changed: true } : { changed: false, denied: true }\n}\n\n/** Replace `old` with `next` when it occurs exactly once, as whole words,\n * outside the \"Checked facts\" section; anything else is ambiguous and\n * left alone. Whole words, so \"paid\" is not rewritten inside \"unpaid\". */\nexport function replaceOnce(body: string, old: string, next: string): string {\n if (!old) return body\n const at = body.indexOf(FACTS_HEADING)\n const prose = at === -1 ? body : body.slice(0, at)\n const escaped = old.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n const hits = [...prose.matchAll(new RegExp(`(?<![\\\\p{L}\\\\p{N}])${escaped}(?![\\\\p{L}\\\\p{N}])`, \"gu\"))]\n if (hits.length !== 1) return body\n const first = hits[0].index!\n return body.slice(0, first) + next + body.slice(first + old.length)\n}\n\nfunction removeFact(body: string, remove: { attribute?: string; text?: string }): string {\n let out = body\n if (remove.attribute) {\n const attr = remove.attribute.toLowerCase()\n out = out.split(\"\\n\").filter((l) => l.match(LINE_RE)?.[1].toLowerCase() !== attr).join(\"\\n\")\n }\n if (remove.text) out = replaceOnce(out, remove.text, \"\")\n return out\n}\n\n// --- Held patches: a person decides ----------------------------------------\n\nexport type HeldDecision = { ok: true; held: HeldPatch; page?: string } | { ok: false; error: string }\n\n/**\n * Apply a held patch as it is, without the fact-loss guard: a person\n * looked at it. A removal deletes the attribute's fact line and the\n * exact text it names; the page's previous body stays in `_versions/`.\n */\nexport function approveHeld(hub: WikiHub, wikiDir: string, id: string, opts: { by?: string; now?: number } = {}): HeldDecision {\n const all = listHeld(wikiDir, { all: true })\n const h = all.find((x) => x.id === id)\n if (!h) return { ok: false, error: `no held patch \"${id}\"` }\n if (h.status !== \"held\") return { ok: false, error: `\"${id}\" is already ${h.status}` }\n const p = h.patch\n const now = opts.now ?? Date.now()\n const today = new Date(now).toISOString().slice(0, 10)\n const target = pageTargets(hub).get(pageKey(p.page))?.[0]\n if (!target) {\n // A held `create` (a possible duplicate), or a fact for the page it\n // would have made: a person said it is a new subject after all.\n if (p.kind === \"remove\") return { ok: false, error: `no page \"${p.page}\" (it may have been renamed)` }\n const lines: FactLine[] = []\n if (p.attribute && p.value) {\n const w = new FactLedger(wikiDir).write({ subject: p.page, attribute: p.attribute, value: p.value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n if (w.status === \"contradiction\") return { ok: false, error: `the wiki has a newer check of ${p.attribute}; answer question ${w.questionId ?? \"(see wiki questions)\"} instead` }\n lines.push({ attribute: p.attribute, value: w.fact.value, source: p.source, checkedAt: p.checkedAt, by: p.agentId })\n }\n const store = hub.getAgentWiki(p.agentId)\n const path = newPagePath(store, p.page, p.pageType)\n const draft: NewPage = { title: p.page, type: p.pageType, owner: p.agentId, summaries: p.summary ? [p.summary] : [], sources: [p.source], aliases: p.aliases ?? [], at: p.checkedAt }\n if (!createPage(store, path, draft, lines, today)) return { ok: false, error: `write denied for ${p.agentId}/${path}` }\n try { store.rebuildIndex() } catch { /* the page is written; the next rebuild indexes it */ }\n return decide(wikiDir, all, h, \"approved\", opts.by, now, `${p.agentId}/${path}`)\n }\n\n let r: { changed: boolean; denied?: boolean }\n if (p.kind === \"remove\") {\n r = updatePage(target, [], { guard: false, today, remove: { attribute: p.attribute, text: p.previous } })\n } else {\n if (!p.attribute || !p.value) return { ok: false, error: `\"${id}\" carries no fact to apply` }\n const w = new FactLedger(wikiDir).write({ subject: target.article.meta.title, attribute: p.attribute, value: p.value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n if (w.status === \"contradiction\") return { ok: false, error: `the wiki has a newer check of ${p.attribute}; answer question ${w.questionId ?? \"(see wiki questions)\"} instead` }\n const previous = p.kind === \"correct\" ? p.previous : undefined\n r = updatePage(target, [{ line: { attribute: p.attribute, value: w.fact.value, source: p.source, checkedAt: p.checkedAt, by: p.agentId, previous }, previous, patch: p }], { guard: false, today })\n }\n if (r.denied) return { ok: false, error: `write denied for ${target.agentId}/${target.path}` }\n if (r.changed) {\n try { target.store.rebuildIndex() } catch { /* the page is written; the next rebuild indexes it */ }\n }\n return decide(wikiDir, all, h, \"approved\", opts.by, now, `${target.agentId}/${target.path}`)\n}\n\nexport function rejectHeld(wikiDir: string, id: string, opts: { by?: string; now?: number } = {}): HeldDecision {\n const all = listHeld(wikiDir, { all: true })\n const h = all.find((x) => x.id === id)\n if (!h) return { ok: false, error: `no held patch \"${id}\"` }\n if (h.status !== \"held\") return { ok: false, error: `\"${id}\" is already ${h.status}` }\n return decide(wikiDir, all, h, \"rejected\", opts.by, opts.now ?? Date.now())\n}\n\nfunction decide(wikiDir: string, all: HeldPatch[], h: HeldPatch, status: \"approved\" | \"rejected\", by: string | undefined, now: number, page?: string): HeldDecision {\n const decided: HeldPatch = { ...h, status, decidedBy: by ?? \"operator\", decidedAt: new Date(now).toISOString() }\n writeJson(heldFile(wikiDir), all.map((x) => (x.id === h.id ? decided : x)))\n return { ok: true, held: decided, ...(page ? { page } : {}) }\n}\n\n// --- Page text -----------------------------------------------------------------\n\nexport interface FactLine {\n attribute: string\n value: string\n source: string\n checkedAt: string\n by: string\n previous?: string\n}\n\nconst LINE_RE = /^- \\*\\*(.+?):\\*\\* /\n\n/**\n * Add or update one line per attribute in the page's \"Checked facts\"\n * section. Nothing outside that section changes. A changed value keeps\n * the old one on its line as \"previously\", so a correction never drops a\n * fact from the page.\n *\n * `superseded` holds the replaced lines: their older parts live on in the\n * ledger's history and the page's versions, so the guard lets them go.\n */\nexport function applyFactLines(body: string, lines: FactLine[]): { body: string; superseded: string[] } {\n if (lines.length === 0) return { body, superseded: [] }\n const all = body.replace(/\\s+$/, \"\").split(\"\\n\")\n const start = all.findIndex((l) => l.trim() === FACTS_HEADING)\n let head = all\n let section: string[] = []\n let tail: string[] = []\n if (start !== -1) {\n head = all.slice(0, start)\n const rest = all.slice(start + 1)\n const end = rest.findIndex((l) => /^#{1,2} /.test(l))\n section = (end === -1 ? rest : rest.slice(0, end)).filter((l) => l.trim())\n tail = end === -1 ? [] : rest.slice(end)\n }\n\n const superseded: string[] = []\n for (const l of lines) {\n const at = section.findIndex((s) => s.match(LINE_RE)?.[1].toLowerCase() === l.attribute.toLowerCase())\n const old = at === -1 ? undefined : parseFactLine(section[at])\n if (at !== -1) superseded.push(section[at])\n // A re-check of the same value refreshes the line and keeps its history.\n const previous = old && old.value === l.value ? old.previous : old ? `${old.value}, checked ${old.checkedAt}` : l.previous\n // An existing line keeps its spelling of the attribute.\n const attribute = section[at]?.match(LINE_RE)?.[1] ?? l.attribute\n const line = renderFactLine({ ...l, attribute, previous })\n if (at === -1) section.push(line)\n else section[at] = line\n }\n\n const out = [...(head.some((l) => l.trim()) ? [...head, \"\"] : []), FACTS_HEADING, \"\", ...section]\n if (tail.length) out.push(\"\", ...tail)\n return { body: out.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trim(), superseded }\n}\n\nfunction renderFactLine(l: FactLine): string {\n const prev = l.previous ? ` (previously: ${l.previous})` : \"\"\n return `- **${l.attribute}:** ${l.value} — ${l.source}; checked ${l.checkedAt.slice(0, 10)} by ${l.by}${prev}`\n}\n\nfunction parseFactLine(line: string): { value: string; checkedAt: string; previous?: string } | undefined {\n const m = line.match(/^- \\*\\*.+?:\\*\\* (.*?) — .*?; checked (\\S+) by \\S+(?: \\(previously: (.*)\\))?$/)\n return m ? { value: m[1], checkedAt: m[2], ...(m[3] ? { previous: m[3] } : {}) } : undefined\n}\n\nfunction contributionStamp(agentId: string, at: string): string {\n return `contribution:${agentId}@${at.slice(0, 10)}`\n}\n\nconst TYPE_FOLDER: Record<WikiArticleType, string> = {\n person: \"people\", project: \"projects\", place: \"places\", concept: \"concepts\",\n event: \"events\", decision: \"decisions\", pattern: \"patterns\",\n}\n\nfunction newPagePath(store: WikiStore, title: string, type?: WikiArticleType): string {\n const slug = title.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, \"-\").replace(/^-+|-+$/g, \"\").slice(0, 60) || \"page\"\n const folder = type ? TYPE_FOLDER[type] : \"contributions\"\n let path = `${folder}/${slug}.md`\n for (let n = 2; store.readArticle(path); n++) path = `${folder}/${slug}-${n}.md`\n return path\n}\n"],"mappings":"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","names":["createHash","existsSync","mkdirSync","readdirSync","readFileSync","renameSync","writeFileSync","resolve","DEFAULT_CONTRIBUTION_LIMITS","ITEMS_PER_CALL","ITEM_CHARS","PAGE_CHARS","PAGES_PER_CALL","FIELD_CHARS","STEPS_PER_TRACE","FACTS_HEADING","contributionsDir","wikiDir","resolve","readJson","file","fallback","existsSync","readFileSync","err","writeJson","data","mkdirSync","tmp","writeFileSync","renameSync","readState","listPendingBatches","dir","readdirSync","f","b","heldFile","listHeld","opts","list","h","latestReport","last","pendingWork","hub","agentId","state","now","since","sinceDay","done","items","e","sinceMs","t","listTraces","tools","getTrace","s","clip","text","a","saveCursor","read","unread","prev","lastRunAt","processed","w","runContribution","limits","all","pages","readablePages","batch","seen","chunk","prompt","buildContributionPrompt","relevantPages","reply","p","parseContributionPatches","out","add","store","skip","byTitle","scoreAll","buildIndex","byBody","picked","half","r","i","maxPatches","work","wiki","raw","match","parsed","x","kind","page","clean","rawSource","source","checked","attribute","value","previous","summary","aliases","checkedAt","body","createHash","isWikiArticleType","v","max","pageKey","title","pageTargets","targets","id","article","keys","k","mergeContributions","nowIso","today","batches","patches","report","held","hold","patch","reason","lost","distinct","d","newPages","key","draft","existing","duplicateOf","possibleDuplicate","ledger","FactLedger","edits","editTargets","editKey","dup","target","subject","status","touched","updatePage","path","newPagePath","createPage","known","lines","intro","applyFactLines","contributionStamp","l","TITLE_STOPWORDS","titleTokens","type","mine","best","theirs","nums","set","n","shared","score","before","superseded","fixed","replaceOnce","removeFact","lostStructuredFacts","meta","stamps","old","next","at","prose","escaped","hits","first","remove","attr","LINE_RE","approveHeld","decide","rejectHeld","by","decided","start","head","section","tail","rest","end","parseFactLine","line","renderFactLine","m","TYPE_FOLDER","slug","folder"]}
|
|
1
|
+
{"version":3,"sources":["../src/wiki/contributions.ts"],"sourcesContent":["import { createHash } from \"crypto\"\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from \"fs\"\nimport { resolve } from \"path\"\nimport type Database from \"better-sqlite3\"\nimport { buildIndex, scoreAll } from \"@/memory/bm25\"\nimport { getTrace, listTraces } from \"@/storage/traces\"\nimport { FactLedger } from \"./facts/ledger\"\nimport { lostStructuredFacts } from \"./fact-guard\"\nimport type { WikiHub } from \"./hub\"\nimport type { WikiStore } from \"./store\"\nimport { isWikiArticleType, type WikiArticle, type WikiArticleType } from \"./types\"\n\n// --- Daily per-agent wiki contributions (#824) ---\n//\n// Only the central absorb wrote the wiki, and it missed what agents learn\n// while working: a fleet test found money and status facts weeks stale\n// although the owning agent had checked the current values that day.\n//\n// So each opted-in agent reviews its own work once a day (its chat turns\n// and its task traces, with the tool calls it ran) and proposes small,\n// sourced patches:\n//\n// add one fact line for a page\n// correct the page states an old value; give the exact old text and\n// the new value\n// create a short page for an entity that has none\n//\n// Every patch needs a source and a check date; one without is dropped.\n// There is no field for a page body, so an agent cannot rewrite a page:\n// rewrites are what lost facts in the test.\n//\n// One merge a day applies them all. Facts go through the fact ledger\n// (facts/ledger.ts), so the newest check wins and the older value stays\n// in the fact's history; pages keep every earlier body in `_versions/`.\n// A patch that removes a fact, or an edit that would lose a phone number,\n// email, role, contact marker, link or number, is held for a person.\n//\n// Storage, all skipped by the article index (`_` prefix):\n// _contributions/state.json per-agent cursor\n// _contributions/pending/<run>.json one batch per agent run\n// _contributions/merged/<run>.json batches a merge consumed\n// _contributions/reports/<time>.json what each merge did\n// _contributions/held.json patches waiting for a person\n\nexport type ContributionKind = \"add\" | \"correct\" | \"create\" | \"remove\"\n\nexport interface ContributionPatch {\n /** Stable for the same agent, page, attribute, value and check. */\n id: string\n kind: ContributionKind\n /** Title of the page the patch is about. */\n page: string\n /** For `create`: the article type. */\n pageType?: WikiArticleType\n /** For `create`: other names the subject goes by. */\n aliases?: string[]\n /** \"phone\", \"billing status\", \"main contact\"… */\n attribute?: string\n value?: string\n /** For `correct` and `remove`: the exact text on the page that is wrong. */\n previous?: string\n /** For `create`: one sentence saying what the entity is. */\n summary?: string\n /** Where the agent checked it: a system, command, URL or \"owner said\". */\n source: string\n /** When it was checked (ISO). */\n checkedAt: string\n agentId: string\n}\n\nexport interface ContributionBatch {\n id: string\n agentId: string\n runAt: string\n model: string\n /** Chat entries and task traces the run read. */\n workIds: string[]\n patches: ContributionPatch[]\n costUsd: number\n calls: number\n /** Why the run stopped before reading all of the agent's new work. */\n stoppedBy?: \"max-patches\" | \"max-cost\" | \"max-items\"\n}\n\nexport interface ContributionLimits {\n /** Patches one run may submit. */\n maxPatches: number\n /** Model spend one run may reach, in USD. Each call is capped at what\n * is left, and no call starts once it is spent. */\n maxCostUsd: number\n /** Chat entries and task traces one run reads. */\n maxItems: number\n}\n\nexport const DEFAULT_CONTRIBUTION_LIMITS: ContributionLimits = { maxPatches: 30, maxCostUsd: 0.5, maxItems: 60 }\n\n/** Work items sent to the model per call. */\nconst ITEMS_PER_CALL = 12\nconst ITEM_CHARS = 2000\nconst PAGE_CHARS = 1500\nconst PAGES_PER_CALL = 8\nconst FIELD_CHARS = 300\nconst STEPS_PER_TRACE = 12\nexport const FACTS_HEADING = \"## Checked facts\"\n\n// --- Storage -----------------------------------------------------------------\n\nexport function contributionsDir(wikiDir: string): string {\n return resolve(wikiDir, \"_contributions\")\n}\n\ninterface ContributionState {\n agents: Record<string, { lastRunAt: string; processed: string[] }>\n}\n\nfunction readJson<T>(file: string, fallback: T): T {\n if (!existsSync(file)) return fallback\n try {\n return JSON.parse(readFileSync(file, \"utf-8\")) as T\n } catch (err) {\n // A damaged file read as empty would be overwritten on the next save.\n throw new Error(`${file} is not valid JSON: ${(err as Error).message}`)\n }\n}\n\nfunction writeJson(file: string, data: unknown): void {\n mkdirSync(resolve(file, \"..\"), { recursive: true })\n const tmp = `${file}.${process.pid}.tmp`\n writeFileSync(tmp, `${JSON.stringify(data, null, 2)}\\n`)\n renameSync(tmp, file)\n}\n\nfunction readState(wikiDir: string): ContributionState {\n const s = readJson<ContributionState>(resolve(contributionsDir(wikiDir), \"state.json\"), { agents: {} })\n return { agents: s.agents ?? {} }\n}\n\nexport function listPendingBatches(wikiDir: string): ContributionBatch[] {\n const dir = resolve(contributionsDir(wikiDir), \"pending\")\n if (!existsSync(dir)) return []\n return readdirSync(dir).filter((f) => f.endsWith(\".json\")).sort()\n .map((f) => readJson<ContributionBatch | null>(resolve(dir, f), null))\n .filter((b): b is ContributionBatch => !!b)\n}\n\nexport interface HeldPatch {\n id: string\n patch: ContributionPatch\n reason: string\n /** Facts the change would have lost. */\n lost?: string[]\n heldAt: string\n status: \"held\" | \"approved\" | \"rejected\"\n decidedBy?: string\n decidedAt?: string\n}\n\nfunction heldFile(wikiDir: string): string {\n return resolve(contributionsDir(wikiDir), \"held.json\")\n}\n\n/** Held patches; only those still waiting unless `all`. */\nexport function listHeld(wikiDir: string, opts: { all?: boolean } = {}): HeldPatch[] {\n const list = readJson<HeldPatch[]>(heldFile(wikiDir), [])\n return opts.all ? list : list.filter((h) => h.status === \"held\")\n}\n\nexport function latestReport(wikiDir: string): MergeReport | null {\n const dir = resolve(contributionsDir(wikiDir), \"reports\")\n if (!existsSync(dir)) return null\n const last = readdirSync(dir).filter((f) => f.endsWith(\".json\")).sort().pop()\n return last ? readJson<MergeReport | null>(resolve(dir, last), null) : null\n}\n\n// --- What a run reads --------------------------------------------------------\n\n/** One piece of the agent's work: a chat turn or a task it ran. */\nexport interface WorkItem {\n id: string\n /** ISO time (or date) the work happened. */\n at: string\n kind: \"chat\" | \"task\"\n title: string\n text: string\n}\n\n/**\n * The agent's work since its last run, oldest first: its chat entries\n * from the wiki's raw pool and, given the trace database, the tasks it ran\n * with their tool calls and results. On a first run `since` (default:\n * the day before `now`) bounds the window.\n */\nexport function pendingWork(\n hub: WikiHub, wikiDir: string, agentId: string,\n opts: { db?: Database.Database; since?: string; now?: number } = {},\n): WorkItem[] {\n const state = readState(wikiDir).agents[agentId]\n const now = opts.now ?? Date.now()\n const since = opts.since ?? state?.lastRunAt ?? new Date(now - 86_400_000).toISOString()\n const sinceDay = since.slice(0, 10)\n const done = new Set(state?.processed ?? [])\n const items: WorkItem[] = []\n\n for (const e of hub.getAgentEntries(agentId)) {\n if (e.date < sinceDay || done.has(e.id)) continue\n items.push({ id: e.id, at: e.date, kind: \"chat\", title: [e.source, e.sourceContext].filter(Boolean).join(\" · \"), text: e.content })\n }\n\n if (opts.db) {\n const sinceMs = Date.parse(since)\n for (const t of listTraces(opts.db, { agentId, since: Number.isFinite(sinceMs) ? sinceMs : undefined, limit: 500 })) {\n if (t.status === \"in-flight\" || done.has(t.taskId)) continue\n const steps = getTrace(opts.db, t.taskId)?.steps ?? []\n const tools = steps\n .filter((s) => s.name === \"tool_use\" || s.action)\n .slice(0, STEPS_PER_TRACE)\n .map((s) => `- ${s.action ?? s.name}${s.inputSummary ? ` ${clip(s.inputSummary, 160)}` : \"\"}${s.outputSummary ? ` → ${clip(s.outputSummary, 240)}` : \"\"}${s.error ? ` ✗ ${clip(s.error, 120)}` : \"\"}`)\n const text = [\n `Request: ${clip(t.originalMessage ?? t.messagePreview ?? \"\", 600)}`,\n tools.length ? `Tool calls:\\n${tools.join(\"\\n\")}` : \"\",\n t.finalResponse ? `Reply: ${clip(t.finalResponse, 800)}` : \"\",\n ].filter(Boolean).join(\"\\n\")\n items.push({ id: t.taskId, at: new Date(t.startedAt).toISOString(), kind: \"task\", title: `task ${t.taskId}${t.channel ? ` · ${t.channel}` : \"\"}`, text })\n }\n }\n return items.sort((a, b) => a.at.localeCompare(b.at) || a.id.localeCompare(b.id))\n}\n\nfunction saveCursor(wikiDir: string, agentId: string, read: WorkItem[], unread: WorkItem[], now: number): void {\n const state = readState(wikiDir)\n const prev = state.agents[agentId]\n // The cursor stays on the oldest item not read yet, so a run cut short\n // by a cap picks up there tomorrow; ids read at or after it are skipped.\n const lastRunAt = unread.length ? unread[0].at : new Date(now).toISOString()\n const processed = [...new Set([...(prev?.processed ?? []), ...read.map((w) => w.id)])].slice(-5000)\n state.agents[agentId] = { lastRunAt, processed }\n writeJson(resolve(contributionsDir(wikiDir), \"state.json\"), state)\n}\n\n// --- The run -----------------------------------------------------------------\n\n/** One model call: the reply text and what it cost. `maxCostUsd` is what\n * is left of the run's cap; the call must not spend more. */\nexport type ContributionCall = (prompt: string, maxCostUsd: number) => Promise<{ text: string; costUsd?: number }>\n\nexport interface ContributeOptions extends Partial<ContributionLimits> {\n model: string\n call: ContributionCall\n db?: Database.Database\n since?: string\n now?: number\n /** Compute the batch without saving it or moving the cursor. */\n dryRun?: boolean\n}\n\n/**\n * Review an agent's work since its last run and queue sourced patches\n * for the daily merge. Stops at the patch cap, the cost cap or the item\n * cap, whichever comes first.\n */\nexport async function runContribution(hub: WikiHub, wikiDir: string, agentId: string, opts: ContributeOptions): Promise<ContributionBatch> {\n const limits: ContributionLimits = {\n maxPatches: opts.maxPatches ?? DEFAULT_CONTRIBUTION_LIMITS.maxPatches,\n maxCostUsd: opts.maxCostUsd ?? DEFAULT_CONTRIBUTION_LIMITS.maxCostUsd,\n maxItems: opts.maxItems ?? DEFAULT_CONTRIBUTION_LIMITS.maxItems,\n }\n const now = opts.now ?? Date.now()\n const all = pendingWork(hub, wikiDir, agentId, { db: opts.db, since: opts.since, now })\n const pages = all.length ? readablePages(hub, agentId) : []\n const batch: ContributionBatch = {\n id: `${new Date(now).toISOString().replace(/[:.]/g, \"-\")}-${agentId.replace(/[^\\w-]+/g, \"_\")}`,\n agentId, runAt: new Date(now).toISOString(), model: opts.model,\n workIds: [], patches: [], costUsd: 0, calls: 0,\n }\n\n const read: WorkItem[] = []\n const seen = new Set<string>()\n while (read.length < all.length) {\n if (batch.patches.length >= limits.maxPatches) { batch.stoppedBy = \"max-patches\"; break }\n if (batch.costUsd >= limits.maxCostUsd) { batch.stoppedBy = \"max-cost\"; break }\n if (read.length >= limits.maxItems) { batch.stoppedBy = \"max-items\"; break }\n const chunk = all.slice(read.length, read.length + Math.min(ITEMS_PER_CALL, limits.maxItems - read.length))\n const prompt = buildContributionPrompt(agentId, chunk, relevantPages(pages, chunk), limits.maxPatches - batch.patches.length)\n const reply = await opts.call(prompt, Math.max(0.01, limits.maxCostUsd - batch.costUsd))\n batch.calls++\n batch.costUsd += reply.costUsd ?? 0\n read.push(...chunk)\n for (const p of parseContributionPatches(reply.text, agentId, { now })) {\n if (batch.patches.length >= limits.maxPatches) break\n if (seen.has(p.id)) continue\n seen.add(p.id)\n batch.patches.push(p)\n }\n }\n batch.workIds = read.map((w) => w.id)\n batch.costUsd = Math.round(batch.costUsd * 10_000) / 10_000\n\n if (!opts.dryRun) {\n if (batch.patches.length) writeJson(resolve(contributionsDir(wikiDir), \"pending\", `${batch.id}.json`), batch)\n saveCursor(wikiDir, agentId, read, all.slice(read.length), now)\n }\n return batch\n}\n\ninterface PageRef {\n title: string\n aliases: string[]\n type?: WikiArticleType\n lastUpdated?: string\n content: string\n}\n\n/** Every page the agent may read: its own, then the shared wiki's. */\nfunction readablePages(hub: WikiHub, agentId: string): PageRef[] {\n const out: PageRef[] = []\n const add = (store: WikiStore, skip?: (p: string) => boolean) => {\n for (const a of store.listArticles(agentId)) {\n if (a.path.includes(\"/_versions/\") || skip?.(a.path)) continue\n out.push({ title: a.meta.title, aliases: a.meta.aliases ?? [], type: a.meta.type, lastUpdated: a.meta.lastUpdated, content: a.content })\n }\n }\n add(hub.getAgentWiki(agentId))\n for (const s of hub.sharedScope(agentId)) add(s.store, s.skip)\n return out\n}\n\n/**\n * Pages the work most likely touches: half by title and alias, half by\n * body. Titles alone missed a stale page whose title was worded\n * differently from the work, and the model created a duplicate instead\n * of correcting it (#824 review).\n */\nfunction relevantPages(pages: PageRef[], items: WorkItem[]): PageRef[] {\n if (pages.length === 0) return []\n const text = items.map((w) => `${w.title} ${w.text}`).join(\"\\n\")\n const byTitle = scoreAll(text, buildIndex(pages.map((p) => [p.title, ...p.aliases].join(\" \"))))\n const byBody = scoreAll(text, buildIndex(pages.map((p) => `${p.title} ${p.aliases.join(\" \")} ${clip(p.content, 4000)}`)))\n const picked: number[] = []\n const half = Math.ceil(PAGES_PER_CALL / 2)\n for (const r of byTitle.slice(0, half)) picked.push(r.docIndex)\n for (const r of byBody) {\n if (picked.length >= PAGES_PER_CALL) break\n if (!picked.includes(r.docIndex)) picked.push(r.docIndex)\n }\n for (const r of byTitle.slice(half)) {\n if (picked.length >= PAGES_PER_CALL) break\n if (!picked.includes(r.docIndex)) picked.push(r.docIndex)\n }\n return picked.map((i) => pages[i])\n}\n\nexport function buildContributionPrompt(agentId: string, items: WorkItem[], pages: PageRef[], maxPatches: number): string {\n const work = items.map((w) => `### ${w.at.slice(0, 16)} · ${w.kind} · ${w.title}\\n${clip(w.text, ITEM_CHARS)}`).join(\"\\n\\n\")\n const wiki = pages.length\n ? pages.map((p) => `### ${p.title}${p.type ? ` [${p.type}]` : \"\"}${p.lastUpdated ? ` (updated ${p.lastUpdated})` : \"\"}\\n${clip(p.content, PAGE_CHARS)}`).join(\"\\n\\n\")\n : \"(no matching pages)\"\n return `You are agent \"${agentId}\". Below is your own work since your last wiki contribution (chat turns, and tasks with the tool calls you ran and what they returned) and the wiki pages it seems to touch. Propose small, sourced patches to the shared wiki from what you actually used or checked.\n\n## Your work\n\n${work}\n\n## Current wiki pages\n\n${wiki}\n\n## Patch kinds\n\n- \"add\": a fact you used or checked that the page lacks.\n- \"correct\": the page states something your work shows is wrong or out of date. Put the exact wrong text from the page in \"previous\", and the right value in \"value\".\n- \"create\": an entity (person, organization, project, invoice, place…) you dealt with that has no page. Give a one-sentence \"summary\"; add its facts as separate \"add\" patches on the same page title.\n\n## Rules\n\n- Only facts your work shows you checked (a tool result, a system you read) or were told by someone who knows. No guesses, no inferences, nothing from general knowledge.\n- Every patch names its \"source\": the system, command, URL or person (e.g. \"invoice list in the billing app\", \"owner said in chat\"). A patch without a source is dropped.\n- \"checkedAt\" is the date and time of the work that shows the check (ISO). A patch without it is dropped.\n- One fact per patch: an \"attribute\" (\"phone\", \"role\", \"billing status\", \"due date\") and its \"value\", copied exactly.\n- Never rewrite or summarise a page, and never propose removing a fact.\n- Skip facts a page already states with the same value.\n- Put each fact on the page about its subject. If a page above is about the same thing under another name, use that page (with \"correct\" when it is out of date) instead of creating a new one. Create a page only when none of the pages above is about the subject.\n- State the fact itself, not the story of how you found it.\n- Do not record facts about the wiki, AgentX, this contribution run or your own tools, unless that is your job.\n- Skip anything you could not verify. \"Not checked\" or \"unknown\" is not a fact.\n- At most ${maxPatches} patches. Return [] when there is nothing worth adding.\n\nReturn ONLY a JSON array, no prose, no code fences:\n\n[\n {\"kind\": \"add\", \"page\": \"Exact Page Title\", \"attribute\": \"phone\", \"value\": \"+1 555 0100\", \"source\": \"contacts app\", \"checkedAt\": \"2026-01-31T10:00:00Z\"},\n {\"kind\": \"correct\", \"page\": \"Exact Page Title\", \"attribute\": \"billing status\", \"previous\": \"overdue\", \"value\": \"paid\", \"source\": \"invoice list\", \"checkedAt\": \"2026-01-31T10:00:00Z\"},\n {\"kind\": \"create\", \"page\": \"New Entity Name\", \"pageType\": \"person\", \"summary\": \"One sentence.\", \"source\": \"chat with the owner\", \"checkedAt\": \"2026-01-31T10:00:00Z\"}\n]`\n}\n\n/** Valid patches from a model reply; anything malformed is dropped. */\nexport function parseContributionPatches(raw: string, agentId: string, opts: { now?: number } = {}): ContributionPatch[] {\n const match = raw.match(/\\[[\\s\\S]*\\]/)\n if (!match) return []\n let parsed: unknown\n try { parsed = JSON.parse(match[0]) } catch { return [] }\n if (!Array.isArray(parsed)) return []\n const now = opts.now ?? Date.now()\n const out: ContributionPatch[] = []\n for (const x of parsed) {\n if (!x || typeof x !== \"object\") continue\n const r = x as Record<string, unknown>\n const kind = r.kind\n if (kind !== \"add\" && kind !== \"correct\" && kind !== \"create\" && kind !== \"remove\") continue\n const page = clean(r.page, 120)\n // The fact line adds \"checked <date> by <agent>\" itself.\n const rawSource = clean(r.source, FIELD_CHARS)\n const source = rawSource.replace(/[\\s,;(–—-]*\\bchecked\\b[^;]*$/i, \"\").replace(/[\\s,;(]+$/, \"\") || rawSource\n const checked = typeof r.checkedAt === \"string\" ? Date.parse(r.checkedAt) : NaN\n if (!page || !source || !Number.isFinite(checked)) continue\n const attribute = clean(r.attribute, 60)\n const value = clean(r.value, FIELD_CHARS)\n const previous = clean(r.previous, FIELD_CHARS)\n const summary = clean(r.summary, FIELD_CHARS)\n if ((kind === \"add\" || kind === \"correct\") && (!attribute || !value)) continue\n if (kind === \"remove\" && !attribute && !previous) continue\n if (kind === \"create\" && !summary) continue\n const aliases = Array.isArray(r.aliases) ? r.aliases.map((a) => clean(a, 120)).filter(Boolean).slice(0, 10) : []\n // A check can't be dated after the run.\n const checkedAt = new Date(Math.min(checked, now)).toISOString()\n const body = { kind, page, attribute, value, previous, summary, source, checkedAt, agentId }\n out.push({\n id: createHash(\"sha1\").update(JSON.stringify(body)).digest(\"hex\").slice(0, 12),\n kind, page, source, checkedAt, agentId,\n ...(attribute ? { attribute } : {}),\n ...(value ? { value } : {}),\n ...(previous && kind !== \"add\" && kind !== \"create\" ? { previous } : {}),\n ...(summary && kind === \"create\" ? { summary } : {}),\n ...(kind === \"create\" && isWikiArticleType(r.pageType) ? { pageType: r.pageType } : {}),\n ...(kind === \"create\" && aliases.length ? { aliases } : {}),\n })\n }\n return out\n}\n\n/** One line, trimmed, capped; \"\" for anything not a string. */\nfunction clean(v: unknown, max: number): string {\n return typeof v === \"string\" ? v.replace(/\\s+/g, \" \").trim().slice(0, max) : \"\"\n}\n\nfunction clip(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max)}…` : s\n}\n\n// --- The daily merge -----------------------------------------------------------\n\nexport interface MergeReport {\n at: string\n batches: string[]\n agents: string[]\n patches: number\n /** Facts the ledger took as new, newer or re-checked. */\n applied: Array<{ page: string; attribute: string; value: string; by: string; status: string }>\n /** Pages that got a new or changed fact. */\n pagesUpdated: string[]\n pagesCreated: string[]\n /** Patches with an older check than the wiki's: a question was raised. */\n contradictions: Array<{ page: string; attribute: string; value: string; by: string; questionId?: string }>\n held: Array<{ id: string; page: string; attribute?: string; by: string; reason: string; lost?: string[] }>\n /** Several pages for one subject: listed for a person to merge. */\n duplicates: Array<{ title: string; pages: string[] }>\n dryRun?: boolean\n}\n\ninterface PageTarget {\n agentId: string\n store: WikiStore\n path: string\n article: WikiArticle\n}\n\n/** Title or alias, without case or punctuation. */\nexport function pageKey(title: string): string {\n return (title || \"\").toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, \" \").trim()\n}\n\n/** Every page by title and alias, across agents. Copied agents are read-only here. */\nfunction pageTargets(hub: WikiHub): Map<string, PageTarget[]> {\n const targets = new Map<string, PageTarget[]>()\n for (const id of hub.listAgents()) {\n if (hub.syncedFrom(id)) continue\n const store = hub.getAgentWiki(id)\n for (const article of store.listAllArticles()) {\n if (article.path.includes(\"/_versions/\")) continue\n const keys = new Set([article.meta.title, ...(article.meta.aliases ?? [])].map(pageKey).filter(Boolean))\n for (const k of keys) {\n const list = targets.get(k) ?? []\n list.push({ agentId: id, store, path: article.path, article })\n targets.set(k, list)\n }\n }\n }\n return targets\n}\n\n/**\n * Apply every pending batch. The newest checked fact wins (the fact\n * ledger keeps the older one in its history), new pages for one subject\n * become one page, and a change that would lose a fact is held.\n */\nexport function mergeContributions(hub: WikiHub, wikiDir: string, opts: { now?: number; dryRun?: boolean; log?: (m: string) => void } = {}): MergeReport {\n const now = opts.now ?? Date.now()\n const nowIso = new Date(now).toISOString()\n const today = nowIso.slice(0, 10)\n const batches = listPendingBatches(wikiDir)\n // Oldest check first, so the ledger takes each newer value over the\n // last and keeps the older one in its history.\n const patches = batches.flatMap((b) => b.patches).sort((a, b) => a.checkedAt.localeCompare(b.checkedAt))\n const report: MergeReport = {\n at: nowIso, batches: batches.map((b) => b.id), agents: [...new Set(batches.map((b) => b.agentId))].sort(),\n patches: patches.length, applied: [], pagesUpdated: [], pagesCreated: [], contradictions: [], held: [], duplicates: [],\n ...(opts.dryRun ? { dryRun: true } : {}),\n }\n const held: HeldPatch[] = []\n const hold = (patch: ContributionPatch, reason: string, lost?: string[]) => {\n const id = `h-${patch.id}`\n held.push({ id, patch, reason, heldAt: nowIso, status: \"held\", ...(lost?.length ? { lost } : {}) })\n report.held.push({ id, page: patch.page, attribute: patch.attribute, by: patch.agentId, reason, ...(lost?.length ? { lost } : {}) })\n }\n\n const targets = pageTargets(hub)\n for (const [, list] of targets) {\n const distinct = [...new Map(list.map((t) => [`${t.agentId}:${t.path}`, t])).values()]\n const title = distinct[0]?.article.meta.title\n if (distinct.length > 1 && title && !report.duplicates.some((d) => d.title === title)) {\n report.duplicates.push({ title, pages: distinct.map((t) => `${t.agentId}/${t.path}`) })\n }\n }\n\n // New pages: one per subject, however many agents proposed it. A page\n // that already exists (by title or alias) takes the facts instead.\n const newPages = new Map<string, NewPage>()\n for (const p of patches) {\n if (p.kind !== \"create\") continue\n const key = pageKey(p.page)\n if (targets.has(key)) continue\n const draft = newPages.get(key) ?? { title: p.page, owner: p.agentId, summaries: [], sources: [], aliases: [], at: p.checkedAt }\n draft.type ??= p.pageType\n if (p.summary && !draft.summaries.includes(p.summary)) draft.summaries.push(p.summary)\n if (!draft.sources.includes(p.source)) draft.sources.push(p.source)\n for (const a of p.aliases ?? []) if (!draft.aliases.includes(a)) draft.aliases.push(a)\n newPages.set(key, draft)\n }\n for (const p of patches) {\n const key = pageKey(p.page)\n if ((p.kind === \"add\" || p.kind === \"correct\") && !targets.has(key) && !newPages.has(key)) {\n // A fact about a subject with no page and no `create`: start one.\n newPages.set(key, { title: p.page, owner: p.agentId, summaries: [], sources: [p.source], aliases: [], at: p.checkedAt })\n }\n }\n\n // A new page whose title is a near match of an existing one is probably\n // that page under a longer or shorter name; creating it is how the\n // first trial duplicated a stale page instead of correcting it.\n const existing = [...targets.values()].map((list) => list[0])\n const duplicateOf = new Map<string, string>()\n for (const [key, draft] of newPages) {\n const match = possibleDuplicate(draft.title, draft.type, existing.map((t) => ({ title: t.article.meta.title, type: t.article.meta.type, ref: `${t.agentId}/${t.path}` })))\n if (match) duplicateOf.set(key, match)\n }\n for (const key of duplicateOf.keys()) newPages.delete(key)\n\n const ledger = new FactLedger(wikiDir)\n // Keyed by the page itself, not by the name a patch used: a title patch\n // and an alias patch to one page each started from the same stored\n // body, and the second write dropped the first one's lines.\n const edits = new Map<string, PageEdit[]>()\n const editTargets = new Map<string, PageTarget>()\n const editKey = (key: string) => {\n const t = targets.get(key)?.[0]\n if (!t) return `new:${key}`\n const k = `page:${t.agentId}:${t.path}`\n editTargets.set(k, t)\n return k\n }\n for (const p of patches) {\n const key = pageKey(p.page)\n const dup = duplicateOf.get(key)\n if (dup && p.kind !== \"remove\") { hold(p, `possible duplicate of ${dup}`); continue }\n if (p.kind === \"create\") continue\n if (p.kind === \"remove\") { hold(p, \"removes a fact\"); continue }\n const target = targets.get(key)?.[0]\n if (target && !target.store.canRead(target.article.meta, p.agentId)) {\n hold(p, \"the contributing agent cannot read this page\")\n continue\n }\n const subject = target?.article.meta.title ?? newPages.get(key)!.title\n let status = \"planned\"\n let value = p.value!\n if (!opts.dryRun) {\n const r = ledger.write({ subject, attribute: p.attribute!, value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n status = r.status\n if (r.status === \"contradiction\") {\n report.contradictions.push({ page: subject, attribute: p.attribute!, value, by: p.agentId, questionId: r.questionId })\n continue\n }\n if (r.status === \"unchanged\") continue\n value = r.fact.value\n }\n report.applied.push({ page: subject, attribute: p.attribute!, value, by: p.agentId, status })\n const list = edits.get(editKey(key)) ?? []\n const previous = p.kind === \"correct\" ? p.previous : undefined\n list.push({ line: { attribute: p.attribute!, value, source: p.source, checkedAt: p.checkedAt, by: p.agentId, previous }, previous, patch: p })\n edits.set(editKey(key), list)\n }\n\n const touched = new Set<WikiStore>()\n for (const [key, list] of edits) {\n const target = editTargets.get(key)\n if (!target) continue\n const r = updatePage(target, list, { guard: true, today, dryRun: opts.dryRun })\n if (r.lost) for (const e of list) hold(e.patch, \"the change would lose facts the page has\", r.lost)\n else if (r.denied) for (const e of list) hold(e.patch, `write denied for ${target.agentId}/${target.path}`)\n else if (r.changed) {\n report.pagesUpdated.push(`${target.agentId}/${target.path}`)\n if (!opts.dryRun) touched.add(target.store)\n }\n }\n\n for (const [key, draft] of newPages) {\n const list = edits.get(`new:${key}`) ?? []\n if (!draft.summaries.length && !list.length) continue\n const store = hub.getAgentWiki(draft.owner)\n const path = newPagePath(store, draft.title, draft.type)\n report.pagesCreated.push(`${draft.owner}/${path}`)\n if (opts.dryRun) continue\n if (createPage(store, path, draft, list.map((e) => e.line), today)) touched.add(store)\n }\n\n if (!opts.dryRun) {\n for (const store of touched) {\n try { store.rebuildIndex() } catch (err) { opts.log?.(`index rebuild failed: ${(err as Error).message}`) }\n }\n const dir = contributionsDir(wikiDir)\n if (held.length) {\n const known = listHeld(wikiDir, { all: true })\n writeJson(heldFile(wikiDir), [...known, ...held.filter((h) => !known.some((k) => k.id === h.id))])\n }\n mkdirSync(resolve(dir, \"merged\"), { recursive: true })\n for (const b of batches) renameSync(resolve(dir, \"pending\", `${b.id}.json`), resolve(dir, \"merged\", `${b.id}.json`))\n writeJson(resolve(dir, \"reports\", `${nowIso.replace(/[:.]/g, \"-\")}.json`), report)\n }\n return report\n}\n\nfunction createPage(store: WikiStore, path: string, draft: NewPage, lines: FactLine[], today: string): boolean {\n const intro = draft.summaries.length ? draft.summaries.join(\" \") : `${draft.title}.`\n const { body } = applyFactLines(`${intro}\\n\\n_Sources: ${draft.sources.join(\"; \")}._`, lines)\n return store.writeArticle(path, {\n title: draft.title,\n ...(draft.type ? { type: draft.type } : {}),\n ...(draft.aliases.length ? { aliases: draft.aliases } : {}),\n tags: [],\n owner: draft.owner,\n access: \"public\",\n created: today,\n lastUpdated: today,\n sources: [contributionStamp(draft.owner, draft.at), ...lines.map((l) => contributionStamp(l.by, l.checkedAt))]\n .filter((s, i, a) => a.indexOf(s) === i),\n }, body, draft.owner)\n}\n\nconst TITLE_STOPWORDS = new Set([\"the\", \"and\", \"for\", \"with\", \"von\", \"des\", \"les\", \"der\", \"die\", \"das\", \"une\", \"pour\", \"page\", \"of\", \"de\", \"la\", \"le\", \"du\", \"et\"])\n\nfunction titleTokens(title: string): Set<string> {\n return new Set((title.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? []).filter((t) => (t.length > 2 || /\\d/.test(t)) && !TITLE_STOPWORDS.has(t)))\n}\n\n/**\n * The existing page a new title most likely means, or undefined. A match\n * shares at least two significant words and most of the shorter title's\n * words (\"Tax Payment Plan\" and \"Tax Payment Plan Engagement 4471\"). A\n * person page never matches a page of another type, and titles carrying\n * different numbers never match.\n */\nexport function possibleDuplicate(\n title: string, type: WikiArticleType | undefined,\n pages: Array<{ title: string; type?: WikiArticleType; ref: string }>,\n): string | undefined {\n const mine = titleTokens(title)\n if (mine.size < 2) return undefined\n let best: { ref: string; title: string; score: number } | undefined\n for (const p of pages) {\n if (type && p.type && (type === \"person\") !== (p.type === \"person\")) continue\n const theirs = titleTokens(p.title)\n if (theirs.size < 2) continue\n // Two numbered things (invoices, issues) with different numbers are\n // different things, however alike the rest of the title.\n const nums = (set: Set<string>) => [...set].filter((t) => /\\d/.test(t))\n const [a, b] = [nums(mine), nums(theirs)]\n if (a.length && b.length && !a.some((n) => b.includes(n))) continue\n let shared = 0\n for (const t of mine) if (theirs.has(t)) shared++\n const score = shared / Math.min(mine.size, theirs.size)\n if (shared >= 2 && score >= 0.75 && (!best || score > best.score)) best = { ref: p.ref, title: p.title, score }\n }\n return best ? `\"${best.title}\" (${best.ref})` : undefined\n}\n\ninterface NewPage {\n title: string\n type?: WikiArticleType\n owner: string\n summaries: string[]\n sources: string[]\n aliases: string[]\n /** Earliest check behind it. */\n at: string\n}\n\ninterface PageEdit {\n line: FactLine\n /** For a correction the ledger accepted: the exact wrong text to replace in place. */\n previous?: string\n patch: ContributionPatch\n}\n\n/**\n * Write a page's fact lines and in-place corrections. With `guard`, an\n * edit that would lose a structured fact is not written and the lost\n * facts are returned.\n */\nfunction updatePage(\n target: PageTarget, list: PageEdit[],\n opts: { guard: boolean; today: string; dryRun?: boolean; remove?: { attribute?: string; text?: string } },\n): { changed: boolean; lost?: string[]; denied?: boolean } {\n const before = target.article.content\n let { body, superseded } = applyFactLines(before, list.map((e) => e.line))\n for (const e of list) {\n if (!e.previous || e.previous === e.line.value) continue\n const fixed = replaceOnce(body, e.previous, e.line.value)\n if (fixed !== body) { body = fixed; superseded.push(e.previous) }\n }\n if (opts.remove) body = removeFact(body, opts.remove)\n if (body === before) return { changed: false }\n if (opts.guard) {\n const lost = lostStructuredFacts(before, body, superseded)\n if (lost.length) return { changed: false, lost }\n }\n if (opts.dryRun) return { changed: true }\n const meta = target.article.meta\n const stamps = list.map((e) => contributionStamp(e.line.by, e.line.checkedAt))\n const ok = target.store.writeArticle(target.path, {\n ...meta,\n lastUpdated: opts.today,\n sources: [...meta.sources, ...stamps].filter((s, i, a) => a.indexOf(s) === i),\n }, body, meta.owner)\n return ok ? { changed: true } : { changed: false, denied: true }\n}\n\n/** Replace `old` with `next` when it occurs exactly once, as whole words,\n * outside the \"Checked facts\" section; anything else is ambiguous and\n * left alone. Whole words, so \"paid\" is not rewritten inside \"unpaid\". */\nexport function replaceOnce(body: string, old: string, next: string): string {\n if (!old) return body\n const at = body.indexOf(FACTS_HEADING)\n const prose = at === -1 ? body : body.slice(0, at)\n const escaped = old.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n const hits = [...prose.matchAll(new RegExp(`(?<![\\\\p{L}\\\\p{N}])${escaped}(?![\\\\p{L}\\\\p{N}])`, \"gu\"))]\n if (hits.length !== 1) return body\n const first = hits[0].index!\n return body.slice(0, first) + next + body.slice(first + old.length)\n}\n\nfunction removeFact(body: string, remove: { attribute?: string; text?: string }): string {\n let out = body\n if (remove.attribute) {\n const attr = remove.attribute.toLowerCase()\n out = out.split(\"\\n\").filter((l) => l.match(LINE_RE)?.[1].toLowerCase() !== attr).join(\"\\n\")\n }\n if (remove.text) out = replaceOnce(out, remove.text, \"\")\n return out\n}\n\n// --- Held patches: a person decides ----------------------------------------\n\nexport type HeldDecision = { ok: true; held: HeldPatch; page?: string } | { ok: false; error: string }\n\n/**\n * Apply a held patch as it is, without the fact-loss guard: a person\n * looked at it. A removal deletes the attribute's fact line and the\n * exact text it names; the page's previous body stays in `_versions/`.\n */\nexport function approveHeld(hub: WikiHub, wikiDir: string, id: string, opts: { by?: string; now?: number } = {}): HeldDecision {\n const all = listHeld(wikiDir, { all: true })\n const h = all.find((x) => x.id === id)\n if (!h) return { ok: false, error: `no held patch \"${id}\"` }\n if (h.status !== \"held\") return { ok: false, error: `\"${id}\" is already ${h.status}` }\n const p = h.patch\n const now = opts.now ?? Date.now()\n const today = new Date(now).toISOString().slice(0, 10)\n const target = pageTargets(hub).get(pageKey(p.page))?.[0]\n if (!target) {\n // A held `create` (a possible duplicate), or a fact for the page it\n // would have made: a person said it is a new subject after all.\n if (p.kind === \"remove\") return { ok: false, error: `no page \"${p.page}\" (it may have been renamed)` }\n const lines: FactLine[] = []\n if (p.attribute && p.value) {\n const w = new FactLedger(wikiDir).write({ subject: p.page, attribute: p.attribute, value: p.value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n if (w.status === \"contradiction\") return { ok: false, error: `the wiki has a newer check of ${p.attribute}; answer question ${w.questionId ?? \"(see wiki questions)\"} instead` }\n lines.push({ attribute: p.attribute, value: w.fact.value, source: p.source, checkedAt: p.checkedAt, by: p.agentId })\n }\n const store = hub.getAgentWiki(p.agentId)\n const path = newPagePath(store, p.page, p.pageType)\n const draft: NewPage = { title: p.page, type: p.pageType, owner: p.agentId, summaries: p.summary ? [p.summary] : [], sources: [p.source], aliases: p.aliases ?? [], at: p.checkedAt }\n if (!createPage(store, path, draft, lines, today)) return { ok: false, error: `write denied for ${p.agentId}/${path}` }\n try { store.rebuildIndex() } catch { /* the page is written; the next rebuild indexes it */ }\n return decide(wikiDir, all, h, \"approved\", opts.by, now, `${p.agentId}/${path}`)\n }\n\n let r: { changed: boolean; denied?: boolean }\n if (p.kind === \"remove\") {\n r = updatePage(target, [], { guard: false, today, remove: { attribute: p.attribute, text: p.previous } })\n } else {\n if (!p.attribute || !p.value) return { ok: false, error: `\"${id}\" carries no fact to apply` }\n const w = new FactLedger(wikiDir).write({ subject: target.article.meta.title, attribute: p.attribute, value: p.value, source: p.source, verifiedBy: p.agentId, verifiedAt: p.checkedAt }, { now })\n if (w.status === \"contradiction\") return { ok: false, error: `the wiki has a newer check of ${p.attribute}; answer question ${w.questionId ?? \"(see wiki questions)\"} instead` }\n const previous = p.kind === \"correct\" ? p.previous : undefined\n r = updatePage(target, [{ line: { attribute: p.attribute, value: w.fact.value, source: p.source, checkedAt: p.checkedAt, by: p.agentId, previous }, previous, patch: p }], { guard: false, today })\n }\n if (r.denied) return { ok: false, error: `write denied for ${target.agentId}/${target.path}` }\n if (r.changed) {\n try { target.store.rebuildIndex() } catch { /* the page is written; the next rebuild indexes it */ }\n }\n return decide(wikiDir, all, h, \"approved\", opts.by, now, `${target.agentId}/${target.path}`)\n}\n\nexport function rejectHeld(wikiDir: string, id: string, opts: { by?: string; now?: number } = {}): HeldDecision {\n const all = listHeld(wikiDir, { all: true })\n const h = all.find((x) => x.id === id)\n if (!h) return { ok: false, error: `no held patch \"${id}\"` }\n if (h.status !== \"held\") return { ok: false, error: `\"${id}\" is already ${h.status}` }\n return decide(wikiDir, all, h, \"rejected\", opts.by, opts.now ?? Date.now())\n}\n\nfunction decide(wikiDir: string, all: HeldPatch[], h: HeldPatch, status: \"approved\" | \"rejected\", by: string | undefined, now: number, page?: string): HeldDecision {\n const decided: HeldPatch = { ...h, status, decidedBy: by ?? \"operator\", decidedAt: new Date(now).toISOString() }\n writeJson(heldFile(wikiDir), all.map((x) => (x.id === h.id ? decided : x)))\n return { ok: true, held: decided, ...(page ? { page } : {}) }\n}\n\n// --- Page text -----------------------------------------------------------------\n\nexport interface FactLine {\n attribute: string\n value: string\n source: string\n checkedAt: string\n by: string\n previous?: string\n}\n\nconst LINE_RE = /^- \\*\\*(.+?):\\*\\* /\n\n/**\n * Add or update one line per attribute in the page's \"Checked facts\"\n * section. Nothing outside that section changes. A changed value keeps\n * the old one on its line as \"previously\", so a correction never drops a\n * fact from the page.\n *\n * `superseded` holds the replaced lines: their older parts live on in the\n * ledger's history and the page's versions, so the guard lets them go.\n */\nexport function applyFactLines(body: string, lines: FactLine[]): { body: string; superseded: string[] } {\n if (lines.length === 0) return { body, superseded: [] }\n const all = body.replace(/\\s+$/, \"\").split(\"\\n\")\n const start = all.findIndex((l) => l.trim() === FACTS_HEADING)\n let head = all\n let section: string[] = []\n let tail: string[] = []\n if (start !== -1) {\n head = all.slice(0, start)\n const rest = all.slice(start + 1)\n const end = rest.findIndex((l) => /^#{1,2} /.test(l))\n section = (end === -1 ? rest : rest.slice(0, end)).filter((l) => l.trim())\n tail = end === -1 ? [] : rest.slice(end)\n }\n\n const superseded: string[] = []\n for (const l of lines) {\n const at = section.findIndex((s) => s.match(LINE_RE)?.[1].toLowerCase() === l.attribute.toLowerCase())\n const old = at === -1 ? undefined : parseFactLine(section[at])\n if (at !== -1) superseded.push(section[at])\n // A re-check of the same value refreshes the line and keeps its history.\n const previous = old && old.value === l.value ? old.previous : old ? `${old.value}, checked ${old.checkedAt}` : l.previous\n // An existing line keeps its spelling of the attribute.\n const attribute = section[at]?.match(LINE_RE)?.[1] ?? l.attribute\n const line = renderFactLine({ ...l, attribute, previous })\n if (at === -1) section.push(line)\n else section[at] = line\n }\n\n const out = [...(head.some((l) => l.trim()) ? [...head, \"\"] : []), FACTS_HEADING, \"\", ...section]\n if (tail.length) out.push(\"\", ...tail)\n return { body: out.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trim(), superseded }\n}\n\nfunction renderFactLine(l: FactLine): string {\n const prev = l.previous ? ` (previously: ${l.previous})` : \"\"\n return `- **${l.attribute}:** ${l.value} — ${l.source}; checked ${l.checkedAt.slice(0, 10)} by ${l.by}${prev}`\n}\n\nfunction parseFactLine(line: string): { value: string; checkedAt: string; previous?: string } | undefined {\n const m = line.match(/^- \\*\\*.+?:\\*\\* (.*?) — .*?; checked (\\S+) by \\S+(?: \\(previously: (.*)\\))?$/)\n return m ? { value: m[1], checkedAt: m[2], ...(m[3] ? { previous: m[3] } : {}) } : undefined\n}\n\nfunction contributionStamp(agentId: string, at: string): string {\n return `contribution:${agentId}@${at.slice(0, 10)}`\n}\n\nconst TYPE_FOLDER: Record<WikiArticleType, string> = {\n person: \"people\", project: \"projects\", place: \"places\", concept: \"concepts\",\n event: \"events\", decision: \"decisions\", pattern: \"patterns\",\n}\n\nfunction newPagePath(store: WikiStore, title: string, type?: WikiArticleType): string {\n const slug = title.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, \"-\").replace(/^-+|-+$/g, \"\").slice(0, 60) || \"page\"\n const folder = type ? TYPE_FOLDER[type] : \"contributions\"\n let path = `${folder}/${slug}.md`\n for (let n = 2; store.readArticle(path); n++) path = `${folder}/${slug}-${n}.md`\n return path\n}\n"],"mappings":"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","names":["createHash","existsSync","mkdirSync","readdirSync","readFileSync","renameSync","writeFileSync","resolve","DEFAULT_CONTRIBUTION_LIMITS","ITEMS_PER_CALL","ITEM_CHARS","PAGE_CHARS","PAGES_PER_CALL","FIELD_CHARS","STEPS_PER_TRACE","FACTS_HEADING","contributionsDir","wikiDir","resolve","readJson","file","fallback","existsSync","readFileSync","err","writeJson","data","mkdirSync","tmp","writeFileSync","renameSync","readState","listPendingBatches","dir","readdirSync","f","b","heldFile","listHeld","opts","list","h","latestReport","last","pendingWork","hub","agentId","state","now","since","sinceDay","done","items","e","sinceMs","t","listTraces","tools","getTrace","s","clip","text","a","saveCursor","read","unread","prev","lastRunAt","processed","w","runContribution","limits","all","pages","readablePages","batch","seen","chunk","prompt","buildContributionPrompt","relevantPages","reply","p","parseContributionPatches","out","add","store","skip","byTitle","scoreAll","buildIndex","byBody","picked","half","r","i","maxPatches","work","wiki","raw","match","parsed","x","kind","page","clean","rawSource","source","checked","attribute","value","previous","summary","aliases","checkedAt","body","createHash","isWikiArticleType","v","max","pageKey","title","pageTargets","targets","id","article","keys","k","mergeContributions","nowIso","today","batches","patches","report","held","hold","patch","reason","lost","distinct","d","newPages","key","draft","existing","duplicateOf","possibleDuplicate","ledger","FactLedger","edits","editTargets","editKey","dup","target","subject","status","touched","updatePage","path","newPagePath","createPage","known","lines","intro","applyFactLines","contributionStamp","l","TITLE_STOPWORDS","titleTokens","type","mine","best","theirs","nums","set","n","shared","score","before","superseded","fixed","replaceOnce","removeFact","lostStructuredFacts","meta","stamps","old","next","at","prose","escaped","hits","first","remove","attr","LINE_RE","approveHeld","decide","rejectHeld","by","decided","start","head","section","tail","rest","end","parseFactLine","line","renderFactLine","m","TYPE_FOLDER","slug","folder"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{b as a,c as b,d as c,e as d,f as e}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=doctor-
|
|
1
|
+
import{b as a,c as b,d as c,e as d,f as e}from"./chunk-M5AHI2PZ.js";import"./chunk-S2GAEH2F.js";import"./chunk-JXF54PT7.js";import"./chunk-54OORW5I.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{e as daemonVoiceCheck,b as doctor,a as runDoctorChecks,c as runNotificationChecks,d as runReminderChecks};
|
|
2
|
+
//# sourceMappingURL=doctor-ZOXHT7ZQ.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q}from"./chunk-U6EJ53DA.js";import"./chunk-H4NSB54D.js";import"./chunk-MTX4UPNB.js";import"./chunk-QAWKN2N4.js";import"./chunk-IMLAPB7G.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import"./chunk-QIJLFPWE.js";export{a as ENRICH_BY,b as ENRICH_TYPES,h as buildEnrichPrompt,j as checkEnrichment,n as createEntityPage,e as enrichContext,g as fingerprint,c as lensProperties,o as loadEnrichState,f as mentionsOf,l as mergedMeta,i as parseEnrichReply,d as readableAlongside,q as runEnrich,p as saveEnrichState,m as targetPage,k as withOverview};
|
|
2
|
+
//# sourceMappingURL=enrich-R2LIDLPZ.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as A,k as R}from"./chunk-H4NSB54D.js";import"./chunk-MTX4UPNB.js";import{f as g}from"./chunk-QAWKN2N4.js";import"./chunk-IMLAPB7G.js";import{c as I}from"./chunk-OWNQ2FD4.js";import{a as E}from"./chunk-ROLSSYXE.js";import"./chunk-QIJLFPWE.js";var b="wiki-events",x="importance_set",S=new Set(["event","due_date","topic"]),L=10,j=320;function _(t,e,c){let o=new Set(c.map(r=>r.toLowerCase()));for(let r of t??[])if(!(!E.includes(r.level)||!r.title&&!r.tags?.length)){if(r.title){let i;try{i=new RegExp(r.title,"i")}catch{continue}if(!i.test(e))continue}if(r.unless){let i;try{i=new RegExp(r.unless,"i")}catch{continue}if(i.test(e))continue}if(!(r.tags?.length&&!r.tags.some(i=>o.has(i.toLowerCase()))))return r.level}}function O(t,e){let c=` ${g(e)} `,o=[];for(let r of t.entities.values()){if(S.has(r.type))continue;let i=g(r.title);i.length>=4&&c.includes(` ${i} `)&&o.push(r)}return o}function C(t,e){let c=A(t,e,null).filter(r=>!S.has(r.type)),o=O(t,e.title);return[...new Map([...o,...c].map(r=>[r.id,r])).values()].slice(0,L)}function W(t,e){return e.pages.find(c=>!t.syncedFrom(c.agentId))}function $(t){return(t.statements??[]).some(e=>e.by===b&&e.property===x)}function G(t){return t.pages.some(e=>e.article.meta.importance&&!$(e.article.meta))}function U(t,e,c){let o=new Set;for(let s of c.about){let l=e.names.get(g(s))??(e.entities.has(s)?s:void 0);l&&o.add(l)}let r=[],i=[],a=[...e.entities.values()].filter(s=>s.type==="event").sort((s,l)=>(l.date||"").localeCompare(s.date||""));for(let s of a){if(s.pages.some(n=>n.article.meta.importance)&&(!c.force||G(s)))continue;let f=C(e,s);if(c.about.length&&!f.some(n=>o.has(n.id)))continue;let d=W(t,s);if(!d){i.push(s);continue}r.push({event:s,page:d,candidates:f})}return{items:r,noPage:i}}var M=(t,e)=>t.length>e?`${t.slice(0,e)}\u2026`:t;function V(t,e){let c=["You are sorting the event pages of a company wiki by importance, and saying what each event is about.","","Levels:","- minor: routine upkeep or a small incident with no lasting effect (a disk filled and was cleaned, a job was restarted, a reminder was sent).","- normal: something a person would want in the history of the thing it is about (a delivery, a payment, an outage that was noticed, a meeting with an outcome).","- major: a turning point (a client won or lost, a contract signed, a legal or financial deadline missed, data lost, a decision that changes how things are done).","When unsure between two levels, pick the lower one.","","## Events"];return t.forEach((o,r)=>{let i=M(R(o.page.article.content).replace(/\s+/g," ").trim(),j);c.push(`### ${r+1}. ${o.event.title} (${o.event.date||"no date"})`,i||"(no text)"),c.push(o.candidates.length?`May be about: ${o.candidates.map(a=>`"${a.title}" (${a.type})`).join(", ")}`:"May be about: nothing listed","")}),c.push("## Task","Return one JSON object and nothing else:",'{"events": [{"n": 1, "importance": "minor", "about": ["Exact Title"], "why": "one short reason"}]}',"","Rules:",`- One item per event, with its number. importance is one of ${E.join(", ")}.`,`- about: only titles from that event's own "May be about" list, copied exactly, and only the ones the event really concerns: the machine that failed, the client it was for, the person it happened to. Often one, at most three. Leave it empty when none fits.`,"- why: under 15 words, in English.",...e.importance.major_set_by==="owner"?["- major is only a suggestion here: the owner confirms it."]:[]),c.join(`
|
|
2
|
+
`)}function N(t){let e=t.match(/```(?:json)?\s*\n([\s\S]*?)\n```/),c=e?e[1]:t.slice(t.indexOf("{"),t.lastIndexOf("}")+1);try{let o=JSON.parse(c);return o&&typeof o=="object"&&!Array.isArray(o)?o:null}catch{return null}}function P(t,e){return t==="major"&&e.importance.major_set_by==="owner"?{importance:"normal",proposed:"major"}:{importance:t}}function T(t,e,c){let o=new Map,r=N(t);for(let i of Array.isArray(r?.events)?r.events:[]){let a=i??{},s=Number(a.n)-1,l=e[s];if(!Number.isInteger(s)||!l||o.has(s))continue;let f=String(a.importance??"").trim().toLowerCase();if(!E.includes(f))continue;let d=[],n=new Map(l.candidates.map(u=>[g(u.title),u.title])),p=[];for(let u of Array.isArray(a.about)?a.about:[]){let m=n.get(g(String(u??"")));m&&!p.includes(m)?p.push(m):!m&&String(u??"").trim()&&d.push(`about ${String(u).trim().slice(0,80)}: not in the list shown`)}p.length>3&&d.push(`about: kept the first 3 of ${p.length}`);let h=typeof a.why=="string"?M(a.why.trim(),160):void 0;o.set(s,{verdict:{...P(f,c),about:p.slice(0,3),why:h||void 0,by:"model"},dropped:d})}return o}function B(t,e,c){let o=(t.statements??[]).filter(a=>a.by!==b),r=new Set(o.filter(a=>a.property==="involves").map(a=>g(a.value))),i=e.about.filter(a=>!r.has(g(a))).map(a=>({property:"involves",value:a,checked_at:c,by:b}));return i.push({property:x,value:e.proposed??e.importance,checked_at:c,by:b,...e.why?{note:e.why}:{}}),{...t,importance:e.importance,importanceProposed:e.proposed,statements:[...o,...i]}}async function K(t,e,c,o){let r=e.ontology,{items:i,noPage:a}=U(t,e,o),s=i.slice(0,o.max),l={outcomes:[],costUsd:0,calls:0,capped:!1,left:i.length-s.length};for(let n of o.about.length?a:[])l.outcomes.push({event:n.id,title:n.title,date:n.date,status:"no-page",about:[],dropped:["its pages are copied from another node"]});let f=(n,p,h)=>{let u=`${n.page.agentId}/${n.page.article.path}`,m={event:n.event.id,title:n.event.title,date:n.event.date,page:u,status:"dry-run",importance:p.importance,proposed:p.proposed,about:p.about,by:p.by,why:p.why,dropped:h};if(o.dryRun){l.outcomes.push(m);return}let v=t.getAgentWiki(n.page.agentId),k=n.page.article.path,w;try{w=v.withArticleLock(k,()=>{let y=v.readArticle(k);return y?y.meta.importance&&!$(y.meta)?"a level was set on the page during the run":v.writeArticle(k,B(y.meta,p,o.today),y.content,y.meta.owner||n.page.agentId)?void 0:"write refused":"the page was moved or removed during the run"})}catch(y){if(!(y instanceof I))throw y;w="the page was busy; run again"}l.outcomes.push(w?{...m,status:"failed",dropped:[...h,w]}:{...m,status:"written"})},d=[];for(let n of s){let p=_(r.importance.rules,n.event.title,n.page.article.meta.tags??[]);if(!p){d.push(n);continue}let h=new Set(O(e,n.event.title).map(m=>m.id)),u=n.candidates.filter(m=>h.has(m.id)).slice(0,3).map(m=>m.title);f(n,{...P(p,r),about:u,why:"matched an importance rule",by:"rule"},[])}if(o.rulesOnly)return l.left+=d.length,l;for(let n=0;n<d.length;n+=o.batch){let p=d.slice(n,n+o.batch);if(l.costUsd>=o.maxCostUsd){l.capped=!0,l.left+=d.length-n;break}l.calls++;let h;try{let u=await c(V(p,r));l.costUsd+=u.costUsd,h=T(u.text,p,r)}catch(u){for(let m of p)l.outcomes.push({event:m.event.id,title:m.event.title,date:m.event.date,page:`${m.page.agentId}/${m.page.article.path}`,status:"failed",about:[],dropped:[u.message.slice(0,200)]});continue}p.forEach((u,m)=>{let v=h.get(m);v?f(u,v.verdict,v.dropped):l.outcomes.push({event:u.event.id,title:u.event.title,date:u.event.date,page:`${u.page.agentId}/${u.page.article.path}`,status:"no-answer",about:[],dropped:["the reply had no usable item for this event"]})})}if(!o.dryRun)for(let n of new Set(l.outcomes.filter(p=>p.status==="written").map(p=>p.page.split("/")[0])))t.getAgentWiki(n).rebuildIndex();return l}function z(t,e,c,o){let r=e.names.get(g(c))??(e.entities.has(c)?c:void 0),i=r?e.entities.get(r):void 0;if(!i)return{ok:!1,reason:`no page is titled "${c}"`};if(i.type!=="event")return{ok:!1,title:i.title,reason:`"${i.title}" is a ${i.type}, not an event`};let a=W(t,i);if(!a)return{ok:!1,title:i.title,reason:"its pages are copied from another node; set the level there"};let s=t.getAgentWiki(a.agentId),l,f="write refused";try{l=s.withArticleLock(a.article.path,()=>{let d=s.readArticle(a.article.path)??a.article,n=(d.meta.statements??[]).filter(h=>!(h.by===b&&h.property===x)),p={...d.meta,importance:o,importanceProposed:void 0,statements:n.length?n:void 0};return s.writeArticle(a.article.path,p,d.content,d.meta.owner||a.agentId)})}catch(d){if(!(d instanceof I))throw d;l=!1,f="the page was busy; run again"}return l&&s.rebuildIndex(),{ok:l,title:i.title,page:`${a.agentId}/${a.article.path}`,reason:l?void 0:f}}function X(t,e,c){let o=[],r=new Map(e.outcomes.filter(i=>i.importance).map(i=>[i.event,i]));for(let i of c){let a=t.names.get(g(i))??(t.entities.has(i)?i:void 0),s=a?t.entities.get(a):void 0;if(!s)continue;let l=new Set(A(t,s,new Set(["event"])).map(n=>n.id)),f={minor:0,normal:0,major:0},d=new Set;for(let n of t.entities.values()){if(n.type!=="event")continue;let p=r.get(n.id);!(l.has(n.id)||p?.about.some(u=>g(u)===g(s.title)))||d.has(n.id)||(d.add(n.id),f[p?.importance??n.importance]++)}o.push({title:s.title,type:s.type,before:l.size,after:f})}return o}export{b as EVENTS_BY,V as buildEventsPrompt,T as checkEventsReply,C as eventCandidates,B as eventMeta,U as pickEvents,_ as ruleLevel,K as runEvents,z as setEventLevel,X as summariseAbout};
|
|
3
|
+
//# sourceMappingURL=event-levels-WOYYEWSZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wiki/event-levels.ts"],"sourcesContent":["// --- Give each event an importance level and the pages it is about (#811) ---\n//\n// Event pages are half the wiki, and until a level is set they all show\n// as `normal` beside decisions and client events. This pass reads the\n// event pages (never the raw entries) and writes, per event:\n// - `importance`: minor, normal or major;\n// - `involves` statements: the people, organisations, assets or\n// projects the event is about, so it shows in their History.\n// The ontology's `importance.rules` decide first, for free. What they\n// leave is sent to a model in batches. Each answer is checked against\n// what the call was shown before a page is written through the store,\n// which keeps the old version. Where only the owner may set `major`, a\n// suggested `major` is stored as a proposal and the event stays `normal`.\n\nimport type { WikiHub } from \"./hub\"\nimport type { WikiArticleMeta } from \"./types\"\nimport { LockBusyError } from \"./facts/ledger-file\"\nimport { normName, type Entity, type GraphPage, type WikiGraph } from \"./ontology/graph\"\nimport { linkedEntities } from \"./ontology/lens\"\nimport { IMPORTANCE_LEVELS, type Importance, type ImportanceRule, type Ontology, type WikiStatement } from \"./ontology/types\"\nimport { bodyOf } from \"./ontology/view-entity\"\n\nexport const EVENTS_BY = \"wiki-events\"\n/** Statement that records this job set the level; the owner's `set` removes it. */\nconst LEVEL_MARK = \"importance_set\"\n\n/** Types an event can be about. Events, due dates and topics are not. */\nconst ABOUT_SKIP = new Set([\"event\", \"due_date\", \"topic\"])\nconst MAX_CANDIDATES = 10\nconst BODY_CHARS = 320\n\nexport interface EventItem {\n event: Entity\n /** The page the result is written to: one this node owns. */\n page: GraphPage\n /** Entities the event may be about: linked to it, or named in its title. */\n candidates: Entity[]\n}\n\nexport interface EventVerdict {\n importance: Importance\n /** Set when `major` was suggested but only the owner may set it. */\n proposed?: Importance\n /** Titles of the candidates the event is about. */\n about: string[]\n why?: string\n by: \"rule\" | \"model\"\n}\n\nexport interface EventOutcome {\n event: string\n title: string\n date: string\n page?: string\n status: \"written\" | \"dry-run\" | \"no-page\" | \"no-answer\" | \"failed\"\n importance?: Importance\n proposed?: Importance\n about: string[]\n by?: \"rule\" | \"model\"\n why?: string\n dropped: string[]\n}\n\nexport interface EventsRun {\n outcomes: EventOutcome[]\n costUsd: number\n calls: number\n /** Set when the run stopped at its spending cap. */\n capped: boolean\n /** Events without a level that this run did not reach. */\n left: number\n}\n\nexport interface EventsCall {\n (prompt: string): Promise<{ text: string; costUsd: number }>\n}\n\nexport interface EventsOptions {\n /** Entity ids or titles: only events linked to or naming them. */\n about: string[]\n /** Most events per run. */\n max: number\n /** Events per model call. */\n batch: number\n maxCostUsd: number\n dryRun: boolean\n /** Redo events that already have a level set by this job. */\n force: boolean\n /** Skip the model: only the ontology's rules decide. */\n rulesOnly: boolean\n today: string\n}\n\n/** The first rule that matches the event, if any. */\nexport function ruleLevel(rules: ImportanceRule[] | undefined, title: string, tags: string[]): Importance | undefined {\n const have = new Set(tags.map(t => t.toLowerCase()))\n for (const r of rules ?? []) {\n if (!IMPORTANCE_LEVELS.includes(r.level) || (!r.title && !r.tags?.length)) continue\n if (r.title) {\n let re: RegExp\n try { re = new RegExp(r.title, \"i\") } catch { continue } // reported by checkOntology\n if (!re.test(title)) continue\n }\n if (r.unless) {\n let re: RegExp\n try { re = new RegExp(r.unless, \"i\") } catch { continue } // reported by checkOntology\n if (re.test(title)) continue\n }\n if (r.tags?.length && !r.tags.some(t => have.has(t.toLowerCase()))) continue\n return r.level\n }\n return undefined\n}\n\n/** Entities whose name appears as whole words in `text`. */\nfunction namedEntities(g: WikiGraph, text: string): Entity[] {\n const hay = ` ${normName(text)} `\n const out: Entity[] = []\n for (const e of g.entities.values()) {\n if (ABOUT_SKIP.has(e.type)) continue\n const name = normName(e.title)\n if (name.length >= 4 && hay.includes(` ${name} `)) out.push(e)\n }\n return out\n}\n\n/** What the event may be about: pages it links to or that link to it,\n * then pages its title names. Linked ones first. */\nexport function eventCandidates(g: WikiGraph, ev: Entity): Entity[] {\n const linked = linkedEntities(g, ev, null).filter(x => !ABOUT_SKIP.has(x.type))\n const named = namedEntities(g, ev.title)\n return [...new Map([...named, ...linked].map(x => [x.id, x])).values()].slice(0, MAX_CANDIDATES)\n}\n\nfunction localPage(hub: Pick<WikiHub, \"syncedFrom\">, e: Entity): GraphPage | undefined {\n return e.pages.find(p => !hub.syncedFrom(p.agentId))\n}\n\n/** True when this job set the page's level. */\nfunction ownLevel(meta: WikiArticleMeta): boolean {\n return (meta.statements ?? []).some(s => s.by === EVENTS_BY && s.property === LEVEL_MARK)\n}\n\n/** True when the level on the event was set by a person or another job. */\nfunction setByOthers(ev: Entity): boolean {\n return ev.pages.some(p => p.article.meta.importance && !ownLevel(p.article.meta))\n}\n\n/** Events this run should look at, newest first. */\nexport function pickEvents(hub: Pick<WikiHub, \"syncedFrom\">, g: WikiGraph, opts: Pick<EventsOptions, \"about\" | \"force\">): { items: EventItem[]; noPage: Entity[] } {\n const scope = new Set<string>()\n for (const name of opts.about) {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n if (id) scope.add(id)\n }\n const items: EventItem[] = []\n const noPage: Entity[] = []\n const events = [...g.entities.values()].filter(e => e.type === \"event\").sort((a, b) => (b.date || \"\").localeCompare(a.date || \"\"))\n for (const ev of events) {\n const hasLevel = ev.pages.some(p => p.article.meta.importance)\n // A level a person set is never redone; --force redoes only this job's.\n if (hasLevel && (!opts.force || setByOthers(ev))) continue\n const candidates = eventCandidates(g, ev)\n if (opts.about.length && !candidates.some(c => scope.has(c.id))) continue\n const page = localPage(hub, ev)\n if (!page) { noPage.push(ev); continue }\n items.push({ event: ev, page, candidates })\n }\n return { items, noPage }\n}\n\nconst clip = (s: string, n: number) => (s.length > n ? `${s.slice(0, n)}…` : s)\n\nexport function buildEventsPrompt(items: EventItem[], o: Ontology): string {\n const lines: string[] = [\n \"You are sorting the event pages of a company wiki by importance, and saying what each event is about.\",\n \"\",\n \"Levels:\",\n \"- minor: routine upkeep or a small incident with no lasting effect (a disk filled and was cleaned, a job was restarted, a reminder was sent).\",\n \"- normal: something a person would want in the history of the thing it is about (a delivery, a payment, an outage that was noticed, a meeting with an outcome).\",\n \"- major: a turning point (a client won or lost, a contract signed, a legal or financial deadline missed, data lost, a decision that changes how things are done).\",\n \"When unsure between two levels, pick the lower one.\",\n \"\",\n \"## Events\",\n ]\n items.forEach((it, i) => {\n const body = clip(bodyOf(it.page.article.content).replace(/\\s+/g, \" \").trim(), BODY_CHARS)\n lines.push(`### ${i + 1}. ${it.event.title} (${it.event.date || \"no date\"})`, body || \"(no text)\")\n lines.push(it.candidates.length ? `May be about: ${it.candidates.map(c => `\"${c.title}\" (${c.type})`).join(\", \")}` : \"May be about: nothing listed\", \"\")\n })\n lines.push(\n \"## Task\",\n \"Return one JSON object and nothing else:\",\n `{\"events\": [{\"n\": 1, \"importance\": \"minor\", \"about\": [\"Exact Title\"], \"why\": \"one short reason\"}]}`,\n \"\",\n \"Rules:\",\n `- One item per event, with its number. importance is one of ${IMPORTANCE_LEVELS.join(\", \")}.`,\n \"- about: only titles from that event's own \\\"May be about\\\" list, copied exactly, and only the ones the event really concerns: the machine that failed, the client it was for, the person it happened to. Often one, at most three. Leave it empty when none fits.\",\n \"- why: under 15 words, in English.\",\n ...(o.importance.major_set_by === \"owner\" ? [\"- major is only a suggestion here: the owner confirms it.\"] : []),\n )\n return lines.join(\"\\n\")\n}\n\n/** The JSON object in the reply, fenced or not. */\nfunction parseReply(text: string): Record<string, unknown> | null {\n const fenced = text.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/)\n const raw = fenced ? fenced[1] : text.slice(text.indexOf(\"{\"), text.lastIndexOf(\"}\") + 1)\n try {\n const v = JSON.parse(raw)\n return v && typeof v === \"object\" && !Array.isArray(v) ? v as Record<string, unknown> : null\n } catch {\n return null\n }\n}\n\n/** Keep `major` for the owner where the ontology says so. */\nfunction withOwnerRule(level: Importance, o: Ontology): Pick<EventVerdict, \"importance\" | \"proposed\"> {\n if (level === \"major\" && o.importance.major_set_by === \"owner\") return { importance: \"normal\", proposed: \"major\" }\n return { importance: level }\n}\n\n/** Per-event verdicts from one reply, keeping only what the call was shown. */\nexport function checkEventsReply(text: string, items: EventItem[], o: Ontology): Map<number, { verdict: EventVerdict; dropped: string[] }> {\n const out = new Map<number, { verdict: EventVerdict; dropped: string[] }>()\n const parsed = parseReply(text)\n for (const raw of Array.isArray(parsed?.events) ? parsed!.events as unknown[] : []) {\n const r = (raw ?? {}) as Record<string, unknown>\n const at = Number(r.n) - 1\n const it = items[at]\n if (!Number.isInteger(at) || !it || out.has(at)) continue\n const level = String(r.importance ?? \"\").trim().toLowerCase() as Importance\n if (!IMPORTANCE_LEVELS.includes(level)) continue\n const dropped: string[] = []\n const allowed = new Map(it.candidates.map(c => [normName(c.title), c.title]))\n const about: string[] = []\n for (const t of Array.isArray(r.about) ? r.about : []) {\n const title = allowed.get(normName(String(t ?? \"\")))\n if (title && !about.includes(title)) about.push(title)\n else if (!title && String(t ?? \"\").trim()) dropped.push(`about ${String(t).trim().slice(0, 80)}: not in the list shown`)\n }\n if (about.length > 3) dropped.push(`about: kept the first 3 of ${about.length}`)\n const why = typeof r.why === \"string\" ? clip(r.why.trim(), 160) : undefined\n out.set(at, { verdict: { ...withOwnerRule(level, o), about: about.slice(0, 3), why: why || undefined, by: \"model\" }, dropped })\n }\n return out\n}\n\n/** Page meta with the level and this job's `involves` facts replaced. */\nexport function eventMeta(meta: WikiArticleMeta, v: EventVerdict, today: string): WikiArticleMeta {\n const kept = (meta.statements ?? []).filter(s => s.by !== EVENTS_BY)\n const taken = new Set(kept.filter(s => s.property === \"involves\").map(s => normName(s.value)))\n const added: WikiStatement[] = v.about\n .filter(t => !taken.has(normName(t)))\n .map(t => ({ property: \"involves\", value: t, checked_at: today, by: EVENTS_BY }))\n // The marker records that this job set the level, so --force may redo it.\n added.push({ property: LEVEL_MARK, value: v.proposed ?? v.importance, checked_at: today, by: EVENTS_BY, ...(v.why ? { note: v.why } : {}) })\n // `lastUpdated` stays: the level and links are not news about the event,\n // and the catalog sorts and labels pages by that date.\n return { ...meta, importance: v.importance, importanceProposed: v.proposed, statements: [...kept, ...added] }\n}\n\nexport async function runEvents(hub: WikiHub, g: WikiGraph, call: EventsCall, opts: EventsOptions): Promise<EventsRun> {\n const o = g.ontology\n const { items: all, noPage } = pickEvents(hub, g, opts)\n const items = all.slice(0, opts.max)\n const run: EventsRun = { outcomes: [], costUsd: 0, calls: 0, capped: false, left: all.length - items.length }\n for (const ev of opts.about.length ? noPage : []) {\n run.outcomes.push({ event: ev.id, title: ev.title, date: ev.date, status: \"no-page\", about: [], dropped: [\"its pages are copied from another node\"] })\n }\n\n const write = (it: EventItem, v: EventVerdict, dropped: string[]): void => {\n const where = `${it.page.agentId}/${it.page.article.path}`\n const base: EventOutcome = { event: it.event.id, title: it.event.title, date: it.event.date, page: where, status: \"dry-run\", importance: v.importance, proposed: v.proposed, about: v.about, by: v.by, why: v.why, dropped }\n if (opts.dryRun) { run.outcomes.push(base); return }\n const store = hub.getAgentWiki(it.page.agentId)\n const path = it.page.article.path\n // Absorb or a person may have changed the page while the run waited\n // for the model: write onto what is on disk now, not the copy read at\n // the start. The page lock keeps another write from landing between\n // this read and the write.\n let why: string | undefined\n try {\n why = store.withArticleLock(path, () => {\n const current = store.readArticle(path)\n if (!current) return \"the page was moved or removed during the run\"\n if (current.meta.importance && !ownLevel(current.meta)) return \"a level was set on the page during the run\"\n return store.writeArticle(path, eventMeta(current.meta, v, opts.today), current.content, current.meta.owner || it.page.agentId) ? undefined : \"write refused\"\n })\n } catch (err) {\n if (!(err instanceof LockBusyError)) throw err\n why = \"the page was busy; run again\"\n }\n run.outcomes.push(why ? { ...base, status: \"failed\", dropped: [...dropped, why] } : { ...base, status: \"written\" })\n }\n\n // Rules first: free, and the same answer every run.\n const forModel: EventItem[] = []\n for (const it of items) {\n const level = ruleLevel(o.importance.rules, it.event.title, it.page.article.meta.tags ?? [])\n if (!level) { forModel.push(it); continue }\n // A rule gives the level only; what the title names is what it is about.\n const named = new Set(namedEntities(g, it.event.title).map(e => e.id))\n const about = it.candidates.filter(c => named.has(c.id)).slice(0, 3).map(c => c.title)\n write(it, { ...withOwnerRule(level, o), about, why: \"matched an importance rule\", by: \"rule\" }, [])\n }\n if (opts.rulesOnly) {\n run.left += forModel.length\n return run\n }\n\n for (let i = 0; i < forModel.length; i += opts.batch) {\n const batch = forModel.slice(i, i + opts.batch)\n if (run.costUsd >= opts.maxCostUsd) {\n run.capped = true\n run.left += forModel.length - i\n break\n }\n run.calls++\n let verdicts: ReturnType<typeof checkEventsReply>\n try {\n const reply = await call(buildEventsPrompt(batch, o))\n run.costUsd += reply.costUsd\n verdicts = checkEventsReply(reply.text, batch, o)\n } catch (err) {\n for (const it of batch) {\n run.outcomes.push({ event: it.event.id, title: it.event.title, date: it.event.date, page: `${it.page.agentId}/${it.page.article.path}`, status: \"failed\", about: [], dropped: [(err as Error).message.slice(0, 200)] })\n }\n continue\n }\n batch.forEach((it, at) => {\n const v = verdicts.get(at)\n if (v) write(it, v.verdict, v.dropped)\n else run.outcomes.push({ event: it.event.id, title: it.event.title, date: it.event.date, page: `${it.page.agentId}/${it.page.article.path}`, status: \"no-answer\", about: [], dropped: [\"the reply had no usable item for this event\"] })\n })\n }\n if (!opts.dryRun) {\n for (const agentId of new Set(run.outcomes.filter(x => x.status === \"written\").map(x => x.page!.split(\"/\")[0]))) {\n hub.getAgentWiki(agentId).rebuildIndex()\n }\n }\n return run\n}\n\n/** The owner's own word: set a level on an event and clear any proposal. */\nexport function setEventLevel(hub: WikiHub, g: WikiGraph, name: string, level: Importance): { ok: boolean; title?: string; page?: string; reason?: string } {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n const ev = id ? g.entities.get(id) : undefined\n if (!ev) return { ok: false, reason: `no page is titled \"${name}\"` }\n if (ev.type !== \"event\") return { ok: false, title: ev.title, reason: `\"${ev.title}\" is a ${ev.type}, not an event` }\n const page = localPage(hub, ev)\n if (!page) return { ok: false, title: ev.title, reason: \"its pages are copied from another node; set the level there\" }\n // Dropping this job's marker makes the level the owner's: no run redoes it.\n const store = hub.getAgentWiki(page.agentId)\n let ok: boolean\n let reason = \"write refused\"\n try {\n ok = store.withArticleLock(page.article.path, () => {\n const current = store.readArticle(page.article.path) ?? page.article\n const statements = (current.meta.statements ?? []).filter(s => !(s.by === EVENTS_BY && s.property === LEVEL_MARK))\n const meta: WikiArticleMeta = { ...current.meta, importance: level, importanceProposed: undefined, statements: statements.length ? statements : undefined }\n return store.writeArticle(page.article.path, meta, current.content, current.meta.owner || page.agentId)\n })\n } catch (err) {\n if (!(err instanceof LockBusyError)) throw err\n ok = false\n reason = \"the page was busy; run again\"\n }\n if (ok) store.rebuildIndex()\n return { ok, title: ev.title, page: `${page.agentId}/${page.article.path}`, reason: ok ? undefined : reason }\n}\n\nexport interface AboutSummary {\n title: string\n type: string\n /** Events in its History before this run, and how they split after. */\n before: number\n after: Record<Importance, number>\n}\n\n/** For a pilot: what each named page's History looks like after the run. */\nexport function summariseAbout(g: WikiGraph, run: EventsRun, about: string[]): AboutSummary[] {\n const out: AboutSummary[] = []\n const byEvent = new Map(run.outcomes.filter(x => x.importance).map(x => [x.event, x]))\n for (const name of about) {\n const id = g.names.get(normName(name)) ?? (g.entities.has(name) ? name : undefined)\n const e = id ? g.entities.get(id) : undefined\n if (!e) continue\n const linkedBefore = new Set(linkedEntities(g, e, new Set([\"event\"])).map(x => x.id))\n const after: Record<Importance, number> = { minor: 0, normal: 0, major: 0 }\n const seen = new Set<string>()\n for (const ev of g.entities.values()) {\n if (ev.type !== \"event\") continue\n const o = byEvent.get(ev.id)\n const linkedAfter = linkedBefore.has(ev.id) || !!o?.about.some(t => normName(t) === normName(e.title))\n if (!linkedAfter || seen.has(ev.id)) continue\n seen.add(ev.id)\n after[o?.importance ?? ev.importance]++\n }\n out.push({ title: e.title, type: e.type, before: linkedBefore.size, after })\n }\n return out\n}\n"],"mappings":"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","names":["EVENTS_BY","LEVEL_MARK","ABOUT_SKIP","MAX_CANDIDATES","BODY_CHARS","ruleLevel","rules","title","tags","have","t","IMPORTANCE_LEVELS","re","namedEntities","g","text","hay","normName","out","e","name","eventCandidates","ev","linked","linkedEntities","x","named","localPage","hub","p","ownLevel","meta","s","setByOthers","pickEvents","opts","scope","id","items","noPage","events","a","b","candidates","c","page","clip","n","buildEventsPrompt","o","lines","it","i","body","bodyOf","parseReply","fenced","raw","v","withOwnerRule","level","checkEventsReply","parsed","r","at","dropped","allowed","about","why","eventMeta","today","kept","taken","added","runEvents","call","all","run","write","where","base","store","path","current","err","LockBusyError","forModel","batch","verdicts","reply","agentId","setEventLevel","ok","reason","statements","summariseAbout","byEvent","linkedBefore","after","seen"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a,b,c,d,e,f}from"./chunk-4ZWZ42YE.js";import"./chunk-PE5V2LI7.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-OWNQ2FD4.js";import"./chunk-QIJLFPWE.js";export{d as approveFactProposal,c as listFactProposals,a as parseClaim,b as proposeFacts,e as rejectFactProposal,f as routeMemo};
|
|
2
|
+
//# sourceMappingURL=fact-proposals-X2O4W7VN.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{b as h}from"./chunk-
|
|
1
|
+
import{b as h}from"./chunk-IPMXIPTS.js";import"./chunk-RKPAVWXF.js";import{b as I}from"./chunk-LLNPKE7H.js";import"./chunk-SHEUCITK.js";import"./chunk-GL3H7XMI.js";import"./chunk-AK3XOA5N.js";import"./chunk-WRJFKA43.js";import"./chunk-3UOTLMXD.js";import"./chunk-FCPTN6NF.js";import"./chunk-7I7IEX4S.js";import"./chunk-54OORW5I.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";var p=t=>typeof t=="string"?t.trim():"";function $(t){return[`Run ${t.runId} "${t.title}" [${t.status}] on step ${t.step}: waiting on ${t.waitingOn}.`,t.tags?.length?`Tags: ${t.tags.join(", ")}`:"",...(t.steps??[]).slice(-8).map(s=>`- ${String(s.at).slice(0,16).replace("T"," ")} ${s.step} ${s.status}${s.note?`: ${s.note}`:""}`)].filter(Boolean).join(`
|
|
2
2
|
`)}async function T(t,c){let s=c.fetch??fetch,m=c.daemonUrl.replace(/\/$/,""),r=(p(t.action)||"list").toLowerCase(),f=c.env??process.env,w=async i=>{let l=await s(`${m}${i}`,{signal:AbortSignal.timeout(1e4)}),n=await l.json().catch(()=>({}));return{ok:l.ok,status:l.status,data:n}};try{if(r==="list"){let e=await w("/follow-up");if(!e.ok)return`Error: ${e.data?.error||`HTTP ${e.status}`}`;let o=e.data.groups??[];return o.length?o.map(d=>[`${d.tag}:`,...d.rows.map(a=>`- ${a.runId} "${a.title}" on ${a.step}: waiting on ${a.waitingOn} (since ${String(a.since).slice(0,16).replace("T"," ")} UTC)`)].join(`
|
|
3
3
|
`)).join(`
|
|
4
4
|
`):"No follow-up workflows are running."}if(r==="match"){let e=p(t.request)||p(t.title);if(!e)return"Error: match needs `request`: the owner's request in their words.";let o=h(t,f),d=await w(`/follow-up/match?q=${encodeURIComponent(e)}${o?`&agentId=${encodeURIComponent(o.agentId)}`:""}`);if(!d.ok)return`Error: ${d.data?.error||`HTTP ${d.status}`}`;let a=d.data.matches??[];return a.length?["Saved workflows, best fit first (confidence 0-1):",...a.map(u=>`- ${u.workflowId} "${u.title}" (${u.confidence}${u.autoStart?", starts without asking":""}): ${u.steps.map(k=>k.id).join(" \u2192 ")}`),'Start one with {action:"start", workflowId:"<id>", title:"\u2026", tags:["client:<name>"]}. Run its steps through the workflow, not by hand.'].join(`
|
|
5
5
|
`):"No saved workflow fits. If the request has several steps, build one: start with title and steps."}if(r==="status"){let e=p(t.runId);if(!e)return"Error: status needs runId.";let o=await w(`/follow-up/${encodeURIComponent(e)}`);return o.ok?$(o.data.run):`Error: ${o.data?.error||`HTTP ${o.status}`}`}let i=h(t,f);if(!i)return"Error: couldn't tell which agent you are. Pass callerAgentId.";let l=await s(`${m}/follow-up`,{method:"POST",headers:{"Content-Type":"application/json",...I(f)},body:JSON.stringify({action:r,agentId:i.agentId,workflowId:t.workflowId,title:t.title,description:t.description,tags:t.tags,inputs:t.inputs,steps:t.steps,edges:t.edges,approval:t.approval,autoStart:t.autoStart,requestId:t.requestId,runId:t.runId,step:t.step,evidence:t.evidence,note:t.note,reason:t.reason,fromRun:t.fromRun,status:t.status}),signal:AbortSignal.timeout(2e4)}),n=await l.json().catch(()=>({}));if(!l.ok)return`Error: ${n?.error||`HTTP ${l.status}`}`;if(r==="start"){let e=n.run;return[`Started run ${e.runId} "${e.title}"${n.built?" (built from the steps you gave; propose it with fromRun to keep it)":""}.`,n.awaitingApproval?"It waits for the owner's approval before the first step.":`It is on step ${e.step}: ${e.waitingOn}.`,"AgentX follows it from here: it starts each step, reminds whoever is slow, and tells the owner when it ends. Do not run its steps by hand.",...n.warning?[`Note: ${n.warning}`]:[]].join(" ")}return r==="plan"?[`Plan recorded on run ${n.run?.runId??t.runId}:`,...(n.plan??[]).map(e=>`- ${e.id} ${e.title}`),'Report each step with {action:"step", runId, step:"<id>", status:"started"|"done"|"failed"}.'].join(`
|
|
6
6
|
`):r==="step"?`Step recorded. ${n.run?$(n.run):""}`.trim():r==="done"?`Step recorded as done. ${n.run?$(n.run):""}`.trim():r==="blocked"?"The step is marked blocked and the owner is told. Nothing more happens on it until it is sorted.":`Saved ${n.workflowId} switched off, and asked the owner (card ${n.cardId}) whether to keep it as a reusable workflow.`}catch(i){return`Error: couldn't reach the daemon (${i?.message??i}).`}}export{T as runWorkflowTool};
|
|
7
|
-
//# sourceMappingURL=follow-up-tool-
|
|
7
|
+
//# sourceMappingURL=follow-up-tool-GUBBXNEZ.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=grants-
|
|
1
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./chunk-UNIXYV3U.js";import"./chunk-AKWBDCMU.js";import"./chunk-Y4CYQV7G.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{c as DEFAULT_GRANT_DAYS,a as GUEST_SCOPE_PREFIX,b as JOIN_CARD_BY,h as JOIN_FAILED,d as MAX_GRANT_DAYS,j as NO_GRANT,l as PAUSED,k as WAITING_HOST,s as endGrant,o as grantBrief,u as grantForGuest,e as grantIdOf,n as guestAccess,p as guestTask,g as inviteGuest,i as joinGuest,f as newGrantId,q as pauseGrant,r as resumeGrant,m as settleGrant,t as updateGrant};
|
|
2
|
+
//# sourceMappingURL=grants-CEUGZBQ4.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a}from"./chunk-C43E3YFT.js";import"./chunk-OISCRNMW.js";import"./chunk-OWNQ2FD4.js";import"./chunk-KEXBEUSU.js";import"./chunk-ROLSSYXE.js";import"./chunk-OW5EXDVY.js";import"./chunk-WPNRDEHW.js";import"./chunk-66DPMVUC.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-MCI3DIWW.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-54OORW5I.js";import"./chunk-BRK6M6LA.js";import"./chunk-UIBUZ2N3.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{a as WikiHub};
|
|
2
|
+
//# sourceMappingURL=hub-IIW2GBO5.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -10940,6 +10940,10 @@ declare class AgentXDaemon {
|
|
|
10940
10940
|
/** The channel and chat of the running turn of `agentId` that `proof`
|
|
10941
10941
|
* names, as the registry files the run. Null when it names none. */
|
|
10942
10942
|
private provenTurn;
|
|
10943
|
+
/** The agent whose running turn `proof` names: the owner of its task,
|
|
10944
|
+
* or `claimed` when its channel and chat match a running turn of that
|
|
10945
|
+
* agent. Null when the call proves none. */
|
|
10946
|
+
private provenAgent;
|
|
10943
10947
|
private handleHttp;
|
|
10944
10948
|
/**
|
|
10945
10949
|
* OpenAI-compatible chat completions endpoint.
|
|
@@ -12299,6 +12303,8 @@ declare class WikiStore {
|
|
|
12299
12303
|
readonly baseDir: string;
|
|
12300
12304
|
private rawDir;
|
|
12301
12305
|
private log;
|
|
12306
|
+
/** How long a write waits for another process holding the page's lock. */
|
|
12307
|
+
lockWaitMs: number;
|
|
12302
12308
|
constructor(baseDir?: string, log?: (...args: unknown[]) => void);
|
|
12303
12309
|
/**
|
|
12304
12310
|
* Check if an agent can read an article.
|
|
@@ -12324,10 +12330,19 @@ declare class WikiStore {
|
|
|
12324
12330
|
before?: string;
|
|
12325
12331
|
}): WikiEntry[];
|
|
12326
12332
|
private parseEntry;
|
|
12333
|
+
/**
|
|
12334
|
+
* Run `fn` holding the page's lock, so a read → change → write inside it
|
|
12335
|
+
* can't lose a write from another process. Every `writeArticle` takes
|
|
12336
|
+
* the same lock; re-entrant within one process. Locks live under
|
|
12337
|
+
* `_locks/`, which page listings skip. Throws LockBusyError when another
|
|
12338
|
+
* holder keeps it past the wait.
|
|
12339
|
+
*/
|
|
12340
|
+
withArticleLock<T>(path: string, fn: () => T): T;
|
|
12327
12341
|
/**
|
|
12328
12342
|
* Write or update a wiki article.
|
|
12329
12343
|
*/
|
|
12330
12344
|
writeArticle(path: string, meta: WikiArticleMeta, content: string, agentId: string): boolean;
|
|
12345
|
+
private writeArticleLocked;
|
|
12331
12346
|
/**
|
|
12332
12347
|
* Save current article content as an immutable version before overwriting.
|
|
12333
12348
|
* Versions stored in _versions/{article-path}/{timestamp}.md
|