@rubytech/create-maxy-code 0.1.315 → 0.1.316

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 (47) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
  3. package/payload/platform/plugins/docs/references/admin-session.md +1 -1
  4. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  5. package/payload/platform/plugins/memory/references/schema-estate-agent.md +32 -0
  6. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  7. package/payload/platform/services/claude-session-manager/dist/http-server.js +14 -5
  8. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  9. package/payload/platform/services/webchat-channel/dist/permission.d.ts +46 -0
  10. package/payload/platform/services/webchat-channel/dist/permission.d.ts.map +1 -0
  11. package/payload/platform/services/webchat-channel/dist/permission.js +56 -0
  12. package/payload/platform/services/webchat-channel/dist/permission.js.map +1 -0
  13. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  14. package/payload/platform/services/webchat-channel/dist/server.js +47 -1
  15. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  16. package/payload/platform/templates/specialists/agents/data-manager.md +3 -1
  17. package/payload/server/public/assets/{AccessGate-B0sCa0QJ.js → AccessGate-bu988Xo-.js} +1 -1
  18. package/payload/server/public/assets/{AdminLoginScreens-C7Oaqpr6.js → AdminLoginScreens-BCYaOOuk.js} +1 -1
  19. package/payload/server/public/assets/{AdminShell-DgK7TWCI.js → AdminShell-DSjJ4Biu.js} +1 -1
  20. package/payload/server/public/assets/{Checkbox-C4m1jfdP.js → Checkbox-B4Dbvjls.js} +1 -1
  21. package/payload/server/public/assets/{OperatorConversations-z2mSY_eQ.js → OperatorConversations-XsXP7-P-.js} +1 -1
  22. package/payload/server/public/assets/{admin-DxYk1Ghu.js → admin-m0797WGA.js} +1 -1
  23. package/payload/server/public/assets/{audio-attachment-mime-BXj3DB3Y.js → audio-attachment-mime-Jm4KJ4YC.js} +1 -1
  24. package/payload/server/public/assets/{brand-BwWvCHLs.css → brand-DvttVeGB.css} +1 -1
  25. package/payload/server/public/assets/{browser-NzxOujfD.js → browser-CBjNMPsz.js} +1 -1
  26. package/payload/server/public/assets/chat-Sg-RGuV6.js +1 -0
  27. package/payload/server/public/assets/{data-CTROHvif.js → data-CEqE4BDw.js} +1 -1
  28. package/payload/server/public/assets/{graph-Dx2a6vGB.js → graph-BZNc3EXa.js} +1 -1
  29. package/payload/server/public/assets/{graph-labels-Dxqq08v6.js → graph-labels-Bj5yM9bI.js} +1 -1
  30. package/payload/server/public/assets/operator-Bph7mx87.js +1 -0
  31. package/payload/server/public/assets/page-CtWCeXdg.js +1 -0
  32. package/payload/server/public/assets/{public-cuggl7du.js → public-gxHCJCs3.js} +1 -1
  33. package/payload/server/public/assets/{public-next-apqAebbA.js → public-next-C3clISGQ.js} +1 -1
  34. package/payload/server/public/assets/{useSelectionMode-DlgEcMtA.js → useSelectionMode-BMn70cch.js} +1 -1
  35. package/payload/server/public/browser.html +6 -6
  36. package/payload/server/public/chat.html +8 -8
  37. package/payload/server/public/data.html +5 -5
  38. package/payload/server/public/graph.html +8 -8
  39. package/payload/server/public/index.html +8 -8
  40. package/payload/server/public/operator.html +10 -10
  41. package/payload/server/public/public-next.html +9 -9
  42. package/payload/server/public/public.html +7 -7
  43. package/payload/server/server.js +100 -7
  44. package/payload/server/public/assets/chat-CEQTEN5z.js +0 -1
  45. package/payload/server/public/assets/operator-BTHMTwNI.js +0 -1
  46. package/payload/server/public/assets/page-B9fQp1g9.js +0 -1
  47. /package/payload/server/public/assets/{brand-DOgCGEoD.js → brand-D8LClgr_.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.315",
3
+ "version": "0.1.316",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -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:f0677ad1f77878f3dd86ce0c1717103701ab0d7081d82ba4d9505b1922e71c9f
4
+ content-hash: sha256:4c25ba31f010fd3042621f035682a6df66d7ec88011a11984ef197f056a61b60
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -2314,7 +2314,7 @@ either is a regression.
2314
2314
  | `/session-rc-spawn` | POST `{ sessionId?, name? }`. Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
2315
2315
  | `/claude-sessions` | **Spawn surface only**. `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (the recorder loopback caller was removed; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
2316
2316
 
2317
- **Admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. A third inception lever, permission mode, is added: `account.json.adminPermissionMode` → `settings.json "permissions.defaultMode"` (the 5 composer-writable modes `default|acceptEdits|plan|auto|bypassPermissions`; `dontAsk` is out of scope). Unlike model/effort (top-level keys), this lever **deep-merges** the nested `permissions.defaultMode`, owning only that key and preserving sibling `permissions` keys (allow/deny/…) — what the binary and the spawn lifeline actually read. All three levers are now changeable from the `/chat` composer (the model is a friendly-labelled checkmark dropdown via `MODEL_DISPLAY_NAMES`, effort a Faster↔Smarter slider, mode a 5-mode checkmark dropdown), each writing its `account.json` key then `POST /reapply-levers` so the next spawn honours it; the full write path is in `.docs/admin-webchat-native-channel.md`. Beyond the composer, the maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no separate session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
2317
+ **Admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. A third inception lever, permission mode, is added: `account.json.adminPermissionMode` → `settings.json "permissions.defaultMode"` (the 5 composer-writable modes `default|acceptEdits|plan|auto|bypassPermissions`; `dontAsk` is out of scope). Unlike model/effort (top-level keys), this lever **deep-merges** the nested `permissions.defaultMode`, owning only that key and preserving sibling `permissions` keys (allow/deny/…) — what the binary and the spawn lifeline actually read. All three levers are now changeable from the `/chat` composer (the model is a friendly-labelled checkmark dropdown via `MODEL_DISPLAY_NAMES`, effort a Faster↔Smarter slider, mode a 5-mode checkmark dropdown), each writing its `account.json` key then `POST /reapply-levers` so the next spawn honours it; the full write path is in `.docs/admin-webchat-native-channel.md`. On an existing chat each picker re-seats the live session and carries the operator's current model+mode+effort so picking one never resets the others. When the live session runs in `default` ("Ask permissions") mode, a tool the agent attempts that needs approval surfaces an Allow/Deny card in the composer (tool, description, argument preview); a click sends the verdict over Claude Code's channel permission relay and the tool runs or is refused — webchat is the only interactive ask surface (WhatsApp stays text-only; Telegram has no agent channel). Beyond the composer, the maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no separate session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
2318
2318
 
2319
2319
  **Row title resolution.** Both the sidebar (`/sidebar-sessions`) and the manager's own row payload resolve a row's title in the same order: operator rename → Claude Code `ai-title` → first non-CLI user message → 8-char sessionId prefix. The operator-rename tier is the on-disk `<accountDir>/session-titles.json` (the manager's `UserTitleStore`), keyed by the CC sessionId — the sidebar reads that same file, so a write to the store lights up both surfaces with one write.
2320
2320
 
@@ -95,7 +95,7 @@ The Hono route `POST /api/admin/claude-sessions` at [`platform/ui/server/routes/
95
95
 
96
96
  The metadata pane surfaces two distinct identifier values. The three-id model was collapsed back to a single-identity contract: claude's bridge suffix and the JSONL basename UUID are two phases of one claude-side identity, not two operator-visible identifiers. The manager resolver accepts either phase on any route. The wire emits one canonical `sessionId` — whichever phase is current — and the pane shows one row.
97
97
 
98
- **Re-seat mints a new id.** Model, mode, and effort are inception-only levers — claude reads them when a session is born and the `claude rc` daemon exposes no per-session switch — so changing one on an *existing* session forks it: `/api/admin/session-reseat` pre-mints a fresh `sessionId`, the manager `/rc-spawn` fork branch runs `--resume <old> --fork-session --session-id <new> --model <model>` (copying history into the new id), and the operator lands on the fork. The fork pins the chosen model and, when supplied, the chosen `permissionMode` (pushed as `--permission-mode`, one of the 5 composer-writable modes) and `effort` (`low|medium|high|xhigh`, merged into the per-spawn inline `--settings.effortLevel`); each is validated against its allowlist before reaching the argv (a present-but-disallowed value is a 400). Both `/chat`'s composer pickers and the dashboard's per-row Re-seat control drive this one fork, for webchat and WhatsApp/Telegram sessions alike. The full write path is in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
98
+ **Re-seat mints a new id.** Model, mode, and effort are inception-only levers — claude reads them when a session is born and the `claude rc` daemon exposes no per-session switch — so changing one on an *existing* session forks it: `/api/admin/session-reseat` pre-mints a fresh `sessionId`, the manager `/rc-spawn` fork branch runs `--resume <old> --fork-session --session-id <new> --model <model>` (copying history into the new id), and the operator lands on the fork. The fork pins the chosen model and, when supplied, the chosen `permissionMode` (pushed as `--permission-mode`, one of the 5 composer-writable modes) and `effort` (`low|medium|high|xhigh`, merged into the per-spawn inline `--settings.effortLevel`); each is validated against its allowlist before reaching the argv (a present-but-disallowed value is a 400). Both `/chat`'s composer pickers and the dashboard's per-row Re-seat control drive this one fork, for webchat and WhatsApp/Telegram sessions alike. On `/chat`, every picker now carries the operator's *current* model, mode, and effort and overrides only the picked lever, so changing one never silently resets the other two (a non-writable current mode is omitted rather than rejected). When a re-seated webchat session runs in `default` ("Ask permissions") mode, a tool the agent attempts that needs approval surfaces an Allow/Deny prompt in `/chat` and blocks until the operator answers — over Claude Code's channel permission relay, the only interactive ask surface (WhatsApp stays text-only). The full write path is in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
99
99
 
100
100
  | Operator label | What it is | Manager wire field | Log key |
101
101
  |---|---|---|---|
@@ -49,7 +49,7 @@ either is a regression.
49
49
  | `/session-rc-spawn` | POST `{ sessionId?, name? }`. Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. The Sidebar navigates the opened tab to `claude.ai/code/session_<id>` on `outcome=bound`; on `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. | `POST /` |
50
50
  | `/claude-sessions` | **Spawn surface only**. `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (the recorder loopback caller was removed; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
51
51
 
52
- **Admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. A third inception lever, permission mode, is added: `account.json.adminPermissionMode` → `settings.json "permissions.defaultMode"` (the 5 composer-writable modes `default|acceptEdits|plan|auto|bypassPermissions`; `dontAsk` is out of scope). Unlike model/effort (top-level keys), this lever **deep-merges** the nested `permissions.defaultMode`, owning only that key and preserving sibling `permissions` keys (allow/deny/…) — what the binary and the spawn lifeline actually read. All three levers are now changeable from the `/chat` composer (the model is a friendly-labelled checkmark dropdown via `MODEL_DISPLAY_NAMES`, effort a Faster↔Smarter slider, mode a 5-mode checkmark dropdown), each writing its `account.json` key then `POST /reapply-levers` so the next spawn honours it; the full write path is in `.docs/admin-webchat-native-channel.md`. Beyond the composer, the maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no separate session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
52
+ **Admin session management moved entirely to claude's own interfaces** (claude.ai/code, claude desktop). A manager-owned per-account `claude rc --spawn same-dir` daemon registers the device as a Remote Control target there; the composer creates / resumes / stops / renames / archives / deletes sessions, with model + permission-mode applied at inception. The model lever is `account.json.adminModel` → `CLAUDE_CONFIG_DIR/settings.json "model"`, written by the daemon supervisor at boot; the reasoning-effort lever is `account.json.effort` → `settings.json "effortLevel"` (accepted values `low|medium|high|xhigh`; any other value, e.g. legacy `"auto"`, leaves the key unset so claude's own default governs), written by the same read-merge-write at boot. A third inception lever, permission mode, is added: `account.json.adminPermissionMode` → `settings.json "permissions.defaultMode"` (the 5 composer-writable modes `default|acceptEdits|plan|auto|bypassPermissions`; `dontAsk` is out of scope). Unlike model/effort (top-level keys), this lever **deep-merges** the nested `permissions.defaultMode`, owning only that key and preserving sibling `permissions` keys (allow/deny/…) — what the binary and the spawn lifeline actually read. All three levers are now changeable from the `/chat` composer (the model is a friendly-labelled checkmark dropdown via `MODEL_DISPLAY_NAMES`, effort a Faster↔Smarter slider, mode a 5-mode checkmark dropdown), each writing its `account.json` key then `POST /reapply-levers` so the next spawn honours it; the full write path is in `.docs/admin-webchat-native-channel.md`. On an existing chat each picker re-seats the live session and carries the operator's current model+mode+effort so picking one never resets the others. When the live session runs in `default` ("Ask permissions") mode, a tool the agent attempts that needs approval surfaces an Allow/Deny card in the composer (tool, description, argument preview); a click sends the verdict over Claude Code's channel permission relay and the tool runs or is refused — webchat is the only interactive ask surface (WhatsApp stays text-only; Telegram has no agent channel). Beyond the composer, the maxy admin UI keeps a single "New session" link (`https://claude.ai/code`, opens in a new tab) and no separate session list, viewer, controls, or model/mode picker. The daemon supervisor lives at [`platform/services/claude-session-manager/src/rc-daemon.ts`](../../../services/claude-session-manager/src/rc-daemon.ts). The `/session-defaults` route and `SpawnPreference` node were deleted with the picker. `/new-session-failure`, `/new-session-submit`, and `/claude-capabilities` are now orphaned (consumed only by the deleted NewSessionModal) — see [`.tasks/501`](../../../.tasks/) for their removal.
53
53
 
54
54
  **Row title resolution.** Both the sidebar (`/sidebar-sessions`) and the manager's own row payload resolve a row's title in the same order: operator rename → Claude Code `ai-title` → first non-CLI user message → 8-char sessionId prefix. The operator-rename tier is the on-disk `<accountDir>/session-titles.json` (the manager's `UserTitleStore`), keyed by the CC sessionId — the sidebar reads that same file, so a write to the store lights up both surfaces with one write.
55
55
 
@@ -53,6 +53,10 @@ The required-properties column above is the minimum a Listing must carry. The co
53
53
  - `floorplanUrls` — string array
54
54
  - `epcUrl` — the EPC document URL
55
55
 
56
+ **Published served-tree references (harvested by the curator after a site is published — see Filesystem ↔ graph below):**
57
+ - `brochureUrl` — the hosted HTML brochure (`https://<publicHost>/sites/<slug>/brochure.html`) when a brochure was published with the site; null when the served tree carries no `brochure.html`. Unconstrained string — no `schema.cypher` constraint or index.
58
+ - `socialTileUrls` — string array of the published Open Graph / social-share tile URLs (`https://<publicHost>/sites/<slug>/socials/og-*.jpg`); empty array when the site was published without a `socials/` subtree. Unconstrained string array — no `schema.cypher` constraint or index.
59
+
56
60
  **Provenance + search:**
57
61
  - `sourceSystem` — `loop-crm` / `zip-upload` / `manual`
58
62
  - `sourceId` — natural key in the source system (for Loop, the `loopPropertyId`)
@@ -108,3 +112,31 @@ If the source emits multiple distinct listing events tied to a single underlying
108
112
  `(:Listing)-[:LISTED_BY]->(:Organization {brandSlug})` is the mandatory parent edge that every Listing carries — it satisfies the ≥1-adjacency write-gate doctrine ([[feedback_graph_hierarchy_doctrine]]) and names the estate agency that listed the property. The target is `:Organization` keyed by `brandSlug`, not `:LocalBusiness`. `:LocalBusiness` is the per-account installer-seeded singleton (the account's own business — Real Agent itself); the write gate refuses any non-system attempt to create a second one. The agencies whose listings ingest through the curator are third-party businesses and live as `:Organization`. `[:FOR_PROPERTY]` is composed additionally when the underlying physical `:Property` node is known (full structural data captured); it is optional because Listings frequently land before Property structural data has been collected.
109
113
 
110
114
  `(:Listing)-[:DEPICTS]->(:ImageObject)` is written by the curator once per image present on the Listing. ImageObjects satisfy the ≥1-adjacency rule via this edge (Listing is the parent); they do not carry their own `LISTED_BY` edge because the Listing already does. Hybrid search expands one hop by default, so a memory-search returning a Listing also returns its DEPICTS-linked ImageObjects in the result's `related` array — no separate search call needed to assemble a property card with the right image.
115
+
116
+ ---
117
+
118
+ ## Filesystem ↔ graph (base template)
119
+
120
+ Unlike a construction job folder (operator-authored source files), the estate-agent projection is over a **published served tree** — hosting output the platform writes, not files the operator edits by hand. Each served listing lives at `<accountDir>/sites/<slug>/`, the on-disk target of `publish-site`, and is served at `https://<publicHost>/sites/<slug>/`. The graph references this tree by **hosted URL**, never by local path: a `:Listing`/`:ImageObject` URL property is the canonical reference, and the served file is the thing it points at. This mapping is the **base template** — the standard a brochure-pipeline publish projects into; it is shipped-generic, not any operator's data.
121
+
122
+ **URL ↔ path rule (deterministic).** Every served artefact resolves both ways by a single substitution: `https://<publicHost>/sites/<slug>/X` ↔ `<accountDir>/sites/<slug>/X`. The `/sites/<slug>/` segment is invariant — it is the publish target's on-disk shape mirrored into the hosted path. To resolve a graph URL to a local file, strip the `https://<publicHost>/sites/<slug>/` prefix and join the remainder onto `<accountDir>/sites/<slug>/`; to project a served file, do the reverse.
123
+
124
+ **Artefact → graph reference.** Every visitor-renderable or publicly-meaningful artefact class under `sites/<slug>/` resolves to a `:Listing` or `:ImageObject` reference:
125
+
126
+ | Served artefact | Graph reference |
127
+ |---|---|
128
+ | `index.html` — the published landing page | `:Listing.pageUrl` |
129
+ | `images/<photo>.{jpg,jpeg,png,webp}` (non-logo) | `:Listing.imageUrls[]`, `:Listing.heroImageUrl` (index 0), and one `:ImageObject.url` per photo |
130
+ | `images/*floorplan*.{jpg,png}` | `:Listing.floorplanUrls[]` (and its `:ImageObject.url`) |
131
+ | `images/epc.{jpg,png,pdf}` or `epc.*` at the root | `:Listing.epcUrl` (and its `:ImageObject.url`) |
132
+ | `brochure.html` — the hosted HTML brochure | `:Listing.brochureUrl` |
133
+ | `socials/og-*.jpg` — Open Graph / social-share tiles | `:Listing.socialTileUrls[]` |
134
+
135
+ **Served but intentionally unreferenced (tool / collateral).** These classes are part of the published bundle but carry no graph reference by design — the reconcile audit excludes them exactly as it excludes the `url-get/` cache, and their presence is never an orphan:
136
+
137
+ - `<slug>-brochure.pdf` — the downloadable form of the brochure; `brochureUrl` references the canonical `brochure.html`, so the PDF is the same artefact class, not a separate node reference.
138
+ - `socials.html`, `social-posts.md`, `og.html` — operator-only social collateral and the re-run template; not visitor-renderable, not indexable.
139
+ - `images.json` — the curator's brochure sidecar (consumed at curation time, not a renderable artefact).
140
+ - `llms.txt`, `llms-full.txt` — AEO surfaces written by `publish-site`.
141
+
142
+ A served file outside the referenced classes and outside this exclusion set is an orphan — the reconcile audit counts it in `unreachable`. `broken-refs` is scoped to **served-tree URLs only**: a `:Listing`/`:ImageObject` URL that matches the `https://<publicHost>/sites/<slug>/` prefix but resolves to no served file (slug rename, un-republished listing) is counted in `broken-refs`. Externally-hosted URLs are outside the served tree and outside this audit — a Loop listing's `b-cdn.net` `:ImageObject.url` or its Rightmove/Zoopla/agent-site `pageUrl` carries no `sites/<slug>/` prefix, the URL↔path rule cannot resolve it, and it is never counted as broken. Map a served file to its nearest canonical reference; invent no node or edge type absent from this schema.
@@ -1 +1 @@
1
- {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAY3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAsBzB,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAgFhE,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAwGD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAiBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAwJD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAmBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CA4sEpD"}
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAY3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAsBzB,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAgFhE,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAwGD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAiBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAwJD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAmBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAstEpD"}
@@ -1747,8 +1747,9 @@ export function buildHttpApp(deps) {
1747
1747
  const sessions = [...seen.entries()].map(([sessionId, pid]) => ({ sessionId, pid }));
1748
1748
  return c.json({ sessions });
1749
1749
  });
1750
- // Task 543 — fire-and-forget `claude --remote-control [name] [--session-id <sid>]`
1751
- // spawn for the admin sessions pane. The new PTY registers itself in
1750
+ // Task 543 — fire-and-forget `claude --remote-control [--session-id <sid>]`
1751
+ // spawn for the admin sessions pane. (Task 945 removed the `name` positional —
1752
+ // `name` is a display label, never a CLI prompt; do not re-add it to argv.) The new PTY registers itself in
1752
1753
  // claude.ai/code as its own Remote Control entry; reconciliation with the
1753
1754
  // rc-daemon is out of scope. The PID lands in
1754
1755
  // `<CLAUDE_CONFIG_DIR>/sessions/<pid>.json` via claude's own bootstrap,
@@ -1956,8 +1957,12 @@ export function buildHttpApp(deps) {
1956
1957
  const existingJsonlPath = sessionId ? findExistingJsonlForSessionId(deps.claudeConfigDir, sessionId) : null;
1957
1958
  const mode = existingJsonlPath ? 'resume' : 'fresh';
1958
1959
  const argv = ['--remote-control'];
1959
- if (name)
1960
- argv.push(name);
1960
+ // Task 945 — `name` is the row's display label, never a prompt. It must NOT
1961
+ // be pushed as a positional: the CLI treats a bare positional as the initial
1962
+ // prompt, so a long label (e.g. a first-message-derived title) became a
1963
+ // multi-kilobyte prompt and the remote-control bind timed out. The sole
1964
+ // positional is `initialMessage` (pushed below). `name` stays in the request
1965
+ // body and the log lines for observability only.
1961
1966
  // Task 889 — append-system-prompt segments are accumulated and pushed once
1962
1967
  // (below, after channel resolution) so the re-seat model line and the
1963
1968
  // authenticated-identity line share a single flag.
@@ -2166,7 +2171,11 @@ export function buildHttpApp(deps) {
2166
2171
  // here is enough for an operator to reproduce by hand. The wrapped
2167
2172
  // argv is fully reconstructible from this line + the spawn adapter
2168
2173
  // source (Task 250 / 556).
2169
- deps.logger(`[rc-spawn] op=argv unitToken=${unitToken} cwd=${deps.spawnCwd} permissionMode=${effectiveRcPermissionMode} argv=${JSON.stringify([deps.claudeBin, ...argv])}`);
2174
+ // Task 945 record the byte count of the sole positional actually placed in
2175
+ // argv (the trailing `initialMessage`, else 0) so a future oversized positional
2176
+ // is visible without reconstructing it from the full argv dump.
2177
+ const positionalBytes = initialMessage ? Buffer.byteLength(initialMessage, 'utf8') : 0;
2178
+ deps.logger(`[rc-spawn] op=argv unitToken=${unitToken} cwd=${deps.spawnCwd} permissionMode=${effectiveRcPermissionMode} positionalBytes=${positionalBytes} argv=${JSON.stringify([deps.claudeBin, ...argv])}`);
2170
2179
  emitRcLife(deps.logger, 'argv', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
2171
2180
  cwd: deps.spawnCwd,
2172
2181
  argv: JSON.stringify([deps.claudeBin, ...argv]),