@rubytech/create-maxy-code 0.1.230 → 0.1.233
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__/rss-sampler-installer.test.js +27 -0
- package/dist/index.js +61 -0
- package/package.json +1 -1
- package/payload/platform/neo4j/schema.cypher +20 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -1
- package/payload/platform/plugins/docs/references/graph.md +12 -0
- package/payload/platform/plugins/docs/references/memory-guide.md +26 -0
- package/payload/platform/plugins/docs/superpowers/plans/2026-06-01-memory-edge.md +589 -0
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +12 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +64 -7
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +16 -0
- 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__/phase-backlinks.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.js +24 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-backlinks.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.js +51 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-tag-normalisation.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts +31 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +7 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.js +7 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.js +37 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-backlinks.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.d.ts +25 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.js +90 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-tag-normalisation.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +117 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js +72 -26
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.js +164 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-edge.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.js +66 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-inline-rewrite.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.js +30 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-timeline-learned-at.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +25 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +26 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts +17 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js +33 -13
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +6 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +32 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.d.ts +21 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.js +51 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-edge.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +37 -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 +72 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.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 +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/skills/challenge/SKILL.md +52 -0
- package/payload/platform/plugins/memory/skills/connect/SKILL.md +56 -0
- package/payload/platform/plugins/memory/skills/emerge/SKILL.md +87 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/scripts/rss-sampler.sh +58 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +4 -0
- 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 +30 -4
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +23 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +14 -2
- 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 +27 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +6 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/templates/specialists/agents/archive-ingest-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/server/{chunk-EXIPYITB.js → chunk-63M3ILJ6.js} +1 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/admin-DfeXRW1m.js +1 -0
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +1 -1
- package/payload/server/public/assets/admin-BKawc0eQ.js +0 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Static-grep contracts for Task 600 installer additions:
|
|
2
|
+
// swap provisioning and rss-sampler service registration.
|
|
3
|
+
//
|
|
4
|
+
// Why static-grep, not behaviour: the install branches spawn (sudo, systemctl,
|
|
5
|
+
// dphys-swapfile), so end-to-end reproduction belongs to the manual smoke path.
|
|
6
|
+
// The unit suite pins the branch points so a future refactor that removes them
|
|
7
|
+
// fails loudly here.
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { dirname, resolve } from "node:path";
|
|
13
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const INDEX_TS = resolve(here, "../../src/index.ts");
|
|
15
|
+
const SRC = readFileSync(INDEX_TS, "utf-8");
|
|
16
|
+
test("installSystemDeps Linux branch installs dphys-swapfile and writes CONF_SWAPSIZE=2048", () => {
|
|
17
|
+
assert.match(SRC, /apt-get.*install.*dphys-swapfile/s, "apt install dphys-swapfile must be present");
|
|
18
|
+
assert.match(SRC, /CONF_SWAPSIZE=2048/, "swap size must be 2048MB");
|
|
19
|
+
assert.match(SRC, /CONF_MAXSWAP=4096/, "swap max must be 4096MB");
|
|
20
|
+
assert.match(SRC, /dphys-swapfile.*restart|restart.*dphys-swapfile/s, "dphys-swapfile service must be restarted");
|
|
21
|
+
});
|
|
22
|
+
test("installService Linux branch writes rss-sampler user unit and enables it", () => {
|
|
23
|
+
assert.match(SRC, /rss-sampler\.service/, "rss-sampler.service unit must be written");
|
|
24
|
+
assert.match(SRC, /rss-sampler\.sh/, "rss-sampler.sh must appear in ExecStart");
|
|
25
|
+
assert.match(SRC, /rss-sampler.*enable|enable.*rss-sampler/s, "rss-sampler must be enabled");
|
|
26
|
+
assert.match(SRC, /rss-sampler installed/, "rss-sampler install must emit a logFile entry");
|
|
27
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -709,6 +709,42 @@ function installSystemDeps() {
|
|
|
709
709
|
// so deployPayload's writeChromiumBinaryPathFile and installService's
|
|
710
710
|
// buildMaxyUnitFile both have a real absolute path to thread through.
|
|
711
711
|
ensureNonSnapChromium();
|
|
712
|
+
// Task 600 — provision swap so the OOM-killer has a buffer to work in
|
|
713
|
+
// instead of silently freezing the box. dphys-swapfile is the standard
|
|
714
|
+
// Raspberry Pi OS swap manager. CONF_MAXSWAP raised to 4096 so the
|
|
715
|
+
// operator can manually grow the swap file without reinstalling.
|
|
716
|
+
// Best-effort: a failure here warns but does not abort the install.
|
|
717
|
+
try {
|
|
718
|
+
console.log(" [privileged] apt-get install dphys-swapfile");
|
|
719
|
+
shell("apt-get", ["install", "-y", "dphys-swapfile"], { sudo: true, bestEffort: true });
|
|
720
|
+
const desiredSwapConf = "CONF_SWAPSIZE=2048\nCONF_MAXSWAP=4096\n";
|
|
721
|
+
const swapConfPath = "/etc/dphys-swapfile";
|
|
722
|
+
let swapCurrent = "";
|
|
723
|
+
if (existsSync(swapConfPath)) {
|
|
724
|
+
try {
|
|
725
|
+
swapCurrent = readFileSync(swapConfPath, "utf-8");
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
swapCurrent = "";
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (swapCurrent === desiredSwapConf) {
|
|
732
|
+
logFile(" swap: already configured (CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096)");
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
const swapTmpPath = `/tmp/dphys-swapfile.${process.pid}`;
|
|
736
|
+
writeFileSync(swapTmpPath, desiredSwapConf);
|
|
737
|
+
console.log(" [privileged] install /etc/dphys-swapfile (CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096)");
|
|
738
|
+
shell("cp", [swapTmpPath, swapConfPath], { sudo: true });
|
|
739
|
+
spawnSync("rm", ["-f", swapTmpPath]);
|
|
740
|
+
console.log(" [privileged] systemctl restart dphys-swapfile");
|
|
741
|
+
shell("systemctl", ["restart", "dphys-swapfile"], { sudo: true, bestEffort: true });
|
|
742
|
+
logFile(" swap: configured CONF_SWAPSIZE=2048 CONF_MAXSWAP=4096 and restarted dphys-swapfile");
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
catch (err) {
|
|
746
|
+
console.error(` WARNING: failed to provision swap: ${err instanceof Error ? err.message : String(err)}`);
|
|
747
|
+
}
|
|
712
748
|
// Hostname resolution — four sources, in priority order:
|
|
713
749
|
// 1. --hostname flag (unconditional — the caller is the authority)
|
|
714
750
|
// 2. OS detection on same-brand upgrade (service exists → keep whatever is currently set)
|
|
@@ -3084,6 +3120,28 @@ function installService() {
|
|
|
3084
3120
|
const claudePtysSliceName = "claude-ptys.slice";
|
|
3085
3121
|
writeFileSync(join(serviceDir, claudePtysSliceName), buildClaudePtysSliceUnitFile());
|
|
3086
3122
|
logFile(` ${claudePtysSliceName}: Task 250 slice for claude-session-*.scope cohort`);
|
|
3123
|
+
// Task 600 — per-brand RSS sampler: a long-running user service that
|
|
3124
|
+
// periodically writes per-claude.exe RSS + aggregate RSS to disk.
|
|
3125
|
+
// Named per-brand (BRAND.hostname prefix) so two brands on the same
|
|
3126
|
+
// device each own their own sampler writing to their own log path.
|
|
3127
|
+
const rssSamplerUnitName = `${BRAND.hostname}-rss-sampler.service`;
|
|
3128
|
+
const rssSamplerScriptPath = resolve(INSTALL_DIR, "platform/scripts/rss-sampler.sh");
|
|
3129
|
+
const rssSamplerLogPath = join(persistDir, "rss-sampler.log");
|
|
3130
|
+
const rssSamplerUnit = `[Unit]
|
|
3131
|
+
Description=${BRAND.productName} RSS Sampler
|
|
3132
|
+
|
|
3133
|
+
[Service]
|
|
3134
|
+
Type=simple
|
|
3135
|
+
ExecStart=/bin/bash ${rssSamplerScriptPath}
|
|
3136
|
+
Environment=LOG_PATH=${rssSamplerLogPath}
|
|
3137
|
+
Restart=on-failure
|
|
3138
|
+
RestartSec=10
|
|
3139
|
+
|
|
3140
|
+
[Install]
|
|
3141
|
+
WantedBy=default.target
|
|
3142
|
+
`;
|
|
3143
|
+
writeFileSync(join(serviceDir, rssSamplerUnitName), rssSamplerUnit);
|
|
3144
|
+
logFile(` rss-sampler installed: ${rssSamplerUnitName} LOG_PATH=${rssSamplerLogPath}`);
|
|
3087
3145
|
// the edge service: always-on front door that owns the public
|
|
3088
3146
|
// port (PORT) and the VNC stack (Xtigervnc + websockify). Its lifecycle is
|
|
3089
3147
|
// independent of the main brand service, so an in-place upgrade triggered
|
|
@@ -3294,11 +3352,14 @@ WantedBy=multi-user.target
|
|
|
3294
3352
|
spawnSync("systemctl", ["--user", "enable", edgeUnitShort], { stdio: "inherit" });
|
|
3295
3353
|
spawnSync("systemctl", ["--user", "enable", claudeSessionManagerUnitShort], { stdio: "inherit" });
|
|
3296
3354
|
spawnSync("systemctl", ["--user", "enable", unitName], { stdio: "inherit" });
|
|
3355
|
+
spawnSync("systemctl", ["--user", "enable", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
|
|
3297
3356
|
// edge first: binds public port + starts VNC stack. Then claude-session-manager
|
|
3298
3357
|
// (so the main brand unit's Requires= is satisfied). Then main brand service.
|
|
3358
|
+
// rss-sampler is independent — start last, failure is non-blocking.
|
|
3299
3359
|
spawnSync("systemctl", ["--user", "restart", edgeUnitShort], { stdio: "inherit" });
|
|
3300
3360
|
spawnSync("systemctl", ["--user", "restart", claudeSessionManagerUnitShort], { stdio: "inherit" });
|
|
3301
3361
|
spawnSync("systemctl", ["--user", "restart", unitName], { stdio: "inherit" });
|
|
3362
|
+
spawnSync("systemctl", ["--user", "restart", `${BRAND.hostname}-rss-sampler`], { stdio: "inherit" });
|
|
3302
3363
|
// Session manager runs in its own systemd user unit and can boot-fail silently
|
|
3303
3364
|
// (e.g. mcp-block-missing). The web server below comes up regardless, so the
|
|
3304
3365
|
// install terminal would otherwise report success while every API call 503s.
|
package/package.json
CHANGED
|
@@ -1566,6 +1566,13 @@ OPTIONS {
|
|
|
1566
1566
|
// mentioned | met | quoted | attended | transacted
|
|
1567
1567
|
// Extractor refuses on ambiguity rather than collapsing to "other".
|
|
1568
1568
|
//
|
|
1569
|
+
// `learnedAt` — datetime(), transaction-time: when this event was ingested.
|
|
1570
|
+
// Distinct from `occurredAt` (valid-time: when the fact was true in the world).
|
|
1571
|
+
// Enables bi-temporal queries: "events ingested on date X about something that
|
|
1572
|
+
// happened in 1990". Backfilled from `createdAt` on pre-existing nodes; nodes
|
|
1573
|
+
// without `createdAt` fall back to `datetime()` (safe approximation).
|
|
1574
|
+
// Task 597.
|
|
1575
|
+
//
|
|
1569
1576
|
// `compiledTruth` source:
|
|
1570
1577
|
// compiledTruthSource = "rewriter" (default) — compiled-truth-rewriter
|
|
1571
1578
|
// library wrote it.
|
|
@@ -1596,6 +1603,9 @@ FOR (t:TimelineEvent) ON (t.occurredAt);
|
|
|
1596
1603
|
CREATE INDEX timeline_event_kind IF NOT EXISTS
|
|
1597
1604
|
FOR (t:TimelineEvent) ON (t.kind);
|
|
1598
1605
|
|
|
1606
|
+
CREATE INDEX timeline_event_learned_at IF NOT EXISTS
|
|
1607
|
+
FOR (t:TimelineEvent) ON (t.learnedAt);
|
|
1608
|
+
|
|
1599
1609
|
CREATE VECTOR INDEX timeline_event_embedding IF NOT EXISTS
|
|
1600
1610
|
FOR (t:TimelineEvent) ON (t.embedding)
|
|
1601
1611
|
OPTIONS {
|
|
@@ -1605,6 +1615,16 @@ OPTIONS {
|
|
|
1605
1615
|
}
|
|
1606
1616
|
};
|
|
1607
1617
|
|
|
1618
|
+
// Task 597 migration — backfill learnedAt on :TimelineEvent nodes written
|
|
1619
|
+
// before transaction-time was tracked. Uses createdAt as the best available
|
|
1620
|
+
// proxy; nodes without createdAt get datetime() (safe: they predate the field).
|
|
1621
|
+
// CALL IN TRANSACTIONS avoids a single large write lock on installs with many nodes.
|
|
1622
|
+
CALL {
|
|
1623
|
+
MATCH (t:TimelineEvent) WHERE t.learnedAt IS NULL
|
|
1624
|
+
WITH t LIMIT 500
|
|
1625
|
+
SET t.learnedAt = coalesce(t.createdAt, datetime())
|
|
1626
|
+
} IN TRANSACTIONS OF 500 ROWS;
|
|
1627
|
+
|
|
1608
1628
|
// `compiledTruthUpdatedAt` indices for stale-detection scans
|
|
1609
1629
|
// (e.g. "find :Person with truth older than 7 days that has new events").
|
|
1610
1630
|
CREATE INDEX person_compiled_truth_updated_at IF NOT EXISTS
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
|
|
4
|
-
content-hash: sha256:
|
|
4
|
+
content-hash: sha256:40fe99e94ab4ff0540965423bb0c7aa6016d438a5503f06aa3ab6608773c694e
|
|
5
5
|
brand: maxy-code
|
|
6
6
|
product-name: Maxy
|
|
7
7
|
---
|
|
@@ -1489,6 +1489,16 @@ Ask naturally:
|
|
|
1489
1489
|
- "What did I last discuss about the Acme proposal?"
|
|
1490
1490
|
- "Who have I met from the fintech conference?"
|
|
1491
1491
|
|
|
1492
|
+
## Thinking tools
|
|
1493
|
+
|
|
1494
|
+
Three slash commands that apply analysis to what's already in your graph:
|
|
1495
|
+
|
|
1496
|
+
**`/challenge <claim>`** — stress-tests an assertion. Maxy searches your graph for nodes that contradict or qualify the claim — nodes that assert the opposite, name exceptions, or add significant caveats — and presents the strongest counter-case it finds. If nothing in your graph challenges the claim, it says so rather than inventing one. Results cite node IDs and relevance scores so you can inspect the sources directly.
|
|
1497
|
+
|
|
1498
|
+
**`/connect <topic-A> <topic-B>`** — finds the bridge. Maxy searches both topics, collects their immediate graph neighborhoods, and looks for nodes they share. If a direct bridge exists it names it in one sentence. If not, it surfaces the closest approach — the two nodes that are semantically nearest across the two sides — and proposes the connection you could draw.
|
|
1499
|
+
|
|
1500
|
+
**`/emerge`** — names the unnamed clusters. Maxy retrieves your KnowledgeDocument and Section nodes that are not yet connected to a Concept node, groups them by shared theme, and proposes a Concept name for each cluster. You approve or skip each proposal one at a time; nothing is written without your confirmation. Clusters of fewer than three nodes are listed at the end as "too small to cluster."
|
|
1501
|
+
|
|
1492
1502
|
## Listing and counting
|
|
1493
1503
|
|
|
1494
1504
|
Maxy answers relational questions — "list all my people", "how many tasks do I have", "find the person with email X", "show me the 20 most recently created nodes" — via direct read-only Cypher against your Neo4j. This is faster and more precise than semantic search when the question is "the exact set where", not "things similar to".
|
|
@@ -1507,6 +1517,22 @@ The page reads only your own brand's Neo4j — a Maxy device and a Real Agent de
|
|
|
1507
1517
|
|
|
1508
1518
|
**Typo-proof cypher.** When Maxy runs direct Cypher to answer a relational question, the query is checked against your Neo4j's live label and relationship-type taxonomy before it executes. Cypher that references an unknown name (an edge or label that does not exist in your graph) is rejected for writes and flagged with a warnings header for reads, so Maxy never silently acts on a query that targeted the wrong set of nodes. You should not see this — it runs invisibly — but it is the safety net that stops a fabricated edge name from producing "empty" results that are really just unreachable. Before acting on a bulk operation Maxy surfaces the result count and a sample; if it ever describes a cypher rejection, that means its first attempt was malformed and it corrected itself.
|
|
1509
1519
|
|
|
1520
|
+
## Bi-temporal timeline events
|
|
1521
|
+
|
|
1522
|
+
Every factual statement Maxy extracts from your conversations is stored as a `:TimelineEvent` node. Each event carries two separate timestamps:
|
|
1523
|
+
|
|
1524
|
+
- **`occurredAt`** (valid-time) — when the fact was true in the world. Set from the text itself; can reference a date in the past ("Alice joined in 1990" stores `occurredAt = 1990-01-01`).
|
|
1525
|
+
- **`learnedAt`** (transaction-time) — when the system ingested this event. Always the wall-clock time of the write; never back-dated.
|
|
1526
|
+
|
|
1527
|
+
This distinction lets you ask two qualitatively different questions:
|
|
1528
|
+
|
|
1529
|
+
- *"What happened to Alice in 1990?"* — query by `occurredAt`.
|
|
1530
|
+
- *"What did Maxy learn about Alice last Tuesday?"* — query by `learnedAt`.
|
|
1531
|
+
|
|
1532
|
+
`memory-compiled-truth-history` returns both fields for every timeline event on an entity under the `timelineEvents` array, alongside the compiled-truth revision history in the `revisions` array.
|
|
1533
|
+
|
|
1534
|
+
**Backfill:** Timeline events written before this feature was added have `learnedAt` set to their `createdAt` value by the schema migration. Events without `createdAt` (very old nodes) receive the migration run time as an approximation.
|
|
1535
|
+
|
|
1510
1536
|
## Write doctrine
|
|
1511
1537
|
|
|
1512
1538
|
Every new node in Maxy's graph is created with at least one connection to an existing node. A contact connects to the conversation or organisation it came from; a task connects to the session that raised it or the entities it will affect; a session summary connects to the conversation it summarises. A node with no connection is noise — it cannot be attributed, traversed, or explained — so the graph refuses to create one. If Maxy ever tries to record something without a link, the write is rejected and Maxy asks you to clarify where it belongs.
|
|
@@ -2572,6 +2598,18 @@ switch them off. Flipping it off again also drops them from any already-
|
|
|
2572
2598
|
expanded neighbourhood so a click near a `ToolCall` does not re-introduce
|
|
2573
2599
|
it.
|
|
2574
2600
|
|
|
2601
|
+
## Direct edge management
|
|
2602
|
+
|
|
2603
|
+
`memory-edge` creates or deletes a typed directed edge between two nodes that already exist in the graph. Both nodes must belong to the same account — mismatched or foreign nodes are rejected with a structured error before any mutation runs.
|
|
2604
|
+
|
|
2605
|
+
**Create:** MERGE is idempotent. First call returns `{created: true}`; a repeated call with the same endpoints and type returns `{created: false}`. Properties supplied on the call are stamped onto the relationship on CREATE only; a subsequent idempotent hit does not overwrite them.
|
|
2606
|
+
|
|
2607
|
+
**Delete:** If the edge is present it is deleted and `{deleted: true}` is returned. If absent, the call is a no-op and returns `{deleted: false}`.
|
|
2608
|
+
|
|
2609
|
+
`relationshipType` is uppercase-coerced. Types that start with an underscore (e.g. `_SOFT_DELETE`) are reserved for platform internals and are rejected.
|
|
2610
|
+
|
|
2611
|
+
Typical flow: call `memory-search` for each endpoint to retrieve their `elementId` values, then call `memory-edge action=create relationshipType=RELATES_TO fromId=<id> toId=<id>`. The new edge appears when you hop-expand either endpoint on the `/graph` canvas.
|
|
2612
|
+
|
|
2575
2613
|
---
|
|
2576
2614
|
# Neo4j Edge Types
|
|
2577
2615
|
Source: https://docs.getmaxy.com/neo4j.md
|
|
@@ -147,3 +147,15 @@ the 90% domain-navigation path stays clean without having to remember to
|
|
|
147
147
|
switch them off. Flipping it off again also drops them from any already-
|
|
148
148
|
expanded neighbourhood so a click near a `ToolCall` does not re-introduce
|
|
149
149
|
it.
|
|
150
|
+
|
|
151
|
+
## Direct edge management
|
|
152
|
+
|
|
153
|
+
`memory-edge` creates or deletes a typed directed edge between two nodes that already exist in the graph. Both nodes must belong to the same account — mismatched or foreign nodes are rejected with a structured error before any mutation runs.
|
|
154
|
+
|
|
155
|
+
**Create:** MERGE is idempotent. First call returns `{created: true}`; a repeated call with the same endpoints and type returns `{created: false}`. Properties supplied on the call are stamped onto the relationship on CREATE only; a subsequent idempotent hit does not overwrite them.
|
|
156
|
+
|
|
157
|
+
**Delete:** If the edge is present it is deleted and `{deleted: true}` is returned. If absent, the call is a no-op and returns `{deleted: false}`.
|
|
158
|
+
|
|
159
|
+
`relationshipType` is uppercase-coerced. Types that start with an underscore (e.g. `_SOFT_DELETE`) are reserved for platform internals and are rejected.
|
|
160
|
+
|
|
161
|
+
Typical flow: call `memory-search` for each endpoint to retrieve their `elementId` values, then call `memory-edge action=create relationshipType=RELATES_TO fromId=<id> toId=<id>`. The new edge appears when you hop-expand either endpoint on the `/graph` canvas.
|
|
@@ -90,6 +90,16 @@ Ask naturally:
|
|
|
90
90
|
- "What did I last discuss about the Acme proposal?"
|
|
91
91
|
- "Who have I met from the fintech conference?"
|
|
92
92
|
|
|
93
|
+
## Thinking tools
|
|
94
|
+
|
|
95
|
+
Three slash commands that apply analysis to what's already in your graph:
|
|
96
|
+
|
|
97
|
+
**`/challenge <claim>`** — stress-tests an assertion. {{productName}} searches your graph for nodes that contradict or qualify the claim — nodes that assert the opposite, name exceptions, or add significant caveats — and presents the strongest counter-case it finds. If nothing in your graph challenges the claim, it says so rather than inventing one. Results cite node IDs and relevance scores so you can inspect the sources directly.
|
|
98
|
+
|
|
99
|
+
**`/connect <topic-A> <topic-B>`** — finds the bridge. {{productName}} searches both topics, collects their immediate graph neighborhoods, and looks for nodes they share. If a direct bridge exists it names it in one sentence. If not, it surfaces the closest approach — the two nodes that are semantically nearest across the two sides — and proposes the connection you could draw.
|
|
100
|
+
|
|
101
|
+
**`/emerge`** — names the unnamed clusters. {{productName}} retrieves your KnowledgeDocument and Section nodes that are not yet connected to a Concept node, groups them by shared theme, and proposes a Concept name for each cluster. You approve or skip each proposal one at a time; nothing is written without your confirmation. Clusters of fewer than three nodes are listed at the end as "too small to cluster."
|
|
102
|
+
|
|
93
103
|
## Listing and counting
|
|
94
104
|
|
|
95
105
|
{{productName}} answers relational questions — "list all my people", "how many tasks do I have", "find the person with email X", "show me the 20 most recently created nodes" — via direct read-only Cypher against your Neo4j. This is faster and more precise than semantic search when the question is "the exact set where", not "things similar to".
|
|
@@ -108,6 +118,22 @@ The page reads only your own brand's Neo4j — a Maxy device and a Real Agent de
|
|
|
108
118
|
|
|
109
119
|
**Typo-proof cypher.** When {{productName}} runs direct Cypher to answer a relational question, the query is checked against your Neo4j's live label and relationship-type taxonomy before it executes. Cypher that references an unknown name (an edge or label that does not exist in your graph) is rejected for writes and flagged with a warnings header for reads, so {{productName}} never silently acts on a query that targeted the wrong set of nodes. You should not see this — it runs invisibly — but it is the safety net that stops a fabricated edge name from producing "empty" results that are really just unreachable. Before acting on a bulk operation {{productName}} surfaces the result count and a sample; if it ever describes a cypher rejection, that means its first attempt was malformed and it corrected itself.
|
|
110
120
|
|
|
121
|
+
## Bi-temporal timeline events
|
|
122
|
+
|
|
123
|
+
Every factual statement {{productName}} extracts from your conversations is stored as a `:TimelineEvent` node. Each event carries two separate timestamps:
|
|
124
|
+
|
|
125
|
+
- **`occurredAt`** (valid-time) — when the fact was true in the world. Set from the text itself; can reference a date in the past ("Alice joined in 1990" stores `occurredAt = 1990-01-01`).
|
|
126
|
+
- **`learnedAt`** (transaction-time) — when the system ingested this event. Always the wall-clock time of the write; never back-dated.
|
|
127
|
+
|
|
128
|
+
This distinction lets you ask two qualitatively different questions:
|
|
129
|
+
|
|
130
|
+
- *"What happened to Alice in 1990?"* — query by `occurredAt`.
|
|
131
|
+
- *"What did {{productName}} learn about Alice last Tuesday?"* — query by `learnedAt`.
|
|
132
|
+
|
|
133
|
+
`memory-compiled-truth-history` returns both fields for every timeline event on an entity under the `timelineEvents` array, alongside the compiled-truth revision history in the `revisions` array.
|
|
134
|
+
|
|
135
|
+
**Backfill:** Timeline events written before this feature was added have `learnedAt` set to their `createdAt` value by the schema migration. Events without `createdAt` (very old nodes) receive the migration run time as an approximation.
|
|
136
|
+
|
|
111
137
|
## Write doctrine
|
|
112
138
|
|
|
113
139
|
Every new node in {{productName}}'s graph is created with at least one connection to an existing node. A contact connects to the conversation or organisation it came from; a task connects to the session that raised it or the entities it will affect; a session summary connects to the conversation it summarises. A node with no connection is noise — it cannot be attributed, traversed, or explained — so the graph refuses to create one. If {{productName}} ever tries to record something without a link, the write is rejected and {{productName}} asks you to clarify where it belongs.
|