@rubytech/create-sitedesk-code 0.1.524 → 0.1.525
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/package.json +1 -1
- package/payload/platform/plugins/admin/skills/superpowers-sprint/SKILL.md +26 -0
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/memory/PLUGIN.md +10 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +5 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.js +141 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +6 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/temporal-type-preserve.d.ts +45 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/temporal-type-preserve.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/temporal-type-preserve.js +122 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/temporal-type-preserve.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js +26 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-type-preserve.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-type-preserve.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-type-preserve.test.js +201 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-type-preserve.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +89 -33
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +6 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-retype.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-retype.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-retype.test.js +148 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-retype.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +83 -6
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +90 -5
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +111 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +38 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +116 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +81 -8
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-agent.test.js +39 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-agent.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/scripts/__tests__/check-canonical-tool-names.test.sh +162 -0
- package/payload/platform/scripts/__tests__/check-no-task-id-leaks.test.sh +53 -0
- package/payload/platform/scripts/__tests__/task-id-citation.test.sh +72 -0
- package/payload/platform/scripts/check-canonical-tool-names.mjs +36 -4
- package/payload/platform/scripts/check-no-task-id-leaks.mjs +80 -62
- package/payload/platform/scripts/lib/canonical-tool-names.mjs +130 -26
- package/payload/platform/scripts/lib/task-id-citation.mjs +67 -0
- package/payload/platform/.docs/search-surface-contract.md +0 -58
- package/payload/platform/docs/superpowers/plans/2026-06-02-task-610-follower-202-retry.md +0 -372
- package/payload/platform/docs/superpowers/plans/2026-06-04-public-agent-knowledge-delivery.md +0 -230
- package/payload/platform/docs/superpowers/plans/2026-06-23-account-filesystem-schema.md +0 -544
- package/payload/platform/docs/superpowers/plans/2026-07-11-task-1557-operator-on-behalf-preference-attribution.md +0 -542
- package/payload/platform/docs/superpowers/plans/2026-07-13-account-schema-ontology-projection.md +0 -547
- package/payload/platform/docs/superpowers/plans/2026-07-14-graph-top-level-labels-ontology-single-source.md +0 -458
- package/payload/platform/docs/superpowers/plans/2026-07-17-task-1736-retire-mcp-stderr-tee.md +0 -397
- package/payload/platform/docs/superpowers/plans/2026-07-18-graph-native-ledger.md +0 -807
- package/payload/platform/docs/superpowers/plans/2026-07-18-ledger-write-path-fix.md +0 -109
- package/payload/platform/docs/superpowers/plans/2026-07-20-storage-pages-create.md +0 -82
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1704-data-portal-standing-audit.md +0 -673
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1789-reseat-channel-row-fork.md +0 -1244
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1818-loop-gate-app-routes.md +0 -462
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1819-top-level-label-allowlist.md +0 -321
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1829-platform-ui-typecheck.md +0 -830
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1831-data-portal-class-derived-allowlist.md +0 -2177
- package/payload/platform/docs/superpowers/plans/2026-07-21-graph-caption-resolver.md +0 -124
- package/payload/platform/docs/superpowers/plans/2026-07-21-task-1877-bash-schema-enforcement.md +0 -107
- package/payload/platform/docs/superpowers/plans/2026-07-21-task-1887-reconcile-allowed-top-level.md +0 -205
- package/payload/platform/docs/superpowers/plans/2026-07-22-task-1899-reconcile-report-only.md +0 -748
- package/payload/platform/docs/superpowers/plans/2026-07-22-task-1910-two-way-portal-exchange.md +0 -1716
- package/payload/platform/docs/superpowers/plans/2026-07-23-task-1930-adherence-enforcement.md +0 -422
- package/payload/platform/docs/superpowers/plans/2026-07-24-task-1942-subaccount-switcher-brand-head.md +0 -327
- package/payload/platform/docs/superpowers/plans/2026-07-25-task-1974-uploads-intake-inbox.md +0 -235
- package/payload/platform/docs/superpowers/plans/2026-07-25-task-1976-intra-folder-hygiene.md +0 -215
- package/payload/platform/docs/superpowers/plans/2026-07-26-task-1902-account-owned-entry-declarations.md +0 -555
- package/payload/platform/docs/superpowers/plans/2026-07-26-task-1926-portal-push-concurrency-guard.md +0 -482
- package/payload/platform/docs/superpowers/plans/2026-07-26-task-2023-sidebar-sessions-async-reads.md +0 -394
- package/payload/platform/docs/superpowers/plans/2026-07-27-task-2016-disabled-agent-routing.md +0 -624
- package/payload/platform/docs/superpowers/plans/2026-07-27-task-2028-declared-file-write-deny.md +0 -303
- package/payload/platform/docs/superpowers/plans/2026-07-27-task-2052-account-machinery-write-fence.md +0 -250
- package/payload/platform/docs/superpowers/plans/2026-07-28-task-2097-email-signature-set.md +0 -65
- package/payload/platform/docs/superpowers/specs/2026-06-02-task-610-follower-202-retry-design.md +0 -116
- package/payload/platform/docs/superpowers/specs/2026-06-23-account-filesystem-schema-design.md +0 -170
- package/payload/platform/docs/superpowers/specs/2026-07-11-task-1557-operator-on-behalf-preference-attribution-design.md +0 -90
- package/payload/platform/docs/superpowers/specs/2026-07-13-account-schema-ontology-projection-design.md +0 -178
- package/payload/platform/docs/superpowers/specs/2026-07-14-graph-top-level-labels-ontology-single-source-design.md +0 -119
- package/payload/platform/docs/superpowers/specs/2026-07-17-task-1736-retire-mcp-stderr-tee-design.md +0 -128
- package/payload/platform/docs/superpowers/specs/2026-07-18-graph-native-ledger-design.md +0 -241
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1704-data-portal-standing-audit-design.md +0 -177
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1789-reseat-channel-row-fork-design.md +0 -201
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1818-loop-gate-app-routes-design.md +0 -217
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1819-top-level-label-allowlist-design.md +0 -80
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1820-cpu-triage-admin-tools-design.md +0 -97
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1829-platform-ui-typecheck-design.md +0 -163
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1831-data-portal-class-derived-allowlist-design.md +0 -163
- package/payload/platform/docs/superpowers/specs/2026-07-22-task-1899-reconcile-report-only-design.md +0 -121
- package/payload/platform/docs/superpowers/specs/2026-07-22-task-1910-two-way-portal-exchange-design.md +0 -103
- package/payload/platform/docs/superpowers/specs/2026-07-23-task-1930-adherence-enforcement-design.md +0 -81
- package/payload/platform/docs/superpowers/specs/2026-07-24-task-1942-subaccount-switcher-brand-head-design.md +0 -35
- package/payload/platform/docs/superpowers/specs/2026-07-26-task-1902-account-owned-entry-declarations-design.md +0 -232
- package/payload/platform/docs/superpowers/specs/2026-07-26-task-1926-portal-push-concurrency-guard-design.md +0 -200
- package/payload/platform/docs/superpowers/specs/2026-07-26-task-2014-ui-suite-nondeterminism-design.md +0 -169
- package/payload/platform/docs/superpowers/specs/2026-07-27-task-2016-disabled-agent-routing-design.md +0 -139
- package/payload/platform/docs/superpowers/specs/2026-07-27-task-2028-declared-file-write-deny-design.md +0 -127
- package/payload/platform/docs/superpowers/specs/2026-07-27-task-2052-account-machinery-write-fence-design.md +0 -150
- package/payload/platform/docs/superpowers/specs/2026-07-28-task-2097-email-signature-set-design.md +0 -155
package/package.json
CHANGED
|
@@ -11,6 +11,23 @@ A structured workflow for executing development work — features, bug fixes, re
|
|
|
11
11
|
|
|
12
12
|
This skill is the maxy-code counterpart to `sprint`. The phase chain is identical in spirit; the difference is the skill at each phase. If both `gstack` and superpowers are installed and the project is set up for it, prefer `sprint` — its plan reviews are richer. Use this skill when `gstack` is not available.
|
|
13
13
|
|
|
14
|
+
## Execution model: inline only, never subagents
|
|
15
|
+
|
|
16
|
+
Every phase of this sprint runs in the current session, in the main agent's own context. No phase dispatches a subagent, and no phase delegates work to the Agent tool, `superpowers:subagent-driven-development`, or `superpowers:dispatching-parallel-agents`.
|
|
17
|
+
|
|
18
|
+
Several of the chained superpowers skills offer or recommend a subagent path. In this sprint, take the inline path at each of them:
|
|
19
|
+
|
|
20
|
+
| Chained skill | Its subagent offer | What this sprint does |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `superpowers:brainstorming` | dispatches a spec document reviewer subagent | review the spec yourself, against the same template |
|
|
23
|
+
| `superpowers:writing-plans` | dispatches a plan document reviewer subagent, and offers "Subagent-Driven (recommended)" as the implementation mode | review the plan yourself; choose the `superpowers:executing-plans` mode, never subagent-driven |
|
|
24
|
+
| `superpowers:executing-plans` | tells you to switch to `superpowers:subagent-driven-development` where subagents exist | ignore that instruction and stay in `executing-plans` |
|
|
25
|
+
| `superpowers:requesting-code-review` | dispatches a `general-purpose` code reviewer subagent | apply the reviewer template to the diff yourself, in this session |
|
|
26
|
+
|
|
27
|
+
A review done inline still uses the chained skill's reviewer template verbatim — the checklist is what makes the review real, not the isolation. The cost of inline is that the reviewer shares the sprint's context and therefore its assumptions; the operator accepts that in exchange for a single visible transcript.
|
|
28
|
+
|
|
29
|
+
Dispatching a subagent from any phase is a defect, not an optimisation.
|
|
30
|
+
|
|
14
31
|
## Output discipline (applies to every emission in this skill)
|
|
15
32
|
|
|
16
33
|
Every message the sprint writes — plan summaries, change logs, status tables, the final summary — is written `/plainly`. That means:
|
|
@@ -54,18 +71,24 @@ Read the task file or operator brief first, then enter brainstorming with what y
|
|
|
54
71
|
|
|
55
72
|
If the operator hands over a fully-formed plan that is already broken into specific files and behaviours, brainstorming can be a fast confirmation rather than an open exploration — but it still runs, because skipping it is the failure mode the phase exists to prevent.
|
|
56
73
|
|
|
74
|
+
When the skill reaches its spec document review, run that review inline against `spec-document-reviewer-prompt.md`. Do not dispatch the reviewer subagent.
|
|
75
|
+
|
|
57
76
|
### Phase 2: Plan — `superpowers:writing-plans`
|
|
58
77
|
|
|
59
78
|
Invoke `superpowers:writing-plans` against the brainstorm output. The skill produces a single written plan: the files to touch, the behaviours to add or change, the edge cases, the test coverage, the deployment story. This is the artefact Phase 6 (Plan Conformity) checks the implementation against.
|
|
60
79
|
|
|
61
80
|
This is a deliberate downgrade from `sprint`'s separate CEO and Eng reviews — multi-approach architecture review is out of scope for the superpowers chain. One reviewed plan is the baseline.
|
|
62
81
|
|
|
82
|
+
Two of the skill's steps offer a subagent; take neither. Review the finished plan inline against `plan-document-reviewer-prompt.md`. When the skill asks which implementation mode to use, choose `superpowers:executing-plans`, never "Subagent-Driven".
|
|
83
|
+
|
|
63
84
|
Present the final plan to the operator and get explicit confirmation before writing any production code.
|
|
64
85
|
|
|
65
86
|
### Phase 3: Implement — `superpowers:executing-plans` + `superpowers:test-driven-development`
|
|
66
87
|
|
|
67
88
|
Invoke `superpowers:executing-plans` to drive execution against the Phase 2 plan. Within each step, follow `superpowers:test-driven-development` — RED-GREEN-REFACTOR for every behaviour change.
|
|
68
89
|
|
|
90
|
+
`superpowers:executing-plans` opens by telling you to switch to `superpowers:subagent-driven-development` when subagents are available. Ignore that line; this sprint runs every task inline in the current session.
|
|
91
|
+
|
|
69
92
|
Tests are ephemeral: design and run them to prove the implementation works during the sprint, then discard them. They are not committed to the repository unless the project's own test suite already lives in the tree and the new behaviour belongs in it. Their purpose is to enforce thinking through behaviour before writing production code, not to build a permanent regression suite.
|
|
70
93
|
|
|
71
94
|
- **Test first.** Write a failing test for each behaviour before implementing it. Watch it fail. Write minimal code to pass. Refactor.
|
|
@@ -94,6 +117,8 @@ If verification fails, return to Phase 3.
|
|
|
94
117
|
|
|
95
118
|
Invoke `superpowers:requesting-code-review` to frame the review request. Then run `code-review:code-review` against the sprint's diff. Process the response through `superpowers:receiving-code-review`, which gates whether each finding is accepted, contested, or filed as follow-up.
|
|
96
119
|
|
|
120
|
+
`superpowers:requesting-code-review` dispatches a `general-purpose` reviewer subagent. Do not dispatch it. Fill its `code-reviewer.md` template with the sprint's context and diff, then work through it inline as the reviewer. `code-review:code-review` likewise runs in this session against the diff, not as a delegated agent.
|
|
121
|
+
|
|
97
122
|
Findings that are accepted and trivial are fixed before proceeding. Findings that are accepted but out-of-scope for this sprint become new `.tasks/NNN-*.md` files (the same deferral rule as Phase 6 — prose deferrals are banned). Findings that are contested get a one-line rebuttal in the debrief.
|
|
98
123
|
|
|
99
124
|
### Phase 6: Land
|
|
@@ -355,6 +380,7 @@ Session: <session-id>
|
|
|
355
380
|
|
|
356
381
|
## Principles
|
|
357
382
|
|
|
383
|
+
- **Inline, always.** Every phase runs in the current session. No subagents, no parallel agent dispatch, no delegated reviewers, whatever the chained skills recommend.
|
|
358
384
|
- **Ship complete.** A sprint is not done until the debrief and the final-status block are delivered. Code without documentation is unfinished work.
|
|
359
385
|
- **Explain the why.** Every change has a reason. "Refactored for clarity" is not a reason. "Extracted to avoid duplicate route derivation across WhatsApp and iMessage" is.
|
|
360
386
|
- **Operator perspective.** Testing instructions are written for the person running the product. If the operator is non-technical, instructions are UI-based.
|
|
@@ -9,6 +9,12 @@ Invoked by the admin agent directly.
|
|
|
9
9
|
|
|
10
10
|
This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
|
|
11
11
|
|
|
12
|
+
## 2026-07-29 (0.1.525)
|
|
13
|
+
|
|
14
|
+
- A repeating routine whose start date had already gone by now runs on its next due occurrence instead of sitting silent forever. There is also a standing check that tells you when a routine has a start date that never fired.
|
|
15
|
+
- Saving a memory no longer rewrites the date and time on a meeting into plain text, so meeting times stay comparable and sortable afterwards.
|
|
16
|
+
- Internal engineering documents are no longer included in what gets installed on a customer device, and the check that scans installed text now reads exactly what ships rather than an out-of-date copy of the list.
|
|
17
|
+
|
|
12
18
|
## 2026-07-29 (0.1.524)
|
|
13
19
|
|
|
14
20
|
- Routines are properly editable now. You can pick where a routine sends its result from the routine window, which previously could not be set at all, so the routines that ship with the platform were impossible to make work from the dashboard. Stopping a routine from chat also no longer means cancelling it outright.
|
|
@@ -239,6 +239,16 @@ The memory tools whose Neo4j read/write re-scopes on the resolved account accept
|
|
|
239
239
|
|
|
240
240
|
Tools that do **not** take `targetAccountId` fall into three groups. **Not account-scoped:** `image-fetch` fetches image bytes by URL; `graph-prune-denylist-add/remove/list` mutate a brand-global deny-list; `memory-ingest-extract` stages a temp file — none read or write a sub-account subgraph. **Bound to the caller's own live session:** `session-compact` compacts the caller's `SESSION_ID` Conversation, which belongs to the house account the operator sits in — re-scoping `accountId` to a sub-account matches nothing and "compact a sub-account's live session" has no referent. **Scheduled, not interactive:** the dream-cycle **cron** (`lib/dream-cycle/*`) takes its account from the scheduler context, not a tool argument; only the interactive `memory-dream-run` tool is house-targetable. These tools keep their own-account no-account guard.
|
|
241
241
|
|
|
242
|
+
## `memory-update` cannot change a property's Neo4j type
|
|
243
|
+
|
|
244
|
+
An update reads the node's own `valueType()` for every key it is about to write. Keys the node already holds as a temporal type (`DATE`, `ZONED DATETIME`, `LOCAL DATETIME`, `ZONED TIME`, `LOCAL TIME`, `DURATION`) are rebuilt with the matching Cypher constructor; everything else rides in the `n += $props` bag as before. `updatedAt` follows the same rule rather than one fixed type — `memory-write` stamps it as an ISO string and the graph tooltip reads it as one, while `:Meeting` nodes hold it as a `ZONED DATETIME`.
|
|
245
|
+
|
|
246
|
+
Each temporal value is vetted by Neo4j's own parser in a read-only probe **before** the update statement runs, so a value the constructor rejects aborts the whole update and leaves every property untouched, including the ones that would have succeeded. Vetting against the database rather than a JS reimplementation matters in both directions: a hand-rolled check would be stricter than Neo4j and reject values it accepts. The refusal is `Update blocked (type-preserving): <key> holds <type> and "<value>" is not a valid <type>`, logged as `reason=type-preserving` — its own slug, not the write-gate's, so a type refusal and a denylist refusal are never read as one thing. Only a `Neo.ClientError` counts as a verdict on the value; a disconnect or a timeout propagates unchanged rather than accusing a timestamp that was correct.
|
|
247
|
+
|
|
248
|
+
Setting a property to `null` still removes it. Removal changes no type, so it is outside this rule — refusing it would take away the only way to clear a nullable temporal property such as `:Meeting.endsAt`.
|
|
249
|
+
|
|
250
|
+
This exists because `SET n += $props` wrote every value verbatim. An agent updating a `:Meeting` with an ISO string replaced its `ZONED DATETIME` `startsAt` with a `STRING`, and a `STRING`-to-`DATETIME` comparison in Neo4j is NULL rather than false — so every calendar reader dropped the row with no error and no log line, and one account's booking page published a busy afternoon as open time for two days. `memory-update-by-name` delegates its whole write to `memory-update` and inherits this; it owns only the lookup.
|
|
251
|
+
|
|
242
252
|
## Graph Hygiene
|
|
243
253
|
|
|
244
254
|
Graph hygiene is **agent-directed, case by case** — no autonomous rule engine, no cron. The Neo4j graph degrades into a landfill if pollution from prior agent errors (wrong-account hostnames, fabricated identifiers, raw monologue dumps) is allowed to compound. Cleanup happens when the admin agent observes a match against the operator-curated deny-list (or the user directly asks) and applies discretion using `memory-update`, `memory-delete`, or `conversation-memory-expunge`.
|
package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js
CHANGED
|
@@ -29,7 +29,11 @@ describe("compiled-truth-revision helper", () => {
|
|
|
29
29
|
const templateEnd = src.indexOf("`", templateStart + "const updateQuery = `".length);
|
|
30
30
|
expect(templateEnd).toBeGreaterThan(templateStart);
|
|
31
31
|
const template = src.slice(templateStart, templateEnd);
|
|
32
|
-
|
|
32
|
+
// Task 2148 replaced the literal `n += $props, n.updatedAt = $updatedAt`
|
|
33
|
+
// with a clause compiled against the node's own property types. The
|
|
34
|
+
// single-TX invariant is unchanged: the SET and the revision CREATE still
|
|
35
|
+
// share one template.
|
|
36
|
+
expect(template).toContain("SET ${compiled.setClause}");
|
|
33
37
|
expect(template).toContain("${revisionClause}");
|
|
34
38
|
// And the revisionClause itself embeds the UNWIND fragment.
|
|
35
39
|
const clauseIdx = src.indexOf("const revisionClause =");
|
package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiled-truth-revision.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/compiled-truth-revision.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAEhF,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,wGAAwG,EAAE,GAAG,EAAE;QAChH,iEAAiE;QACjE,kEAAkE;QAClE,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAC9E,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAC5E,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACnE,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAC9E,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC3E,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACtE,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACpE,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACxE,MAAM,CAAC,+BAA+B,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gGAAgG,EAAE,GAAG,EAAE;QACxG,wEAAwE;QACxE,gEAAgE;QAChE,uEAAuE;QACvE,kEAAkE;QAClE,sEAAsE;QACtE,oCAAoC;QACpC,MAAM,GAAG,GAAG,YAAY,CACtB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,8BAA8B,CAAC,EAC5D,OAAO,CACR,CAAC;QACF,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAC3D,MAAM,CAAC,aAAa,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACrF,MAAM,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"compiled-truth-revision.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/compiled-truth-revision.test.ts"],"names":[],"mappings":"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"}
|
package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-type-preserve.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/temporal-type-preserve.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Task 2148 — the SET compiler that stops `memory-update` retyping a temporal
|
|
2
|
+
// property to a string. `SET n += $props` writes every value verbatim, so an
|
|
3
|
+
// ISO string aimed at a `ZONED DATETIME` silently became a `STRING`, and every
|
|
4
|
+
// `m.startsAt < datetime(...)` comparison against it is NULL rather than false.
|
|
5
|
+
//
|
|
6
|
+
// The compiler is pure: it takes the node's own `valueType()` reading per key
|
|
7
|
+
// and returns the SET clause, the params, and the list of values Neo4j's own
|
|
8
|
+
// temporal parser must vet before the write runs.
|
|
9
|
+
import { describe, it, expect } from "vitest";
|
|
10
|
+
import { normaliseValueType, temporalConstructorFor, compileTypePreservingSet, typePreserveRejection, } from "../temporal-type-preserve.js";
|
|
11
|
+
describe("normaliseValueType", () => {
|
|
12
|
+
it("strips the nullability suffix valueType() appends", () => {
|
|
13
|
+
expect(normaliseValueType("ZONED DATETIME NOT NULL")).toBe("ZONED DATETIME");
|
|
14
|
+
expect(normaliseValueType("STRING NOT NULL")).toBe("STRING");
|
|
15
|
+
expect(normaliseValueType(" DATE ")).toBe("DATE");
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe("temporalConstructorFor", () => {
|
|
19
|
+
it("maps every Neo4j temporal type to its constructor", () => {
|
|
20
|
+
expect(temporalConstructorFor("DATE NOT NULL")).toBe("date");
|
|
21
|
+
expect(temporalConstructorFor("ZONED DATETIME NOT NULL")).toBe("datetime");
|
|
22
|
+
expect(temporalConstructorFor("LOCAL DATETIME NOT NULL")).toBe("localdatetime");
|
|
23
|
+
expect(temporalConstructorFor("ZONED TIME NOT NULL")).toBe("time");
|
|
24
|
+
expect(temporalConstructorFor("LOCAL TIME NOT NULL")).toBe("localtime");
|
|
25
|
+
expect(temporalConstructorFor("DURATION NOT NULL")).toBe("duration");
|
|
26
|
+
});
|
|
27
|
+
it("returns null for every non-temporal type", () => {
|
|
28
|
+
for (const t of ["STRING NOT NULL", "INTEGER NOT NULL", "FLOAT", "BOOLEAN", "LIST<STRING>", "POINT"]) {
|
|
29
|
+
expect(temporalConstructorFor(t)).toBeNull();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
const NOW_ISO = "2026-07-29T12:00:00.000Z";
|
|
34
|
+
function compile(existingTypes, props) {
|
|
35
|
+
return compileTypePreservingSet({
|
|
36
|
+
alias: "n",
|
|
37
|
+
existingTypes,
|
|
38
|
+
props,
|
|
39
|
+
now: { key: "updatedAt", isoValue: NOW_ISO },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
describe("compileTypePreservingSet — scalar keys", () => {
|
|
43
|
+
it("leaves untyped and non-temporal keys in the n += $props bag", () => {
|
|
44
|
+
const c = compile({ title: "STRING NOT NULL" }, { title: "Golf", note: "back nine" });
|
|
45
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = $tp0");
|
|
46
|
+
expect(c.params).toEqual({ props: { title: "Golf", note: "back nine" }, tp0: NOW_ISO });
|
|
47
|
+
expect(c.probes).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe("compileTypePreservingSet — temporal keys", () => {
|
|
51
|
+
it("emits an explicit constructor assignment for a key the node holds as ZONED DATETIME", () => {
|
|
52
|
+
const c = compile({ startsAt: "ZONED DATETIME NOT NULL", title: "STRING NOT NULL" }, { startsAt: "2026-07-29T13:30:00Z", title: "Golf" });
|
|
53
|
+
expect(c.setClause).toBe("n += $props, n.`startsAt` = datetime($tp0), n.`updatedAt` = $tp1");
|
|
54
|
+
expect(c.params.props).toEqual({ title: "Golf" });
|
|
55
|
+
expect(c.params.tp0).toBe("2026-07-29T13:30:00Z");
|
|
56
|
+
expect(c.probes).toEqual([
|
|
57
|
+
{
|
|
58
|
+
key: "startsAt",
|
|
59
|
+
constructorName: "datetime",
|
|
60
|
+
paramName: "tp0",
|
|
61
|
+
value: "2026-07-29T13:30:00Z",
|
|
62
|
+
existingType: "ZONED DATETIME",
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
it("covers each temporal type with its own constructor", () => {
|
|
67
|
+
const c = compile({
|
|
68
|
+
d: "DATE NOT NULL",
|
|
69
|
+
ldt: "LOCAL DATETIME NOT NULL",
|
|
70
|
+
zt: "ZONED TIME NOT NULL",
|
|
71
|
+
lt: "LOCAL TIME NOT NULL",
|
|
72
|
+
dur: "DURATION NOT NULL",
|
|
73
|
+
}, { d: "2026-07-29", ldt: "2026-07-29T13:30:00", zt: "13:30:00Z", lt: "13:30:00", dur: "PT1H" });
|
|
74
|
+
expect(c.setClause).toBe("n += $props, n.`d` = date($tp0), n.`ldt` = localdatetime($tp1), " +
|
|
75
|
+
"n.`zt` = time($tp2), n.`lt` = localtime($tp3), n.`dur` = duration($tp4), " +
|
|
76
|
+
"n.`updatedAt` = $tp5");
|
|
77
|
+
expect(c.params.props).toEqual({});
|
|
78
|
+
expect(c.probes.map((p) => p.constructorName)).toEqual([
|
|
79
|
+
"date",
|
|
80
|
+
"localdatetime",
|
|
81
|
+
"time",
|
|
82
|
+
"localtime",
|
|
83
|
+
"duration",
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
it("escapes a backtick in a property key rather than breaking out of the quoting", () => {
|
|
87
|
+
const c = compile({ "we`ird": "ZONED DATETIME NOT NULL" }, { "we`ird": "2026-07-29T13:30:00Z" });
|
|
88
|
+
expect(c.setClause).toContain("n.`we``ird` = datetime($tp0)");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("compileTypePreservingSet — the updatedAt stamp", () => {
|
|
92
|
+
it("writes an ISO string when the node holds updatedAt as a string", () => {
|
|
93
|
+
const c = compile({ updatedAt: "STRING NOT NULL" }, { title: "Golf" });
|
|
94
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = $tp0");
|
|
95
|
+
expect(c.params.tp0).toBe(NOW_ISO);
|
|
96
|
+
});
|
|
97
|
+
it("writes an ISO string when the node has no updatedAt yet", () => {
|
|
98
|
+
const c = compile({}, { title: "Golf" });
|
|
99
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = $tp0");
|
|
100
|
+
expect(c.params.tp0).toBe(NOW_ISO);
|
|
101
|
+
});
|
|
102
|
+
it("calls the zero-argument constructor when the node holds updatedAt as a datetime", () => {
|
|
103
|
+
const c = compile({ updatedAt: "ZONED DATETIME NOT NULL" }, { title: "Golf" });
|
|
104
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = datetime()");
|
|
105
|
+
expect(c.params).toEqual({ props: { title: "Golf" } });
|
|
106
|
+
});
|
|
107
|
+
it("never lets a caller-supplied updatedAt reach the props bag or a probe", () => {
|
|
108
|
+
const c = compile({ updatedAt: "ZONED DATETIME NOT NULL" }, { updatedAt: "not-a-datetime-at-all", title: "Golf" });
|
|
109
|
+
expect(c.params.props).toEqual({ title: "Golf" });
|
|
110
|
+
expect(c.probes).toEqual([]);
|
|
111
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = datetime()");
|
|
112
|
+
});
|
|
113
|
+
it("rejects when the node holds updatedAt as a DURATION, which has no now form", () => {
|
|
114
|
+
expect(() => compile({ updatedAt: "DURATION NOT NULL" }, { title: "Golf" })).toThrow(/Update blocked \(type-preserving\): updatedAt holds DURATION/);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe("compileTypePreservingSet — rejections", () => {
|
|
118
|
+
it("rejects a non-string value for a temporal key and applies nothing", () => {
|
|
119
|
+
expect(() => compile({ startsAt: "ZONED DATETIME NOT NULL", title: "STRING NOT NULL" }, { startsAt: 1754000000000, title: "Golf" })).toThrow(/Update blocked \(type-preserving\): startsAt holds ZONED DATETIME and "1754000000000" is not a valid ZONED DATETIME/);
|
|
120
|
+
});
|
|
121
|
+
it("rejects an empty string for a temporal key", () => {
|
|
122
|
+
expect(() => compile({ startsAt: "ZONED DATETIME NOT NULL" }, { startsAt: "" })).toThrow(/Update blocked \(type-preserving\): startsAt holds ZONED DATETIME/);
|
|
123
|
+
});
|
|
124
|
+
it("still lets null clear a temporal property", () => {
|
|
125
|
+
// Removal changes no type, so it is not this module's business. `:Meeting`
|
|
126
|
+
// carries a nullable `endsAt` by schema, and refusing null here would take
|
|
127
|
+
// away the only way to clear one.
|
|
128
|
+
const c = compile({ endsAt: "ZONED DATETIME NOT NULL" }, { endsAt: null });
|
|
129
|
+
expect(c.params.props).toEqual({ endsAt: null });
|
|
130
|
+
expect(c.probes).toEqual([]);
|
|
131
|
+
expect(c.setClause).toBe("n += $props, n.`updatedAt` = $tp0");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("typePreserveRejection", () => {
|
|
135
|
+
it("names the key, the held type and the offending value", () => {
|
|
136
|
+
const err = typePreserveRejection("startsAt", "ZONED DATETIME", "not a date");
|
|
137
|
+
expect(err.message).toBe('Update blocked (type-preserving): startsAt holds ZONED DATETIME and "not a date" is not a valid ZONED DATETIME. ' +
|
|
138
|
+
"The whole update was rejected — no property was changed.");
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
//# sourceMappingURL=temporal-type-preserve.test.js.map
|
package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/temporal-type-preserve.test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-type-preserve.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/temporal-type-preserve.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type WriteEventReason = "invalid-input" | "schema-unknown-label" | "schema-property-naming" | "account-isolation" | "producedby-task-not-found" | "constraint-violation" | "conflicting-element-id" | "invalid-target-node-id" | "gate-blocked" | "neo4j-driver-error";
|
|
1
|
+
export type WriteEventReason = "invalid-input" | "schema-unknown-label" | "schema-property-naming" | "account-isolation" | "producedby-task-not-found" | "constraint-violation" | "conflicting-element-id" | "invalid-target-node-id" | "gate-blocked" | "type-preserving" | "neo4j-driver-error";
|
|
2
2
|
interface SuccessEvent {
|
|
3
3
|
tool: string;
|
|
4
4
|
result: "ok";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-ingest.d.ts","sourceRoot":"","sources":["../../src/lib/log-ingest.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,sBAAsB,GACtB,wBAAwB,GACxB,mBAAmB,GACnB,2BAA2B,GAC3B,sBAAsB,GACtB,wBAAwB,GACxB,wBAAwB,GACxB,cAAc,GACd,oBAAoB,CAAC;AAEzB,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnD,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,CAW3D;AAED,kFAAkF;AAClF,wBAAsB,cAAc,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkClE;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,qBAAqB,GAC7C,OAAO,CAAC,CAAC,CAAC,CA8BZ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"log-ingest.d.ts","sourceRoot":"","sources":["../../src/lib/log-ingest.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,sBAAsB,GACtB,wBAAwB,GACxB,mBAAmB,GACnB,2BAA2B,GAC3B,sBAAsB,GACtB,wBAAwB,GACxB,wBAAwB,GACxB,cAAc,GACd,iBAAiB,GACjB,oBAAoB,CAAC;AAEzB,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;AAEnD,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,CAW3D;AAED,kFAAkF;AAClF,wBAAsB,cAAc,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkClE;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,qBAAqB,GAC7C,OAAO,CAAC,CAAC,CAAC,CA8BZ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAuC7D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO5F"}
|
|
@@ -134,6 +134,12 @@ export function classifyReason(err) {
|
|
|
134
134
|
return "schema-unknown-label";
|
|
135
135
|
if (/Schema\.org/i.test(msg) && /property/i.test(msg))
|
|
136
136
|
return "schema-property-naming";
|
|
137
|
+
// A refusal to change a property's Neo4j type. Matched before the gate rule
|
|
138
|
+
// below, which its "Update blocked" prefix would otherwise claim: a label or
|
|
139
|
+
// property denylist refusal and a temporal type refusal are different causes,
|
|
140
|
+
// and an operator grepping the reason must be able to tell them apart.
|
|
141
|
+
if (/^Update blocked \(type-preserving\)/i.test(msg))
|
|
142
|
+
return "type-preserving";
|
|
137
143
|
// graph-write-gate "Write blocked" / "Update blocked" — checkGraphWriteGate
|
|
138
144
|
if (/^(Write|Update) blocked/i.test(msg))
|
|
139
145
|
return "gate-blocked";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-ingest.js","sourceRoot":"","sources":["../../src/lib/log-ingest.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,0EAA0E;AAC1E,6EAA6E;AAC7E,0EAA0E;AAC1E,6CAA6C;AAC7C,wEAAwE;AACxE,4CAA4C;AAC5C,EAAE;AACF,uBAAuB;AACvB,gHAAgH;AAChH,uBAAuB;AACvB,oIAAoI;AACpI,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,4EAA4E;AAC5E,sEAAsE;AACtE,gBAAgB;AAEhB,MAAM,GAAG,GAAG,YAAY,CAAC;AACzB,MAAM,aAAa,GAAG,WAAW,CAAC;AAClC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAC9C,MAAM,UAAU,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"log-ingest.js","sourceRoot":"","sources":["../../src/lib/log-ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** `valueType()` reports nullability, e.g. `ZONED DATETIME NOT NULL`. A value
|
|
2
|
+
* read off a node is always NOT NULL, so the suffix carries no information. */
|
|
3
|
+
export declare function normaliseValueType(raw: string): string;
|
|
4
|
+
/** The constructor for a `valueType()` reading, or null when the type is not
|
|
5
|
+
* temporal and the value can ride in the `n += $props` bag unchanged. */
|
|
6
|
+
export declare function temporalConstructorFor(rawValueType: string): string | null;
|
|
7
|
+
/** A value the caller must vet with Neo4j's own temporal parser before the
|
|
8
|
+
* write runs. Vetting up front is what makes the rejection all-or-nothing. */
|
|
9
|
+
export interface TemporalProbe {
|
|
10
|
+
key: string;
|
|
11
|
+
constructorName: string;
|
|
12
|
+
paramName: string;
|
|
13
|
+
value: unknown;
|
|
14
|
+
/** Normalised `valueType()` reading, for the rejection message. */
|
|
15
|
+
existingType: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CompiledUpdate {
|
|
18
|
+
/** The SET clause body, without the leading `SET`. */
|
|
19
|
+
setClause: string;
|
|
20
|
+
/** Query params. Always carries `props`; temporal values are `tp0`, `tp1`, … */
|
|
21
|
+
params: Record<string, unknown>;
|
|
22
|
+
probes: TemporalProbe[];
|
|
23
|
+
}
|
|
24
|
+
/** The single rejection message for every type-preserving refusal — raised here
|
|
25
|
+
* for a value this module can already see is wrong, and by the caller when
|
|
26
|
+
* Neo4j's parser rejects a probe. `Update blocked` is what `classifyReason`
|
|
27
|
+
* maps to `reason=gate-blocked`, so the refusal always reaches the log. */
|
|
28
|
+
export declare function typePreserveRejection(key: string, existingType: string, value: unknown): Error;
|
|
29
|
+
export interface CompileArgs {
|
|
30
|
+
/** Node alias the SET clause addresses. */
|
|
31
|
+
alias: string;
|
|
32
|
+
/** `valueType()` per property key, for the keys the node already holds. A key
|
|
33
|
+
* absent from this map is new on the node and has no type to preserve. */
|
|
34
|
+
existingTypes: Record<string, string>;
|
|
35
|
+
props: Record<string, unknown>;
|
|
36
|
+
/** The write-time stamp. Its key is removed from `props` first, so a
|
|
37
|
+
* caller-supplied value can never reach the node or a probe — matching the
|
|
38
|
+
* pre-existing behaviour where the explicit stamp overwrote it. */
|
|
39
|
+
now: {
|
|
40
|
+
key: string;
|
|
41
|
+
isoValue: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export declare function compileTypePreservingSet(args: CompileArgs): CompiledUpdate;
|
|
45
|
+
//# sourceMappingURL=temporal-type-preserve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-type-preserve.d.ts","sourceRoot":"","sources":["../../src/lib/temporal-type-preserve.ts"],"names":[],"mappings":"AA2CA;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;0EAC0E;AAC1E,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE1E;AAED;+EAC+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;4EAG4E;AAC5E,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,CAM9F;AAOD,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd;+EAC2E;IAC3E,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;wEAEoE;IACpE,GAAG,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACxC;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,WAAW,GAAG,cAAc,CAgE1E"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Task 2148 — type-preserving SET compiler for memory-update.
|
|
3
|
+
//
|
|
4
|
+
// `SET n += $props` writes every value verbatim. An agent updating a :Meeting
|
|
5
|
+
// with `startsAt: "2026-07-29T13:30:00Z"` therefore replaced a ZONED DATETIME
|
|
6
|
+
// with a STRING, and a `STRING`-to-`DATETIME` comparison in Neo4j is NULL, not
|
|
7
|
+
// false: every calendar reader dropped the row with no error and no log line.
|
|
8
|
+
//
|
|
9
|
+
// This module decides, per key, whether the value can ride in the `n += $props`
|
|
10
|
+
// bag or has to be rebuilt with the temporal constructor matching the type the
|
|
11
|
+
// node already holds. It is pure — the caller owns the session — and it never
|
|
12
|
+
// guesses at Neo4j's temporal grammar: values bound for a constructor come back
|
|
13
|
+
// as `probes`, which the caller vets with Neo4j's own parser before any write.
|
|
14
|
+
//
|
|
15
|
+
// existing valueType(n.startsAt) emitted SET fragment
|
|
16
|
+
// ──────────────────────────────── ─────────────────────────────────
|
|
17
|
+
// STRING / INTEGER / absent (stays in `n += $props`)
|
|
18
|
+
// ZONED DATETIME n.`startsAt` = datetime($tp0)
|
|
19
|
+
// DATE n.`startsAt` = date($tp0)
|
|
20
|
+
//
|
|
21
|
+
// The `updatedAt` stamp follows the same rule rather than being forced to one
|
|
22
|
+
// type: `memory-write` stamps it as an ISO string (memory-write.ts:223) and the
|
|
23
|
+
// graph tooltip reads it with `typeof props.updatedAt === 'string'`
|
|
24
|
+
// (platform/ui/app/graph/display-helpers.ts:286), so an unconditional
|
|
25
|
+
// `datetime()` would be the very retype this module exists to prevent.
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/** Neo4j temporal types, as `valueType()` names them, and the Cypher
|
|
28
|
+
* constructor that rebuilds a value of that type. */
|
|
29
|
+
const TEMPORAL_CONSTRUCTORS = {
|
|
30
|
+
DATE: "date",
|
|
31
|
+
"ZONED DATETIME": "datetime",
|
|
32
|
+
"LOCAL DATETIME": "localdatetime",
|
|
33
|
+
"ZONED TIME": "time",
|
|
34
|
+
"LOCAL TIME": "localtime",
|
|
35
|
+
DURATION: "duration",
|
|
36
|
+
};
|
|
37
|
+
/** The five constructors with a zero-argument "now" form. `duration` has none,
|
|
38
|
+
* which is why a DURATION-typed `updatedAt` is a rejection rather than a
|
|
39
|
+
* silent retype. */
|
|
40
|
+
const NOW_CAPABLE = new Set(["date", "datetime", "localdatetime", "time", "localtime"]);
|
|
41
|
+
/** `valueType()` reports nullability, e.g. `ZONED DATETIME NOT NULL`. A value
|
|
42
|
+
* read off a node is always NOT NULL, so the suffix carries no information. */
|
|
43
|
+
export function normaliseValueType(raw) {
|
|
44
|
+
return raw.trim().replace(/\s+NOT\s+NULL$/i, "").trim();
|
|
45
|
+
}
|
|
46
|
+
/** The constructor for a `valueType()` reading, or null when the type is not
|
|
47
|
+
* temporal and the value can ride in the `n += $props` bag unchanged. */
|
|
48
|
+
export function temporalConstructorFor(rawValueType) {
|
|
49
|
+
return TEMPORAL_CONSTRUCTORS[normaliseValueType(rawValueType)] ?? null;
|
|
50
|
+
}
|
|
51
|
+
/** The single rejection message for every type-preserving refusal — raised here
|
|
52
|
+
* for a value this module can already see is wrong, and by the caller when
|
|
53
|
+
* Neo4j's parser rejects a probe. `Update blocked` is what `classifyReason`
|
|
54
|
+
* maps to `reason=gate-blocked`, so the refusal always reaches the log. */
|
|
55
|
+
export function typePreserveRejection(key, existingType, value) {
|
|
56
|
+
return new Error(`Update blocked (type-preserving): ${key} holds ${existingType} and ` +
|
|
57
|
+
`"${String(value)}" is not a valid ${existingType}. ` +
|
|
58
|
+
`The whole update was rejected — no property was changed.`);
|
|
59
|
+
}
|
|
60
|
+
/** Backticks are the only character that can break out of `n.\`key\``. */
|
|
61
|
+
function quoteKey(key) {
|
|
62
|
+
return "`" + key.replace(/`/g, "``") + "`";
|
|
63
|
+
}
|
|
64
|
+
export function compileTypePreservingSet(args) {
|
|
65
|
+
const { alias, existingTypes, props, now } = args;
|
|
66
|
+
const scalarProps = {};
|
|
67
|
+
const assignments = [];
|
|
68
|
+
const probes = [];
|
|
69
|
+
const params = {};
|
|
70
|
+
let paramIndex = 0;
|
|
71
|
+
for (const [key, value] of Object.entries(props)) {
|
|
72
|
+
if (key === now.key)
|
|
73
|
+
continue;
|
|
74
|
+
const rawType = existingTypes[key];
|
|
75
|
+
const constructorName = rawType ? temporalConstructorFor(rawType) : null;
|
|
76
|
+
if (!constructorName) {
|
|
77
|
+
scalarProps[key] = value;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// `null` removes the property. Removal changes no type, so it is not this
|
|
81
|
+
// module's business — it rides in the props bag exactly as it always did.
|
|
82
|
+
// Refusing it would take away the only way to clear a temporal property.
|
|
83
|
+
if (value === null) {
|
|
84
|
+
scalarProps[key] = value;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const existingType = normaliseValueType(rawType);
|
|
88
|
+
// Only a non-empty string can reach a temporal constructor. Anything else
|
|
89
|
+
// is refused here rather than probed: Neo4j would reject it too, and this
|
|
90
|
+
// way the message names the key without a round trip.
|
|
91
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
92
|
+
throw typePreserveRejection(key, existingType, value);
|
|
93
|
+
}
|
|
94
|
+
const paramName = `tp${paramIndex++}`;
|
|
95
|
+
params[paramName] = value;
|
|
96
|
+
assignments.push(`${alias}.${quoteKey(key)} = ${constructorName}(\$${paramName})`);
|
|
97
|
+
probes.push({ key, constructorName, paramName, value, existingType });
|
|
98
|
+
}
|
|
99
|
+
// The stamp is emitted last so it wins over anything in `props`, exactly as
|
|
100
|
+
// the trailing `n.updatedAt = $updatedAt` did before.
|
|
101
|
+
const nowRawType = existingTypes[now.key];
|
|
102
|
+
const nowConstructor = nowRawType ? temporalConstructorFor(nowRawType) : null;
|
|
103
|
+
if (nowConstructor) {
|
|
104
|
+
const nowType = normaliseValueType(nowRawType);
|
|
105
|
+
if (!NOW_CAPABLE.has(nowConstructor)) {
|
|
106
|
+
throw typePreserveRejection(now.key, nowType, now.isoValue);
|
|
107
|
+
}
|
|
108
|
+
assignments.push(`${alias}.${quoteKey(now.key)} = ${nowConstructor}()`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const paramName = `tp${paramIndex++}`;
|
|
112
|
+
params[paramName] = now.isoValue;
|
|
113
|
+
assignments.push(`${alias}.${quoteKey(now.key)} = \$${paramName}`);
|
|
114
|
+
}
|
|
115
|
+
params.props = scalarProps;
|
|
116
|
+
return {
|
|
117
|
+
setClause: [`${alias} += \$props`, ...assignments].join(", "),
|
|
118
|
+
params,
|
|
119
|
+
probes,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=temporal-type-preserve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-type-preserve.js","sourceRoot":"","sources":["../../src/lib/temporal-type-preserve.ts"],"names":[],"mappings":"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"}
|
package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js
CHANGED
|
@@ -55,6 +55,32 @@ describe("memory-update-by-name — happy path", () => {
|
|
|
55
55
|
expect(params).toEqual({ accountId: ACCOUNT_ID, name: "BioSymm Technologies Ltd" });
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
|
+
describe("memory-update-by-name — Task 2148 type preservation is inherited", () => {
|
|
59
|
+
// This tool owns the lookup and nothing else: the write, the gates and the
|
|
60
|
+
// type-preserving SET all live in memoryUpdate, which it delegates to. So the
|
|
61
|
+
// guard here is that the properties bag arrives verbatim — if it ever grew its
|
|
62
|
+
// own write path, a :Meeting reachable by name would be a second route to the
|
|
63
|
+
// string retype that made Adam Mackay's golf afternoon publish as open time.
|
|
64
|
+
it("hands a temporal property straight to memoryUpdate without rewriting it", async () => {
|
|
65
|
+
mockSession.run.mockResolvedValueOnce({ records: [record("4:meeting:17")] });
|
|
66
|
+
memoryUpdateMock.mockResolvedValueOnce({ nodeId: "4:meeting:17", labels: ["Meeting"], updated: true });
|
|
67
|
+
await memoryUpdateByName({
|
|
68
|
+
label: "Meeting",
|
|
69
|
+
name: "Golf",
|
|
70
|
+
accountId: ACCOUNT_ID,
|
|
71
|
+
properties: { startsAt: "2026-07-29T13:30:00Z", endsAt: "2026-07-29T17:30:00Z" },
|
|
72
|
+
createdBy: CREATED_BY,
|
|
73
|
+
});
|
|
74
|
+
expect(memoryUpdateMock).toHaveBeenCalledWith({
|
|
75
|
+
nodeId: "4:meeting:17",
|
|
76
|
+
properties: { startsAt: "2026-07-29T13:30:00Z", endsAt: "2026-07-29T17:30:00Z" },
|
|
77
|
+
accountId: ACCOUNT_ID,
|
|
78
|
+
createdBy: CREATED_BY,
|
|
79
|
+
});
|
|
80
|
+
// The lookup is the only statement this tool runs itself.
|
|
81
|
+
expect(mockSession.run).toHaveBeenCalledTimes(1);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
58
84
|
describe("memory-update-by-name — reject paths", () => {
|
|
59
85
|
it("throws 'not found' on zero matches with the lookup tuple in the message", async () => {
|
|
60
86
|
mockSession.run.mockResolvedValueOnce({ records: [] });
|