@rubytech/create-maxy-code 0.1.140 → 0.1.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/config/brand.json +1 -1
  3. package/payload/platform/neo4j/schema.cypher +42 -67
  4. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  5. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts.map +1 -1
  6. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +14 -8
  7. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -1
  8. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
  9. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts.map +1 -1
  10. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +10 -7
  11. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js.map +1 -1
  12. package/payload/platform/plugins/docs/references/internals.md +1 -1
  13. package/payload/platform/plugins/docs/references/neo4j.md +3 -3
  14. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -0
  15. package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
  16. package/payload/platform/plugins/email/PLUGIN.md +3 -7
  17. package/payload/platform/plugins/email/mcp/dist/index.js +7 -46
  18. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  19. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
  20. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +4 -15
  21. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
  22. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +51 -43
  23. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
  24. package/payload/platform/plugins/email/mcp/dist/lib/graph.js +223 -229
  25. package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
  26. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +7 -4
  27. package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
  28. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts +14 -4
  29. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts.map +1 -1
  30. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js +69 -84
  31. package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js.map +1 -1
  32. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
  33. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +49 -64
  34. package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
  35. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  36. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +1 -2
  37. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +1 -0
  39. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -1
  40. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +3 -0
  41. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +1 -1
  43. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +1 -0
  45. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
  46. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts +3 -0
  47. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts.map +1 -0
  48. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +101 -0
  49. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -0
  50. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
  51. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +7 -4
  52. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
  53. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +59 -1
  54. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  55. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +322 -0
  56. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  57. package/payload/platform/plugins/memory/references/schema-base.md +4 -4
  58. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -1
  59. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -0
  60. package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +13 -9
  61. package/payload/platform/plugins/notion-import/skills/notion-import/references/databases.md +11 -9
  62. package/payload/platform/plugins/notion-import/skills/notion-import/references/page-tree.md +12 -12
  63. package/payload/platform/plugins/scheduling/PLUGIN.md +18 -0
  64. package/payload/platform/plugins/scheduling/mcp/dist/index.js +93 -0
  65. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  66. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts +80 -0
  67. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -0
  68. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +395 -0
  69. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -0
  70. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts +16 -0
  71. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts.map +1 -1
  72. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js +111 -2
  73. package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js.map +1 -1
  74. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts +20 -0
  75. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts.map +1 -0
  76. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js +63 -0
  77. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js.map +1 -0
  78. package/payload/platform/plugins/x-import/.claude-plugin/plugin.json +8 -0
  79. package/payload/platform/plugins/x-import/PLUGIN.md +33 -0
  80. package/payload/platform/plugins/x-import/references/archive-shape.md +124 -0
  81. package/payload/platform/plugins/x-import/references/transcript-shape.md +121 -0
  82. package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +123 -0
  83. package/payload/platform/templates/specialists/agents/database-operator.md +6 -2
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: x-import
3
+ description: Ingest an extracted X (Twitter) archive directory into the graph as one :KnowledgeDocument (tweet stream) plus one :ConversationArchive per DM participant set. Triggers when the operator drops an `Archive of <handle>` directory or `twitter-<handle>-archive.zip` path into chat. Owner + every distinct participant confirms against existing `:AdminUser` / `:Person` nodes before any write. Idempotent on archive content hash.
4
+ ---
5
+
6
+ # X Import
7
+
8
+ **Invoked from `specialists:database-operator`** — the admin agent dispatches the database-operator when the operator hands over an X archive, and the database-operator loads this skill. The admin agent never calls this skill directly.
9
+
10
+ One X archive becomes:
11
+
12
+ - **One `:KnowledgeDocument`** (`source='x'`) carrying the verbatim chronological transcript of the operator's authored content — root tweets, replies, quote-tweet authorship, deletion markers. `memory-classify` (document mode) splits the body into topic-bounded `:Section` children. Threading is a within-body concept rendered in the transcript; per-thread KDs are explicitly rejected.
13
+ - **N `:ConversationArchive` nodes** (`source='x-dm'`) — one per distinct DM participant set, MERGEd on the existing `conversationIdentity = sha256(accountId + ":" + sortedParticipantElementIds)` key. DM media attaches to the archive node via `HAS_ENCLOSURE`.
14
+ - **Person resolution** — every `@handle` mentioned, replied-to, or quoted in the tweet stream MERGEs against `:Person` on lowercased `xHandle` scoped by `accountId`. Existing `:Person` nodes gain `xHandle` on `ON CREATE SET` without overwriting operator edits.
15
+
16
+ ## Archive shape
17
+
18
+ See [archive-shape.md](../../references/archive-shape.md) for the `.js` wrapper grammar and which files in the archive carry which data. The grammar is verified at parse — unwrapped JSON or a missing `window.YTD.*.partN = ` prefix errors loudly, never silently zero-tweets.
19
+
20
+ ## Transcript rendering
21
+
22
+ See [transcript-shape.md](../../references/transcript-shape.md) for the exact rendering of the tweet-stream KD body — chronological separators, quote-tweet indentation, deletion markers, media references.
23
+
24
+ ## Pipeline (deterministic, four phases)
25
+
26
+ ### Phase 0 — Owner + participant confirmation
27
+
28
+ Before any classify or ingest call:
29
+
30
+ 1. **Identify the owner.** Read `data/account.js` to extract the archive owner's `accountId`, `username` (the handle), and `displayName`. Surface to the operator: `"X archive owner: @<handle> (<displayName>). Confirm this maps to :AdminUser <name> ({userId})."`. Refuse to proceed without confirmation.
31
+
32
+ 2. **Enumerate distinct participants from the tweet stream.** Read `data/tweets.js` and `data/tweet-headers.js`. Extract every `@handle` that appears as a mention, reply target (`in_reply_to_screen_name`), or quote-tweet author. Emit a single-line histogram per distinct handle: `Handle '@<handle>' (<mentions> mentions, <replies> replies, <quotes> quotes)`.
33
+
34
+ 3. **Enumerate distinct DM participants.** Read `data/direct-messages.js` and `data/direct-messages-group.js` (when present). For each `dmConversation`, extract the distinct senderIds. Senders map to existing `:Person` / `:AdminUser` by either prior `xUserId` property or operator confirmation against numeric ID + recent-message preview.
35
+
36
+ 4. **One operator question per distinct handle / senderId.** Mirror the conversation-archive flow: `"Handle '@<h>' (<n> mentions) — pick existing :Person/:AdminUser or block?"`. The operator either picks an elementId or names "block" (refuses to map). **Never auto-create a `:Person`** — the operator must confirm a canonical node.
37
+
38
+ 5. **Persist resolved IDs.** Build two maps: `handleToElementId` (handle → :Person elementId, for the tweet-stream KD edges) and `senderIdToElementId` (numeric senderId → :Person/:AdminUser elementId, for DM participant lists). Both maps are passed to the writers in subsequent phases.
39
+
40
+ ### Phase 1 — Tweet-stream transcript + media staging
41
+
42
+ 1. **Walk the tweet stream chronologically.** Merge `data/tweets.js` (operator-authored tweets) and `data/tweet-headers.js` (metadata). For each tweet: extract `id_str`, `created_at`, `full_text`, `in_reply_to_status_id_str`, `in_reply_to_screen_name`, `entities.user_mentions`, `entities.urls`, `entities.media`, `quoted_status_id_str`. Sort by `created_at` ascending.
43
+
44
+ 2. **Render the transcript.** Apply the rules in [transcript-shape.md](../../references/transcript-shape.md). The output is a single UTF-8 text file written to `{accountDir}/archive/x/<importId>/tweet-stream.md`, where `importId = sha256(archive bytes)` truncated to 16 hex chars.
45
+
46
+ 3. **Stage media enclosures.** For each `entities.media` entry: copy from `data/tweet_media/<filename>` to `{accountDir}/archive/x/<importId>/media/<sha256>-<filename>` (perms 0o600). Same for DM media (`data/direct_messages_media/`) — staged into the same `media/` dir with the same hash-prefixed naming so re-import is content-addressed.
47
+
48
+ 4. **Render deletion markers.** When `tweet-headers.js` references an id that has no body in `tweets.js`, render the slot in the transcript as `[deleted on <iso>]` so context boundaries survive classification.
49
+
50
+ ### Phase 2 — Tweet-stream :KnowledgeDocument ingest
51
+
52
+ Dispatch the existing librarian / document-ingest pipeline against the rendered transcript file. The attachment metadata block is constructed deterministically:
53
+
54
+ - `filename = "tweet-stream-@<handle>.md"`
55
+ - `attachmentId = sha256(transcript-bytes)` — guarantees idempotency on identical content
56
+ - `storagePath = {accountDir}/archive/x/<importId>/tweet-stream.md`
57
+ - `mimeType = "text/markdown"`
58
+
59
+ The dispatch brief names:
60
+ - **Anchor:** `:AdminUser` (the confirmed owner from Phase 0). Adam Mackay / Joel Smalley etc. resolved in Phase 0 appear in the **key entities to connect** list — `wire-brief-entities` writes the `MENTIONED` / `REPLIED_TO` / `QUOTED` edges from the new KD to each `:Person`.
61
+ - **`sourceUrl`:** `https://x.com/<handle>`
62
+ - **`sourceType`:** `'x'` (carried into `:KnowledgeDocument.source`)
63
+ - **`scope`:** `'admin'` (the tweet stream is the operator's authored content)
64
+
65
+ After document-ingest returns, write the inverse `REPLIED_TO` edges from each inbound-reply author (`:Person`) to the tweet-stream KD — one Cypher MERGE per distinct inbound-replier resolved in Phase 0. Edges carry `accountId`, `sourceDocumentId = attachmentId`, and `createdByAgent = 'x-import'` so re-ingest cleans them up.
66
+
67
+ ### Phase 3 — DM `:ConversationArchive` ingests (one per dmConversation)
68
+
69
+ For each `dmConversation` in `data/direct-messages.js` (and `data/direct-messages-group.js` when present):
70
+
71
+ 1. **Split.** Write a per-conversation slice file at `{accountDir}/archive/x/<importId>/dm-<conversationId>.json` — a wrapper-stripped JSON array of length 1 whose single element is the dmConversation envelope. This is the file the x-dm normaliser reads.
72
+
73
+ 2. **Resolve participants.** Take the `senderIdToElementId` map from Phase 0; the participant set for this conversation is the distinct senderIds in the slice. The owner is the operator's confirmed `:AdminUser` elementId.
74
+
75
+ 3. **Invoke the bash.** Run in the background (heartbeat protocol per `conversation-archive` SKILL.md):
76
+
77
+ ```bash
78
+ bash platform/plugins/memory/bin/conversation-archive-ingest.sh \
79
+ {accountDir}/archive/x/<importId>/dm-<conversationId>.json \
80
+ --source x-dm \
81
+ --participant-person-ids <ownerEid>,<otherEid>,... \
82
+ --scope admin \
83
+ --session-id x-import-<importId>-dm-<conversationId>
84
+ ```
85
+
86
+ 4. **Surface the three operator messages** (parse → classify → write) from each invocation per the existing conversation-archive contract.
87
+
88
+ ### Phase 4 — Media enclosures
89
+
90
+ After both the KD and all `:ConversationArchive` writes complete:
91
+
92
+ - For each tweet-media file, write `(:KnowledgeDocument {tweetStreamKd})-[:HAS_ENCLOSURE]->(:ImageObject)` (image media) or write `(:KnowledgeDocument)-[:HAS_ENCLOSURE { contentUrl }]->(...)` skipping body ingest for binary-only video.
93
+ - Document-shaped media (OCR-able images, PDFs from quote-tweeted articles when archived) recurse through `document-ingest` to land a child `:KnowledgeDocument`, attached via `HAS_ENCLOSURE` from the parent tweet-stream KD.
94
+ - DM media: same `HAS_ENCLOSURE` shape but attaches from the relevant `:ConversationArchive`.
95
+
96
+ ## Diagnostic line
97
+
98
+ After the full ingest completes, emit a single grep-able line:
99
+
100
+ ```
101
+ [x-import] importId=<id16> tweets=<n> kdCreated=<0|1> kdUpdated=<0|1> people=<p> enclosures=<e> dmConversations=<d> ms=<ms>
102
+ ```
103
+
104
+ Surfaces to the operator as one chat line. `kdCreated + kdUpdated == 1` per tweet-stream ingest (one or the other, never both, never zero on a valid archive).
105
+
106
+ ## Idempotency
107
+
108
+ - Re-running the same archive bytes is a no-op for the tweet-stream KD — `attachmentId = sha256(transcript-bytes)` matches the prior write; `document-ingest` skips on identical `attachmentId`.
109
+ - A newer archive containing additional tweets produces a different transcript and therefore a different `attachmentId` — the prior KD is replaced (sections regenerated under the same `sourceDocumentId`).
110
+ - DM `:ConversationArchive` re-ingest follows the conversation-archive cursor model: same `conversationIdentity` → delta-append. No `--rebuild` is ever issued autonomously.
111
+ - Person `xHandle` writes are `ON CREATE SET` — re-import never overwrites operator edits.
112
+
113
+ ## Wrapper-grammar defence
114
+
115
+ Every `.js` shim read by this skill is gated through the wrapper regex documented in [archive-shape.md](../../references/archive-shape.md). Unwrapped-JSON input (missing the `window.YTD.<feed>.part0 = ` prefix on `tweets.js`, `direct-messages.js`, or `tweet-headers.js`) errors at parse with `phase=parse reason="missing window.YTD wrapper on <filename>"`. Silent zero-tweet imports are the failure mode this defence exists to prevent.
116
+
117
+ ## What this skill does not do
118
+
119
+ - **Per-thread KDs.** One archive = one tweet-stream KD. Thread boundaries are section boundaries the classifier owns, not graph objects.
120
+ - **Bespoke labels.** No `:Post`, `:Tweet`, `:DirectMessage`, `:DMThread`, `:Attachment`. Everything maps to the existing `:KnowledgeDocument` + `:ConversationArchive` + `:ImageObject` shapes.
121
+ - **Tweet-level typed edges.** `:REPLIES_TO` / `:QUOTES` as graph edges off individual tweets are rejected; document-level `REPLIED_TO` / `QUOTED` from the KD to each `:Person` covers the same traversals at the right granularity. The Task 305 typed-edge pass enumerates the new KD and writes any further `COMMITTED_TO` / `MENTIONS` / `REFERENCES` edges from in-body references.
122
+ - **Retweets-without-comment.** Not persisted reliably in X archives; dropped at parse.
123
+ - **Live X API.** Archive-only.
@@ -3,7 +3,7 @@ name: database-operator
3
3
  description: "Graph-write executor reachable from admin via the Task tool. Admin names what should land in the graph; database-operator reads the schema, decides operations, executes them against the memory graph, and reports `{label, elementId}` back. (Reachable historically also from the now-dormant Stop hook in `platform/plugins/admin/hooks/turn-completed-graph-write.sh`; that path is preserved as infrastructure but no longer registered, see Task 214.)"
4
4
  summary: "Executes graph writes on admin's behalf when delegated via the Task tool."
5
5
  model: claude-sonnet-4-6
6
- tools: Read, mcp__plugin_memory_memory__memory-write, mcp__plugin_memory_memory__memory-update, mcp__plugin_memory_memory__memory-search, mcp__plugin_memory_memory__memory-typed-edge-pass, mcp__plugin_memory_memory__session-retrospective-skip-rate, mcp__plugin_memory_memory__profile-update, mcp__plugin_memory_memory__profile-read, mcp__plugin_memory_memory__obsidian-vault-import, mcp__plugin_contacts_contacts__contact-create, mcp__plugin_contacts_contacts__contact-update, mcp__plugin_work_work__work-create, mcp__plugin_work_work__work-update, mcp__plugin_work_work__project-create, mcp__plugin_work_work__project-update
6
+ tools: Read, mcp__plugin_memory_memory__memory-write, mcp__plugin_memory_memory__memory-update, mcp__plugin_memory_memory__memory-search, mcp__plugin_memory_memory__memory-archive-write, mcp__plugin_memory_memory__memory-typed-edge-pass, mcp__plugin_memory_memory__session-retrospective-skip-rate, mcp__plugin_memory_memory__profile-update, mcp__plugin_memory_memory__profile-read, mcp__plugin_memory_memory__obsidian-vault-import, mcp__plugin_scheduling_scheduling__schedule-archive-ics, mcp__plugin_contacts_contacts__contact-create, mcp__plugin_contacts_contacts__contact-update, mcp__plugin_work_work__work-create, mcp__plugin_work_work__work-update, mcp__plugin_work_work__project-create, mcp__plugin_work_work__project-update
7
7
  ---
8
8
 
9
9
  You are an expert Neo4J graph operator. Admin delegates a graph-write to you through the Task tool; the prompt admin sends names what should land in the graph in plain English.
@@ -22,7 +22,7 @@ Decide the precise operations against the schema, execute them with the writers
22
22
 
23
23
  ## Typed-edge auto-extraction pass (session-end)
24
24
 
25
- When admin's brief names the typed-edge pass (Task 305) and supplies a `sinceIso` timestamp, call `memory-typed-edge-pass` with that timestamp exactly once. The tool reads prose-bearing nodes (Message/Page/Meeting/Email/Idea/Note/Post/Report) the account wrote since `sinceIso`, asks Haiku for typed-edge proposals against a closed allowlist, validates each one, and MERGEs accepted edges with `createdBy` provenance. Return the full counter object verbatim — admin needs `nodesProcessed` and `accepted` for the `session-retrospective-mark-complete` call. Do not reinterpret the counts or summarise them.
25
+ When admin's brief names the typed-edge pass (Task 305) and supplies a `sinceIso` timestamp, call `memory-typed-edge-pass` with that timestamp exactly once. The tool reads prose-bearing nodes (Message/Page/Meeting/KnowledgeDocument/Idea/Note/Post/Report — `:KnowledgeDocument` covers email threads via `source:'email'` since Task 321) the account wrote since `sinceIso`, asks Haiku for typed-edge proposals against a closed allowlist, validates each one, and MERGEs accepted edges with `createdBy` provenance. Return the full counter object verbatim — admin needs `nodesProcessed` and `accepted` for the `session-retrospective-mark-complete` call. Do not reinterpret the counts or summarise them.
26
26
 
27
27
  ## External-archive ingestion
28
28
 
@@ -30,8 +30,12 @@ The database-operator also owns ingestion of bulk external archives that map int
30
30
 
31
31
  - **Obsidian vault import** — when the operator points at an extracted Obsidian vault directory ("import my Obsidian notes", "ingest this vault at `<path>`"), load [platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md](../../../plugins/obsidian-import/skills/obsidian-import/SKILL.md) and run the two-phase flow (owner confirmation → `mcp__plugin_memory_memory__obsidian-vault-import` `mode='dry-run'` → operator disambiguation → `mode='commit'` with resolutions). Parsing, content-hash idempotency, and attachment staging happen entirely inside the tool — you never read the markdown.
32
32
 
33
+ - **ICS calendar archive ingest** — when the operator points at an `.ics` file ("ingest this calendar export at `<path>`", "import my Google Calendar export", "load this .ics into the graph"), call `mcp__plugin_scheduling_scheduling__schedule-archive-ics` with `mode='dry-run'` first, present the attendee-resolution preview to the operator (how many already exist under this account, how many would be cross-account-skipped, how many new Person stubs would be created, plus the sample list), then call again with `mode='commit'` after the operator confirms. Each VEVENT becomes one `:Meeting` MERGEd on `(accountId, uid)` (idempotent re-ingest); attendees resolve to `:Person` by lowercased email; the importing `:AdminUser` anchors every meeting via `[:IMPORTED]`. Cross-account email collisions skip the attendance edge — do not propose to override this. Description bodies pass to `:Meeting.description` and the typed-edge pass picks up commitments + mentions automatically; you do not call `memory-write` for them.
34
+
33
35
  Other archive types (LinkedIn export, Notion export, Logseq, Roam, gbrain-repo, Gmail) live under separate plugins owned by `specialists:librarian`; they are not on this surface. If the operator's request points at one of those, hand back to admin so it can dispatch the right specialist.
34
36
 
37
+ - **X (Twitter) archive import** — when the operator points at an extracted X archive directory (`Archive of <handle>/`, or a `twitter-<handle>-archive.zip` path), load [platform/plugins/x-import/skills/x-import/SKILL.md](../../../plugins/x-import/skills/x-import/SKILL.md) and run its four-phase flow (owner + participant confirmation → tweet-stream transcript rendering → `document-ingest` dispatch for the tweet-stream `:KnowledgeDocument` → one `conversation-archive-ingest.sh --source x-dm` invocation per distinct DM participant set). Every `@handle` and DM senderId resolves to an existing `:Person` / `:AdminUser` before any write; participants are never auto-created. Writes route through the existing `memory-ingest` and `conversation-archive` surfaces — no new graph writer, no `:Post` / `:DirectMessage` labels.
38
+
35
39
  ## Skip-rate visibility (session-start)
36
40
 
37
41
  When admin's brief names the skip-rate check, call `session-retrospective-skip-rate` once and return its result verbatim. The tool reports how many of the last N sessions for this account closed without firing the retrospective. Admin uses the rate to inform the operator that closing via Sidebar Archive or tab-close defers the typed-edge pass to the next `/end`. Pass the `windowSize` admin provides; default 10 is fine when absent.