@rubytech/create-maxy-code 0.1.181 → 0.1.183
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/__tests__/bundler-rewrite-platform-lib.test.js +68 -0
- package/dist/bundler-rewrite-platform-lib.js +29 -0
- package/package.json +1 -1
- package/payload/platform/lib/graph-search/dist/index.d.ts +10 -0
- package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-search/dist/index.js +57 -30
- package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-search/src/__tests__/hybrid.test.ts +95 -2
- package/payload/platform/lib/graph-search/src/__tests__/vector-index-coverage.test.ts +198 -0
- package/payload/platform/lib/graph-search/src/index.ts +73 -29
- package/payload/platform/neo4j/schema.cypher +36 -0
- package/payload/platform/plugins/admin/PLUGIN.md +2 -0
- package/payload/platform/plugins/admin/hooks/admin-authoring-observer.sh +155 -0
- package/payload/platform/plugins/admin/skills/access-manager/SKILL.md +7 -5
- package/payload/platform/plugins/admin/skills/access-manager/references/operations.md +27 -55
- package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +178 -0
- package/payload/platform/plugins/admin/skills/specialist-management/SKILL.md +3 -2
- package/payload/platform/plugins/aeo/mcp/dist/index.js +3 -0
- package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/PLUGIN.md +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/index.js +3 -0
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/access-control.md +29 -22
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js +56 -0
- package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js.map +1 -0
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +5 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +76 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +30 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +10 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +35 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +61 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js +125 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +65 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js +45 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +24 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +16 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +1 -0
- package/payload/platform/plugins/memory/references/schema-base.md +4 -2
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +24 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +3 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/PLUGIN.md +1 -0
- package/payload/platform/plugins/work/mcp/dist/index.js +4 -0
- package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/workflows/PLUGIN.md +1 -0
- package/payload/platform/plugins/workflows/mcp/dist/index.js +3 -0
- package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
- package/payload/platform/scripts/__tests__/agents-md-bootstrap.test.sh +111 -0
- package/payload/platform/scripts/lib/agents-md-bootstrap.sh +49 -0
- package/payload/platform/scripts/setup-account.sh +18 -14
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +12 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +32 -4
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +154 -53
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/templates/agents/admin/AGENTS.md +18 -7
- package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
- package/payload/platform/templates/specialists/agents/archive-ingest-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/citation-auditor.md +1 -1
- package/payload/platform/templates/specialists/agents/compiled-truth-rewriter.md +1 -1
- package/payload/platform/templates/specialists/agents/content-producer.md +3 -1
- package/payload/platform/templates/specialists/agents/database-operator.md +2 -2
- package/payload/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
- package/payload/platform/templates/specialists/agents/public-session-reviewer.md +40 -0
- package/payload/platform/templates/specialists/agents/research-assistant.md +1 -1
- package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts +13 -0
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.d.ts.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js +15 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/lib/voice-corpus.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-retrieve-conditioning.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/src/lib/voice-corpus.ts +15 -1
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +1 -1
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-retrieve-conditioning.ts +1 -1
- package/payload/server/public/assets/ChatInput-DzacFNMk.css +1 -0
- package/payload/server/public/assets/{Checkbox-YrQovXpN.js → Checkbox-BJKNkUYu.js} +1 -1
- package/payload/server/public/assets/{admin-DH5jp-1u.js → admin-BNy4N2d6.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Do2zYONG.js → architectureDiagram-Q4EWVU46-DZoOzmjE.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DpIX_bRu.js → blockDiagram-DXYQGD6D-DG3yufCR.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Cz335ZSY.js → c4Diagram-AHTNJAMY-BBx5wXuZ.js} +1 -1
- package/payload/server/public/assets/channel-DdtUtt5g.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-Dmknn3Wo.js → chunk-336JU56O-DwP7g5ns.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-ClfGjizN.js → chunk-426QAEUC-DXzGdc22.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BPKctJ5c.js → chunk-4TB4RGXK-1LDRjk0E.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-BWDCO9zw.js → chunk-5FUZZQ4R-BHjWhwhn.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-BE34_Db0.js → chunk-5PVQY5BW-CwPHRVN8.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BysA-_6v.js → chunk-EDXVE4YY-7443hrYZ.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-BMVyMsqA.js → chunk-ENJZ2VHE-BTnmmnmX.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-C5KRdLV4.js → chunk-ICPOFSXX-CPnMJplL.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DVZD-AVc.js → chunk-OYMX7WX6-DCQ5Q4RS.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-DYmQdx8x.js → chunk-U2HBQHQK-BmfZG8e4.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-DrZenIl3.js → chunk-X2U36JSP-Da2yJL2u.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-CDuGbvMq.js → chunk-YZCP3GAM-BdUmMUJ6.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-COztbiu5.js → chunk-ZZ45TVLE-abkGirrZ.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CKk2DFZe.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E--YvfDQCh.js +1 -0
- package/payload/server/public/assets/clone-Cw6UfPGM.js +1 -0
- package/payload/server/public/assets/{dagre-Cv9Ib2OM.js → dagre-BVVuAEsU.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-CoEd61KZ.js → dagre-KV5264BT-VG2kNj19.js} +1 -1
- package/payload/server/public/assets/data-uBpwaldK.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-WXNzw3uW.js → diagram-5BDNPKRD-DRiVy69K.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-C6IuQ2VV.js → diagram-G4DWMVQ6-DtpiRTYX.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CdJdir5A.js → diagram-MMDJMWI5-Da3t99fY.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-DxWKQH5T.js → diagram-TYMM5635-BzQmLTJQ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9fvs33K.js → erDiagram-SMLLAGMA-D3Ll-GDw.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BO7Yrbqv.js → flowDiagram-DWJPFMVM-D17bje6d.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CQJyWBZq.js → ganttDiagram-T4ZO3ILL-BjeQ-Bun.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DZfQHrYw.js → gitGraphDiagram-UUTBAWPF-LtX4pvZS.js} +1 -1
- package/payload/server/public/assets/{graph-labels-BMU8LsOD.js → graph-labels-Cn9jAE6I.js} +1 -1
- package/payload/server/public/assets/graph-tvTPvBaz.js +1 -0
- package/payload/server/public/assets/{graphlib-C40H-Q5E.js → graphlib-CzwsfZOw.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-CakfV5f9.js → infoDiagram-42DDH7IO-DOgH4i52.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CPuBPyfa.js → ishikawaDiagram-UXIWVN3A-DYqy5BFj.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-zpZm2Mmo.js → journeyDiagram-VCZTEJTY-CsFpIULJ.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DfJduQCo.js → kanban-definition-6JOO6SKY-5uZuArw7.js} +1 -1
- package/payload/server/public/assets/{lib-Bnh57com.js → lib-p4ylk2XS.js} +1 -1
- package/payload/server/public/assets/{line-BpYQqO5R.js → line-BY8PmCSW.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-C5Mwi14D.js → mermaid-parser.core-CJ_9xqwK.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-D8qBtvvT.js → mermaid.core-CXznBkX7.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bli9JhIN.js → mindmap-definition-QFDTVHPH-DZbHBud5.js} +1 -1
- package/payload/server/public/assets/{page-0lzgQWnS.js → page-B3VYaBcf.js} +1 -1
- package/payload/server/public/assets/{page-C29S3cBt.js → page-CfN7nw1J.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-MsLXTSLg.js → pieDiagram-DEJITSTG-QmOi4DRG.js} +1 -1
- package/payload/server/public/assets/public-Bbew78md.js +7 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-De1sh2K0.js → quadrantDiagram-34T5L4WZ-Cpidq6Xj.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-D5Sfg1t_.js → requirementDiagram-MS252O5E-CBqtfbzR.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DHA3LIbv.js → sankeyDiagram-XADWPNL6-4BiY4dV9.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BE_QlG1B.js → sequenceDiagram-FGHM5R23-DVlL-l2u.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-NIwp3F4u.js → stateDiagram-FHFEXIEX-CAm9dW68.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B2EzXi50.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CPE9jyDF.js → timeline-definition-GMOUNBTQ-CD-tZc4y.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CKfoyYmH.js → vennDiagram-DHZGUBPP-Davcm0TF.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-B9yJek-o.js → wardleyDiagram-NUSXRM2D-40LBYw_Y.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DuCcSLqX.js → xychartDiagram-5P7HB3ND-DEPT-__v.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +1158 -337
- package/payload/premium-plugins/writer-craft/lib/graph-trash/dist/index.d.ts +0 -106
- package/payload/premium-plugins/writer-craft/lib/graph-trash/dist/index.d.ts.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/graph-trash/dist/index.js +0 -340
- package/payload/premium-plugins/writer-craft/lib/graph-trash/dist/index.js.map +0 -1
- package/payload/premium-plugins/writer-craft/lib/graph-trash/package.json +0 -7
- package/payload/server/public/assets/ChatInput-CJ50oqWt.css +0 -1
- package/payload/server/public/assets/channel-PC4_IjI1.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +0 -1
- package/payload/server/public/assets/clone-CkNt9L9r.js +0 -1
- package/payload/server/public/assets/data-CtanHhM2.js +0 -1
- package/payload/server/public/assets/graph-6DPD6be1.js +0 -1
- package/payload/server/public/assets/public-DltgEfA9.js +0 -7
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +0 -1
- /package/payload/server/public/assets/{ChatInput-CJo_77bp.js → ChatInput-CvRaT05l.js} +0 -0
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Soft-delete primitive for the knowledge graph.
|
|
3
|
-
*
|
|
4
|
-
* MCP-tool callers must NEVER `DETACH DELETE` user-domain nodes. Use
|
|
5
|
-
* `trashNode` to mark a node `:Trashed`; `restoreNode` removes the label;
|
|
6
|
-
* `emptyTrash` hard-deletes nodes whose `trashedAt < now - graceDays`. The
|
|
7
|
-
* 2026-04-20 incident wiped 19 nodes via a single autonomous `DETACH DELETE`
|
|
8
|
-
* — Neo4j Community has no PITR, so properties were unrecoverable. This
|
|
9
|
-
* primitive contains the blast radius for every caller.
|
|
10
|
-
*
|
|
11
|
-
* Unique-constraint handling: when the trashed node's labels carry single-
|
|
12
|
-
* key UNIQUE constraints (e.g. `LocalBusiness.accountId`), the live values
|
|
13
|
-
* are snapshotted into `_trashedKeys` (JSON) and nulled on the node, so
|
|
14
|
-
* MERGE against the same key won't collide. `restoreNode` writes them back
|
|
15
|
-
* and fails loudly when an active node already occupies the slot.
|
|
16
|
-
*
|
|
17
|
-
* Label-aware cascade: when `trashNode` trashes a `:Conversation`, it also
|
|
18
|
-
* trashes every `(m:Message)-[:PART_OF]->(c)` Message in the same managed
|
|
19
|
-
* transaction. This makes `MATCH (m:Trashed)` a correct audit primitive —
|
|
20
|
-
* trashing a Conversation without cascading to its Messages silently
|
|
21
|
-
* under-reports the blast radius. `restoreNode` reverses both sides.
|
|
22
|
-
*/
|
|
23
|
-
import type { Session } from "neo4j-driver";
|
|
24
|
-
export interface TrashParams {
|
|
25
|
-
session: Session;
|
|
26
|
-
accountId: string;
|
|
27
|
-
elementId: string;
|
|
28
|
-
/** Provenance marker — appears verbatim in `trashedBy` and `[trash:marked] by=`. */
|
|
29
|
-
by: string;
|
|
30
|
-
reason?: string;
|
|
31
|
-
}
|
|
32
|
-
export interface TrashResult {
|
|
33
|
-
trashed: boolean;
|
|
34
|
-
alreadyTrashed: boolean;
|
|
35
|
-
nodeId: string;
|
|
36
|
-
/** Labels excluding `:Trashed`. */
|
|
37
|
-
labels: string[];
|
|
38
|
-
trashedAt: string;
|
|
39
|
-
originalKeys: Record<string, unknown>;
|
|
40
|
-
}
|
|
41
|
-
export declare function trashNode(params: TrashParams): Promise<TrashResult>;
|
|
42
|
-
export interface RestoreParams {
|
|
43
|
-
session: Session;
|
|
44
|
-
accountId: string;
|
|
45
|
-
elementId: string;
|
|
46
|
-
}
|
|
47
|
-
export interface RestoreResult {
|
|
48
|
-
restored: boolean;
|
|
49
|
-
nodeId: string;
|
|
50
|
-
labels: string[];
|
|
51
|
-
restoredKeys: Record<string, unknown>;
|
|
52
|
-
}
|
|
53
|
-
export declare function restoreNode(params: RestoreParams): Promise<RestoreResult>;
|
|
54
|
-
export interface EmptyTrashParams {
|
|
55
|
-
session: Session;
|
|
56
|
-
accountId: string;
|
|
57
|
-
/** Default 30. */
|
|
58
|
-
graceDays?: number;
|
|
59
|
-
dryRun?: boolean;
|
|
60
|
-
/** Optional label whitelist — only nodes carrying any of these labels are eligible. */
|
|
61
|
-
labels?: string[];
|
|
62
|
-
/** Side-effect callback invoked before the `DETACH DELETE` for each
|
|
63
|
-
* emptied node, e.g. to clean disk attachments or purge sibling JSONL
|
|
64
|
-
* transcripts.
|
|
65
|
-
*
|
|
66
|
-
* Contract (Task 237): if the callback **throws**, the candidate is
|
|
67
|
-
* **skipped this run** — no `DETACH DELETE` runs and no `[trash:emptied]`
|
|
68
|
-
* line emits. The thrown message lands in
|
|
69
|
-
* `[trash:empty-run] reason=onEmpty-failed` and the candidate becomes
|
|
70
|
-
* eligible again on the next sweep. Pre-Task-237 consumers
|
|
71
|
-
* (`removeAttachmentDir` for `:KnowledgeDocument`) cannot throw because
|
|
72
|
-
* they wrap `fs.rm({force:true})`, so the contract change is invisible
|
|
73
|
-
* to them. */
|
|
74
|
-
onEmpty?: (node: TrashCandidate) => Promise<void>;
|
|
75
|
-
}
|
|
76
|
-
export interface TrashCandidate {
|
|
77
|
-
elementId: string;
|
|
78
|
-
labels: string[];
|
|
79
|
-
trashedAt: string;
|
|
80
|
-
trashedBy: string | null;
|
|
81
|
-
/** Original unique-key snapshot — useful for KnowledgeDocument disk cleanup. */
|
|
82
|
-
trashedKeys: Record<string, unknown>;
|
|
83
|
-
}
|
|
84
|
-
export interface EmptyTrashResult {
|
|
85
|
-
graceDays: number;
|
|
86
|
-
dryRun: boolean;
|
|
87
|
-
candidates: TrashCandidate[];
|
|
88
|
-
emptied: number;
|
|
89
|
-
}
|
|
90
|
-
export declare function emptyTrash(params: EmptyTrashParams): Promise<EmptyTrashResult>;
|
|
91
|
-
/**
|
|
92
|
-
* Read-filter clause excluding trashed nodes for the given Cypher alias.
|
|
93
|
-
*
|
|
94
|
-
* Filters both the `:Trashed` label (primitive) and the `deletedAt`
|
|
95
|
-
* property (KnowledgeDocument soft-delete). Belt-and-braces: a row marked
|
|
96
|
-
* by either signal is excluded from reads.
|
|
97
|
-
*
|
|
98
|
-
* notTrashed("node") → "(NOT node:Trashed AND node.deletedAt IS NULL)"
|
|
99
|
-
* notTrashed("related") → "(NOT related:Trashed AND related.deletedAt IS NULL)"
|
|
100
|
-
*/
|
|
101
|
-
export declare function notTrashed(alias: string): string;
|
|
102
|
-
/** Runtime accessor for the static unique-keys map (for tests + sibling tooling). */
|
|
103
|
-
export declare function uniqueKeysForLabels(labels: string[]): string[];
|
|
104
|
-
/** Property names trashNode writes — exposed so callers can re-MERGE without colliding. */
|
|
105
|
-
export declare const TRASH_METADATA_PROPS: readonly string[];
|
|
106
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA2C5C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAyIzE;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CA6G/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uFAAuF;IACvF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;;;;;;;mBAWe;IACf,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiFpF;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAI9D;AAED,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAqB,CAAC"}
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Soft-delete primitive for the knowledge graph.
|
|
4
|
-
*
|
|
5
|
-
* MCP-tool callers must NEVER `DETACH DELETE` user-domain nodes. Use
|
|
6
|
-
* `trashNode` to mark a node `:Trashed`; `restoreNode` removes the label;
|
|
7
|
-
* `emptyTrash` hard-deletes nodes whose `trashedAt < now - graceDays`. The
|
|
8
|
-
* 2026-04-20 incident wiped 19 nodes via a single autonomous `DETACH DELETE`
|
|
9
|
-
* — Neo4j Community has no PITR, so properties were unrecoverable. This
|
|
10
|
-
* primitive contains the blast radius for every caller.
|
|
11
|
-
*
|
|
12
|
-
* Unique-constraint handling: when the trashed node's labels carry single-
|
|
13
|
-
* key UNIQUE constraints (e.g. `LocalBusiness.accountId`), the live values
|
|
14
|
-
* are snapshotted into `_trashedKeys` (JSON) and nulled on the node, so
|
|
15
|
-
* MERGE against the same key won't collide. `restoreNode` writes them back
|
|
16
|
-
* and fails loudly when an active node already occupies the slot.
|
|
17
|
-
*
|
|
18
|
-
* Label-aware cascade: when `trashNode` trashes a `:Conversation`, it also
|
|
19
|
-
* trashes every `(m:Message)-[:PART_OF]->(c)` Message in the same managed
|
|
20
|
-
* transaction. This makes `MATCH (m:Trashed)` a correct audit primitive —
|
|
21
|
-
* trashing a Conversation without cascading to its Messages silently
|
|
22
|
-
* under-reports the blast radius. `restoreNode` reverses both sides.
|
|
23
|
-
*/
|
|
24
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.TRASH_METADATA_PROPS = void 0;
|
|
26
|
-
exports.trashNode = trashNode;
|
|
27
|
-
exports.restoreNode = restoreNode;
|
|
28
|
-
exports.emptyTrash = emptyTrash;
|
|
29
|
-
exports.notTrashed = notTrashed;
|
|
30
|
-
exports.uniqueKeysForLabels = uniqueKeysForLabels;
|
|
31
|
-
/**
|
|
32
|
-
* Single-key UNIQUE properties per label, mirroring `platform/neo4j/schema.cypher`.
|
|
33
|
-
*
|
|
34
|
-
* Composite UNIQUEs (UserProfile, Email composite, AccessGrant) are
|
|
35
|
-
* represented by a single nullable component — Neo4j enforces a composite
|
|
36
|
-
* constraint only when every component is non-null, so nulling one frees it.
|
|
37
|
-
*/
|
|
38
|
-
const UNIQUE_KEYS_BY_LABEL = {
|
|
39
|
-
Person: ["email", "telephone"],
|
|
40
|
-
Service: ["serviceId"],
|
|
41
|
-
LocalBusiness: ["accountId"],
|
|
42
|
-
Task: ["taskId"],
|
|
43
|
-
Event: ["eventId"],
|
|
44
|
-
// :KnowledgeDocument is keyed on `attachmentId` (document writer path —
|
|
45
|
-
// file/URL/obsidian/contract attachment + legacy Gmail-thread shape under
|
|
46
|
-
// `source:'email'`). Task 397 split the conversation transcripts off into
|
|
47
|
-
// `:ConversationArchive`, which carries `conversationIdentity`.
|
|
48
|
-
KnowledgeDocument: ["attachmentId"],
|
|
49
|
-
ConversationArchive: ["conversationIdentity"],
|
|
50
|
-
DigitalDocument: ["attachmentId"],
|
|
51
|
-
Conversation: ["sessionId"],
|
|
52
|
-
Message: ["messageId"],
|
|
53
|
-
Workflow: ["workflowId"],
|
|
54
|
-
WorkflowStep: ["stepId"],
|
|
55
|
-
WorkflowRun: ["runId"],
|
|
56
|
-
Preference: ["preferenceId"],
|
|
57
|
-
Email: ["emailId", "messageId"],
|
|
58
|
-
AdminUser: ["userId"],
|
|
59
|
-
ToolCall: ["callId"],
|
|
60
|
-
// Composite component nulls — frees the composite constraint:
|
|
61
|
-
AccessGrant: ["contactValue"], // composite (contactValue, agentSlug, accountId)
|
|
62
|
-
UserProfile: ["userId"], // composite (accountId, userId)
|
|
63
|
-
};
|
|
64
|
-
const TRASH_PROP_NAMES = [
|
|
65
|
-
"trashedAt",
|
|
66
|
-
"trashedBy",
|
|
67
|
-
"trashReason",
|
|
68
|
-
"_trashedKeys",
|
|
69
|
-
];
|
|
70
|
-
async function trashNode(params) {
|
|
71
|
-
const { session, accountId, elementId, by, reason } = params;
|
|
72
|
-
const lookup = await session.run(`MATCH (n) WHERE elementId(n) = $eid AND n.accountId = $accountId
|
|
73
|
-
RETURN labels(n) AS labels, properties(n) AS props`, { eid: elementId, accountId });
|
|
74
|
-
if (lookup.records.length === 0) {
|
|
75
|
-
throw new Error(`trashNode: node not found (elementId=${elementId} accountId=${accountId.slice(0, 8)}…)`);
|
|
76
|
-
}
|
|
77
|
-
const allLabels = lookup.records[0].get("labels");
|
|
78
|
-
const props = lookup.records[0].get("props");
|
|
79
|
-
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
80
|
-
if (allLabels.includes("Trashed")) {
|
|
81
|
-
return {
|
|
82
|
-
trashed: false,
|
|
83
|
-
alreadyTrashed: true,
|
|
84
|
-
nodeId: elementId,
|
|
85
|
-
labels: baseLabels,
|
|
86
|
-
trashedAt: String(props.trashedAt ?? ""),
|
|
87
|
-
originalKeys: {},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
const uniqueKeys = new Set();
|
|
91
|
-
for (const label of baseLabels) {
|
|
92
|
-
for (const key of UNIQUE_KEYS_BY_LABEL[label] ?? [])
|
|
93
|
-
uniqueKeys.add(key);
|
|
94
|
-
}
|
|
95
|
-
const originalKeys = {};
|
|
96
|
-
for (const k of uniqueKeys) {
|
|
97
|
-
if (props[k] !== undefined && props[k] !== null)
|
|
98
|
-
originalKeys[k] = props[k];
|
|
99
|
-
}
|
|
100
|
-
const setNullClauses = Object.keys(originalKeys)
|
|
101
|
-
.map((k) => `n.\`${k}\` = null`)
|
|
102
|
-
.join(", ");
|
|
103
|
-
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
104
|
-
const trashedAt = new Date().toISOString();
|
|
105
|
-
const isConversation = baseLabels.includes("Conversation");
|
|
106
|
-
// Message unique-key list computed once — matches UNIQUE_KEYS_BY_LABEL["Message"].
|
|
107
|
-
const messageUniqueKeys = UNIQUE_KEYS_BY_LABEL["Message"] ?? [];
|
|
108
|
-
// Root trash + Conversation→Message cascade in one managed transaction so a
|
|
109
|
-
// DB error mid-sweep can't leave a Conversation :Trashed with some Messages
|
|
110
|
-
// un-trashed (the 2026-04-22 audit correctness gap). For non-Conversation
|
|
111
|
-
// labels, the cascade branch is a no-op — same one-write shape as before.
|
|
112
|
-
let cascadedMessageCount = 0;
|
|
113
|
-
await session.executeWrite(async (tx) => {
|
|
114
|
-
await tx.run(`MATCH (n) WHERE elementId(n) = $eid
|
|
115
|
-
SET n:Trashed,
|
|
116
|
-
n.trashedAt = datetime($trashedAt),
|
|
117
|
-
n.trashedBy = $by,
|
|
118
|
-
n.trashReason = $reason,
|
|
119
|
-
n._trashedKeys = $trashedKeysJson${setNullSuffix}`, {
|
|
120
|
-
eid: elementId,
|
|
121
|
-
trashedAt,
|
|
122
|
-
by,
|
|
123
|
-
reason: reason ?? null,
|
|
124
|
-
trashedKeysJson: JSON.stringify(originalKeys),
|
|
125
|
-
});
|
|
126
|
-
if (isConversation) {
|
|
127
|
-
// Two-step cascade: collect Message elementIds and their unique-key
|
|
128
|
-
// values first, then apply :Trashed + snapshot + null in one SET per
|
|
129
|
-
// message using parameter-passed snapshot JSON. This keeps JSON
|
|
130
|
-
// construction in the Node process (where JSON.stringify is trivially
|
|
131
|
-
// correct) rather than building escaped JSON inside Cypher.
|
|
132
|
-
const collectKeys = messageUniqueKeys.length > 0
|
|
133
|
-
? messageUniqueKeys.map((k) => `\`${k}\`: m.\`${k}\``).join(", ")
|
|
134
|
-
: "";
|
|
135
|
-
const collectMsgProps = collectKeys ? `, {${collectKeys}}` : ", {}";
|
|
136
|
-
const collected = await tx.run(`MATCH (c) WHERE elementId(c) = $eid
|
|
137
|
-
MATCH (m:Message)-[:PART_OF]->(c)
|
|
138
|
-
WHERE NOT m:Trashed
|
|
139
|
-
RETURN elementId(m) AS meid${collectMsgProps} AS keys`, { eid: elementId });
|
|
140
|
-
for (const rec of collected.records) {
|
|
141
|
-
const meid = rec.get("meid");
|
|
142
|
-
const keys = rec.get("keys");
|
|
143
|
-
const liveKeys = {};
|
|
144
|
-
for (const k of messageUniqueKeys) {
|
|
145
|
-
if (keys[k] !== undefined && keys[k] !== null)
|
|
146
|
-
liveKeys[k] = keys[k];
|
|
147
|
-
}
|
|
148
|
-
const msgSetNulls = Object.keys(liveKeys).length > 0
|
|
149
|
-
? ", " + Object.keys(liveKeys).map((k) => `m.\`${k}\` = null`).join(", ")
|
|
150
|
-
: "";
|
|
151
|
-
await tx.run(`MATCH (m) WHERE elementId(m) = $meid
|
|
152
|
-
SET m:Trashed,
|
|
153
|
-
m.trashedAt = datetime($trashedAt),
|
|
154
|
-
m.trashedBy = $by,
|
|
155
|
-
m.trashReason = $reason,
|
|
156
|
-
m._trashedKeys = $trashedKeysJson${msgSetNulls}`, {
|
|
157
|
-
meid,
|
|
158
|
-
trashedAt,
|
|
159
|
-
by: `${by}:cascade-from-conversation`,
|
|
160
|
-
reason: reason ?? `cascade from Conversation ${elementId}`,
|
|
161
|
-
trashedKeysJson: JSON.stringify(liveKeys),
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
cascadedMessageCount = collected.records.length;
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
process.stderr.write(`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}\n`);
|
|
168
|
-
if (isConversation) {
|
|
169
|
-
process.stderr.write(`[trash:cascaded] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount} by=${by}\n`);
|
|
170
|
-
}
|
|
171
|
-
return {
|
|
172
|
-
trashed: true,
|
|
173
|
-
alreadyTrashed: false,
|
|
174
|
-
nodeId: elementId,
|
|
175
|
-
labels: baseLabels,
|
|
176
|
-
trashedAt,
|
|
177
|
-
originalKeys,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
async function restoreNode(params) {
|
|
181
|
-
const { session, accountId, elementId } = params;
|
|
182
|
-
const lookup = await session.run(`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
183
|
-
RETURN labels(n) AS labels, n._trashedKeys AS keysJson`, { eid: elementId });
|
|
184
|
-
if (lookup.records.length === 0) {
|
|
185
|
-
throw new Error(`restoreNode: trashed node not found (elementId=${elementId})`);
|
|
186
|
-
}
|
|
187
|
-
const allLabels = lookup.records[0].get("labels");
|
|
188
|
-
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
189
|
-
const keysJson = lookup.records[0].get("keysJson");
|
|
190
|
-
const originalKeys = keysJson ? JSON.parse(keysJson) : {};
|
|
191
|
-
// Conflict check: an active node already holds the unique slot we want back?
|
|
192
|
-
for (const label of baseLabels) {
|
|
193
|
-
const uniqueKeys = UNIQUE_KEYS_BY_LABEL[label] ?? [];
|
|
194
|
-
for (const k of uniqueKeys) {
|
|
195
|
-
const v = originalKeys[k];
|
|
196
|
-
if (v === undefined || v === null)
|
|
197
|
-
continue;
|
|
198
|
-
const conflict = await session.run(`MATCH (other:\`${label}\`)
|
|
199
|
-
WHERE elementId(other) <> $eid
|
|
200
|
-
AND NOT other:Trashed
|
|
201
|
-
AND other.\`${k}\` = $val
|
|
202
|
-
RETURN elementId(other) AS otherId LIMIT 1`, { eid: elementId, val: v });
|
|
203
|
-
if (conflict.records.length > 0) {
|
|
204
|
-
const otherId = conflict.records[0].get("otherId");
|
|
205
|
-
throw new Error(`restoreNode: cannot restore ${label} elementId=${elementId} — active node elementId=${otherId} already holds ${k}=${JSON.stringify(v)}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
const setClauses = Object.keys(originalKeys)
|
|
210
|
-
.map((k) => `n.\`${k}\` = $val_${k}`)
|
|
211
|
-
.join(", ");
|
|
212
|
-
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
213
|
-
const setParams = { eid: elementId };
|
|
214
|
-
for (const [k, v] of Object.entries(originalKeys))
|
|
215
|
-
setParams[`val_${k}`] = v;
|
|
216
|
-
const isConversation = baseLabels.includes("Conversation");
|
|
217
|
-
let cascadedMessageCount = 0;
|
|
218
|
-
await session.executeWrite(async (tx) => {
|
|
219
|
-
await tx.run(`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
220
|
-
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
221
|
-
SET n.restoredAt = datetime()${setSuffix}`, setParams);
|
|
222
|
-
if (isConversation) {
|
|
223
|
-
// Reverse of the trashNode cascade: re-label and restore unique-key
|
|
224
|
-
// snapshots for every `(m:Message)-[:PART_OF]->(c)` that was trashed
|
|
225
|
-
// by the same cascade chain (i.e. m._trashedKeys exists + m was
|
|
226
|
-
// trashed by a `*:cascade-from-conversation` provenance). We scope by
|
|
227
|
-
// the second condition so a user-initiated single-Message trash that
|
|
228
|
-
// happens to sit inside this Conversation isn't accidentally undone.
|
|
229
|
-
const collected = await tx.run(`MATCH (c) WHERE elementId(c) = $eid
|
|
230
|
-
MATCH (m:Trashed:Message)-[:PART_OF]->(c)
|
|
231
|
-
WHERE m.trashedBy ENDS WITH ':cascade-from-conversation'
|
|
232
|
-
RETURN elementId(m) AS meid, m._trashedKeys AS keysJson`, { eid: elementId });
|
|
233
|
-
for (const rec of collected.records) {
|
|
234
|
-
const meid = rec.get("meid");
|
|
235
|
-
const keysJson = rec.get("keysJson");
|
|
236
|
-
const keys = keysJson ? JSON.parse(keysJson) : {};
|
|
237
|
-
const setClause = Object.keys(keys).length > 0
|
|
238
|
-
? ", " + Object.keys(keys).map((k) => `m.\`${k}\` = $val_${k}`).join(", ")
|
|
239
|
-
: "";
|
|
240
|
-
const msgParams = { meid };
|
|
241
|
-
for (const [k, v] of Object.entries(keys))
|
|
242
|
-
msgParams[`val_${k}`] = v;
|
|
243
|
-
await tx.run(`MATCH (m) WHERE elementId(m) = $meid
|
|
244
|
-
REMOVE m:Trashed, m.trashedAt, m.trashedBy, m.trashReason, m._trashedKeys
|
|
245
|
-
SET m.restoredAt = datetime()${setClause}`, msgParams);
|
|
246
|
-
}
|
|
247
|
-
cascadedMessageCount = collected.records.length;
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
process.stderr.write(`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}\n`);
|
|
251
|
-
if (isConversation) {
|
|
252
|
-
process.stderr.write(`[trash:cascade-restored] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount}\n`);
|
|
253
|
-
}
|
|
254
|
-
return {
|
|
255
|
-
restored: true,
|
|
256
|
-
nodeId: elementId,
|
|
257
|
-
labels: baseLabels,
|
|
258
|
-
restoredKeys: originalKeys,
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
async function emptyTrash(params) {
|
|
262
|
-
const t0 = Date.now();
|
|
263
|
-
const { session, accountId, graceDays = 30, dryRun = false, labels: labelFilter, onEmpty } = params;
|
|
264
|
-
const cutoff = new Date(Date.now() - graceDays * 24 * 60 * 60 * 1000).toISOString();
|
|
265
|
-
const labelClause = labelFilter && labelFilter.length > 0
|
|
266
|
-
? `AND ANY(l IN labels(n) WHERE l IN $labelFilter)`
|
|
267
|
-
: "";
|
|
268
|
-
const candidatesResult = await session.run(`MATCH (n:Trashed)
|
|
269
|
-
WHERE n.trashedAt < datetime($cutoff)
|
|
270
|
-
${labelClause}
|
|
271
|
-
RETURN elementId(n) AS eid,
|
|
272
|
-
labels(n) AS labels,
|
|
273
|
-
toString(n.trashedAt) AS trashedAt,
|
|
274
|
-
n.trashedBy AS trashedBy,
|
|
275
|
-
n._trashedKeys AS keysJson
|
|
276
|
-
ORDER BY n.trashedAt ASC`, { cutoff, ...(labelFilter ? { labelFilter } : {}) });
|
|
277
|
-
const candidates = candidatesResult.records.map((r) => {
|
|
278
|
-
const keysJson = r.get("keysJson");
|
|
279
|
-
return {
|
|
280
|
-
elementId: r.get("eid"),
|
|
281
|
-
labels: r.get("labels").filter((l) => l !== "Trashed"),
|
|
282
|
-
trashedAt: String(r.get("trashedAt")),
|
|
283
|
-
trashedBy: r.get("trashedBy") ?? null,
|
|
284
|
-
trashedKeys: keysJson ? JSON.parse(keysJson) : {},
|
|
285
|
-
};
|
|
286
|
-
});
|
|
287
|
-
process.stderr.write(`[trash:empty-run] accountId=${accountId} graceDays=${graceDays} dryRun=${dryRun} candidates=${candidates.length}\n`);
|
|
288
|
-
if (dryRun || candidates.length === 0) {
|
|
289
|
-
process.stderr.write(`[graph:trash:summary] accountId=${accountId} trashedNow=0 emptiedThisRun=0 graceDays=${graceDays} dryRun=${dryRun} elapsedMs=${Date.now() - t0}\n`);
|
|
290
|
-
return { graceDays, dryRun, candidates, emptied: 0 };
|
|
291
|
-
}
|
|
292
|
-
let emptied = 0;
|
|
293
|
-
for (const c of candidates) {
|
|
294
|
-
if (onEmpty) {
|
|
295
|
-
try {
|
|
296
|
-
await onEmpty(c);
|
|
297
|
-
}
|
|
298
|
-
catch (err) {
|
|
299
|
-
// Task 237 — skip the DETACH DELETE so the candidate stays
|
|
300
|
-
// eligible for the next sweep. Surfaces alongside the existing
|
|
301
|
-
// [trash:empty-run] family so an operator's grep catches both
|
|
302
|
-
// candidate listings and skip reasons in one window.
|
|
303
|
-
const id8 = c.elementId.slice(0, 8);
|
|
304
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
305
|
-
process.stderr.write(`[trash:empty-run] reason=onEmpty-failed elementId=${id8} labels=${c.labels.join(",")} message=${message}\n`);
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
await session.run(`MATCH (n) WHERE elementId(n) = $eid DETACH DELETE n`, { eid: c.elementId });
|
|
310
|
-
const ageDays = Math.floor((Date.now() - new Date(c.trashedAt).getTime()) / (24 * 60 * 60 * 1000));
|
|
311
|
-
process.stderr.write(`[trash:emptied] accountId=${accountId} elementId=${c.elementId} labels=${c.labels.join(",")} trashedAt=${c.trashedAt} ageDays=${ageDays}\n`);
|
|
312
|
-
emptied++;
|
|
313
|
-
}
|
|
314
|
-
process.stderr.write(`[graph:trash:summary] accountId=${accountId} trashedNow=0 emptiedThisRun=${emptied} graceDays=${graceDays} dryRun=${dryRun} elapsedMs=${Date.now() - t0}\n`);
|
|
315
|
-
return { graceDays, dryRun, candidates, emptied };
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Read-filter clause excluding trashed nodes for the given Cypher alias.
|
|
319
|
-
*
|
|
320
|
-
* Filters both the `:Trashed` label (primitive) and the `deletedAt`
|
|
321
|
-
* property (KnowledgeDocument soft-delete). Belt-and-braces: a row marked
|
|
322
|
-
* by either signal is excluded from reads.
|
|
323
|
-
*
|
|
324
|
-
* notTrashed("node") → "(NOT node:Trashed AND node.deletedAt IS NULL)"
|
|
325
|
-
* notTrashed("related") → "(NOT related:Trashed AND related.deletedAt IS NULL)"
|
|
326
|
-
*/
|
|
327
|
-
function notTrashed(alias) {
|
|
328
|
-
return `(NOT \`${alias}\`:Trashed AND \`${alias}\`.deletedAt IS NULL)`;
|
|
329
|
-
}
|
|
330
|
-
/** Runtime accessor for the static unique-keys map (for tests + sibling tooling). */
|
|
331
|
-
function uniqueKeysForLabels(labels) {
|
|
332
|
-
const out = new Set();
|
|
333
|
-
for (const l of labels)
|
|
334
|
-
for (const k of UNIQUE_KEYS_BY_LABEL[l] ?? [])
|
|
335
|
-
out.add(k);
|
|
336
|
-
return [...out];
|
|
337
|
-
}
|
|
338
|
-
/** Property names trashNode writes — exposed so callers can re-MERGE without colliding. */
|
|
339
|
-
exports.TRASH_METADATA_PROPS = TRASH_PROP_NAMES;
|
|
340
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|