@rubytech/create-realagent-code 0.1.17 → 0.1.18
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__/onboarding-state-readback.test.js +61 -0
- package/dist/index.js +42 -0
- package/dist/onboarding-readback.js +27 -0
- package/package.json +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +23 -0
- package/payload/platform/scripts/seed-neo4j.sh +35 -0
- package/payload/server/public/assets/{Checkbox-nrf4ISU0.js → Checkbox-BmlrSRF8.js} +1 -1
- package/payload/server/public/assets/{admin-BctPxbjB.js → admin-Drvl0Okz.js} +53 -53
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DZI73ap7.js → architectureDiagram-Q4EWVU46-DU8MnqOj.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BQQz9YNZ.js → blockDiagram-DXYQGD6D-DwBZc1na.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-gl8-XVLH.js → c4Diagram-AHTNJAMY-C9ZHreVX.js} +1 -1
- package/payload/server/public/assets/channel-Boz4UHN2.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-839etdKR.js → chunk-336JU56O-DNXqHk42.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-hyvaLE5p.js → chunk-426QAEUC-DOLKkQGn.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DEIYWdpd.js → chunk-4TB4RGXK-l8iZx-gQ.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-zWevOyjc.js → chunk-5FUZZQ4R-DQwRtUdO.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-CL9KWSZH.js → chunk-5PVQY5BW-CvvoBJnn.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-D91vGp64.js → chunk-EDXVE4YY-DV1J4-LR.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-DApK4iuk.js → chunk-ENJZ2VHE-Co6qpIQl.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BOjV-nTe.js → chunk-ICPOFSXX-9v9O_mwr.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-D3Cv5Z_Z.js → chunk-OYMX7WX6-D2X1NuKZ.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-C92E-iRU.js → chunk-U2HBQHQK-DmqWEsN2.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-DohG6qWK.js → chunk-X2U36JSP-C0b2a6Bq.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-CyeLVSjf.js → chunk-YZCP3GAM-BdBAquWg.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-D7R-lONY.js → chunk-ZZ45TVLE-C1AFspLM.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CRA6E97A.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-VnieTvEm.js +1 -0
- package/payload/server/public/assets/clone-6YhZHo8b.js +1 -0
- package/payload/server/public/assets/{dagre-DjhovTZd.js → dagre-7eiQzAHj.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-DFeRlQuy.js → dagre-KV5264BT-a88ylEXY.js} +1 -1
- package/payload/server/public/assets/data-Dq_if_B4.js +1 -0
- package/payload/server/public/assets/{device-url-actions-CE3A1UDw.js → device-url-actions-_s-UgHa3.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-DsmRGnVL.js → diagram-5BDNPKRD-XuINnSy-.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-CVSK-mLR.js → diagram-G4DWMVQ6-B93iSQ8a.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DMN94Pe-.js → diagram-MMDJMWI5-Gcoj967k.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-DaD4mLMc.js → diagram-TYMM5635-C2BKnsAF.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-BUkZ2Iq1.js → erDiagram-SMLLAGMA-DwbOuflI.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-DW8DX_ge.js → flowDiagram-DWJPFMVM-CEExhdxC.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DWaRL6__.js → ganttDiagram-T4ZO3ILL-kYNYeUK-.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BaPTFtVx.js → gitGraphDiagram-UUTBAWPF-D3X2eJPE.js} +1 -1
- package/payload/server/public/assets/graph-CNFkzAKU.js +1 -0
- package/payload/server/public/assets/{graph-labels-BRtJE9AE.js → graph-labels-C6ZZPglH.js} +1 -1
- package/payload/server/public/assets/{graphlib-BUhb3hPU.js → graphlib-_S6i_Jn2.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-Ch6CE3GO.js → infoDiagram-42DDH7IO-CQx0vDcC.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DApFr2KO.js → ishikawaDiagram-UXIWVN3A-0eZUgqUP.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-D72xl-VA.js → journeyDiagram-VCZTEJTY-D-B2Kd_J.js} +1 -1
- package/payload/server/public/assets/jsx-runtime-CtqEPPN5.css +1 -0
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-TuAvkCJU.js → kanban-definition-6JOO6SKY-BmLn-OEz.js} +1 -1
- package/payload/server/public/assets/{line-Cr3lHgh8.js → line-h25nWPBw.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-BvbEd4_6.js → mermaid-parser.core-CXXeaSZi.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-CSIEcw1L.js → mermaid.core-BjFfgEHL.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CNLvqgk-.js → mindmap-definition-QFDTVHPH-Dql4ILoK.js} +1 -1
- package/payload/server/public/assets/{page-B_80xGrM.js → page-CdWWweCx.js} +1 -1
- package/payload/server/public/assets/{page-BcnqM490.js → page-D20UnO_r.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CSOsdFn6.js → pieDiagram-DEJITSTG-nYaoTCKZ.js} +1 -1
- package/payload/server/public/assets/{public-DGrCAqZN.js → public-CXgyLdJU.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Bsxz9S58.js → quadrantDiagram-34T5L4WZ-XG8xivm9.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-BZRrlQlh.js → requirementDiagram-MS252O5E-C2GzfT-6.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-C-W-Az7g.js → sankeyDiagram-XADWPNL6-3aI78p2X.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DCZPAj4-.js → sequenceDiagram-FGHM5R23-CvaNRYuS.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-C3wODMGb.js → stateDiagram-FHFEXIEX-DHT2Zyvj.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-YmtuS9BN.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-TRzSKinM.js → timeline-definition-GMOUNBTQ-DqPjDUku.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DSKZVM8N.js → vennDiagram-DHZGUBPP-lQB1LgjH.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BRXL08eb.js → wardleyDiagram-NUSXRM2D-sxSMxkwm.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CgWMOf0l.js → xychartDiagram-5P7HB3ND-4-dvvfSD.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +91 -6
- package/payload/server/public/assets/channel-BIMyzzFT.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BAfXNwa9.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D5bE1GaW.js +0 -1
- package/payload/server/public/assets/clone-DOH_suVb.js +0 -1
- package/payload/server/public/assets/data-DzTaKq-r.js +0 -1
- package/payload/server/public/assets/graph-dgoq2zvY.js +0 -1
- package/payload/server/public/assets/jsx-runtime-BgXAk35j.css +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Ch6qbhpm.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-Bz7aoCi7.js → jsx-runtime-BSJRynxp.js} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Task 033 — install-invariant for OnboardingState seed.
|
|
2
|
+
//
|
|
3
|
+
// The installer re-reads Neo4j after seed-neo4j.sh to verify the
|
|
4
|
+
// OnboardingState node landed. The parser turns cypher-shell's plain-
|
|
5
|
+
// format output into a tri-state outcome consumed by the loud-fail
|
|
6
|
+
// branch in src/index.ts. These tests fence the three outcomes the
|
|
7
|
+
// installer logs name: present / missing / unreachable.
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { classifyOnboardingReadBack } from "../onboarding-readback.js";
|
|
11
|
+
test("non-zero exit → unreachable, with stderr tail captured", () => {
|
|
12
|
+
const outcome = classifyOnboardingReadBack({
|
|
13
|
+
status: 1,
|
|
14
|
+
stdout: "",
|
|
15
|
+
stderr: "Connection refused: bolt://localhost:7687",
|
|
16
|
+
});
|
|
17
|
+
assert.equal(outcome.kind, "unreachable");
|
|
18
|
+
if (outcome.kind === "unreachable") {
|
|
19
|
+
assert.match(outcome.stderrTail, /Connection refused/);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
test("header row only (no match) → missing", () => {
|
|
23
|
+
// cypher-shell --format plain emits the column header even when zero rows
|
|
24
|
+
// matched. The seed-or-fail contract treats header-only as the loud-fail.
|
|
25
|
+
const outcome = classifyOnboardingReadBack({
|
|
26
|
+
status: 0,
|
|
27
|
+
stdout: "currentStep\n",
|
|
28
|
+
stderr: "",
|
|
29
|
+
});
|
|
30
|
+
assert.equal(outcome.kind, "missing");
|
|
31
|
+
});
|
|
32
|
+
test("data row present → present, currentStep relayed verbatim", () => {
|
|
33
|
+
const outcome = classifyOnboardingReadBack({
|
|
34
|
+
status: 0,
|
|
35
|
+
stdout: "currentStep\n0\n",
|
|
36
|
+
stderr: "",
|
|
37
|
+
});
|
|
38
|
+
assert.equal(outcome.kind, "present");
|
|
39
|
+
if (outcome.kind === "present") {
|
|
40
|
+
assert.equal(outcome.currentStep, "0");
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
test("empty stdout + zero exit → missing (defensive: cypher-shell flushed nothing)", () => {
|
|
44
|
+
const outcome = classifyOnboardingReadBack({
|
|
45
|
+
status: 0,
|
|
46
|
+
stdout: "",
|
|
47
|
+
stderr: "",
|
|
48
|
+
});
|
|
49
|
+
assert.equal(outcome.kind, "missing");
|
|
50
|
+
});
|
|
51
|
+
test("trailing whitespace tolerated on present row", () => {
|
|
52
|
+
const outcome = classifyOnboardingReadBack({
|
|
53
|
+
status: 0,
|
|
54
|
+
stdout: "currentStep\n0 \n\n",
|
|
55
|
+
stderr: "",
|
|
56
|
+
});
|
|
57
|
+
assert.equal(outcome.kind, "present");
|
|
58
|
+
if (outcome.kind === "present") {
|
|
59
|
+
assert.equal(outcome.currentStep, "0");
|
|
60
|
+
}
|
|
61
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, rea
|
|
|
4
4
|
import { resolve, join, dirname } from "node:path";
|
|
5
5
|
import { randomBytes } from "node:crypto";
|
|
6
6
|
import { resolveInstallPortFromFs, buildMaxyUnitFile, buildClaudeSessionManagerUnitFile } from "./port-resolution.js";
|
|
7
|
+
import { classifyOnboardingReadBack } from "./onboarding-readback.js";
|
|
7
8
|
import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js";
|
|
8
9
|
import { findPeerBrandOnDefaultNeo4jPort } from "./peer-brand-detect.js";
|
|
9
10
|
import { requireSupportedPlatform } from "./platform-detect.js";
|
|
@@ -2289,6 +2290,47 @@ function setupAccount() {
|
|
|
2289
2290
|
logFile(` [neo4j] passing NEO4J_URI=${neo4jUri} to seed`);
|
|
2290
2291
|
shell("bash", [seedScript], { cwd: INSTALL_DIR, env: neo4jEnv });
|
|
2291
2292
|
}
|
|
2293
|
+
// Task 033 — install-invariant: OnboardingState must exist post-seed.
|
|
2294
|
+
// Loud-fails (exit 1) on miss because the first admin session has nothing
|
|
2295
|
+
// to read otherwise: loadOnboardingStep returns -1 (no node), the chat
|
|
2296
|
+
// tries to drive the 9-step flow against missing state, and step
|
|
2297
|
+
// advancements have nowhere to land. Symmetric to Task 904's
|
|
2298
|
+
// [install-invariant] line — log-and-continue isn't enough here because
|
|
2299
|
+
// the gap silently breaks every fresh install. Idempotent on re-runs:
|
|
2300
|
+
// the seed's MERGE leaves the node untouched.
|
|
2301
|
+
const accountId = resolveInstallAccountId();
|
|
2302
|
+
if (accountId) {
|
|
2303
|
+
assertOnboardingStateSeeded(accountId, neo4jUri, password);
|
|
2304
|
+
}
|
|
2305
|
+
else {
|
|
2306
|
+
console.log(" [install-invariant] onboarding-state-check SKIPPED reason=no-account-discovered");
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
// Task 033 — Neo4j read-back assertion. Runs cypher-shell against the
|
|
2310
|
+
// brand's Neo4j and confirms an OnboardingState{accountId} node exists.
|
|
2311
|
+
// Loud-fail exit on miss / Neo4j unreachable so the installer logs name
|
|
2312
|
+
// the exact symptom the next run has to fix.
|
|
2313
|
+
function assertOnboardingStateSeeded(accountId, neo4jUri, password) {
|
|
2314
|
+
const TAG = "[install-invariant]";
|
|
2315
|
+
const cypher = `MATCH (o:OnboardingState {accountId: '${accountId}'}) RETURN o.currentStep AS currentStep;`;
|
|
2316
|
+
const result = spawnSync("cypher-shell", ["-u", "neo4j", "-p", password, "-a", neo4jUri, "--format", "plain", cypher], { stdio: "pipe", encoding: "utf-8", timeout: 10_000 });
|
|
2317
|
+
const outcome = classifyOnboardingReadBack({
|
|
2318
|
+
status: result.status,
|
|
2319
|
+
stdout: result.stdout ?? "",
|
|
2320
|
+
stderr: result.stderr ?? "",
|
|
2321
|
+
});
|
|
2322
|
+
if (outcome.kind === "unreachable") {
|
|
2323
|
+
console.error(` ${TAG} onboarding-state-UNREACHABLE accountId=${accountId} exit=${result.status} stderr=${JSON.stringify(outcome.stderrTail)}`);
|
|
2324
|
+
logFile(` ${TAG} onboarding-state-UNREACHABLE accountId=${accountId} stderr=${outcome.stderrTail}`);
|
|
2325
|
+
throw new Error(`OnboardingState read-back failed: cypher-shell exit=${result.status}`);
|
|
2326
|
+
}
|
|
2327
|
+
if (outcome.kind === "missing") {
|
|
2328
|
+
console.error(` ${TAG} onboarding-state-MISSING accountId=${accountId}`);
|
|
2329
|
+
logFile(` ${TAG} onboarding-state-MISSING accountId=${accountId}`);
|
|
2330
|
+
throw new Error(`OnboardingState missing for accountId=${accountId} after seed-neo4j.sh`);
|
|
2331
|
+
}
|
|
2332
|
+
console.log(` ${TAG} onboarding-state-present accountId=${accountId} currentStep=${outcome.currentStep}`);
|
|
2333
|
+
logFile(` ${TAG} onboarding-state-present accountId=${accountId} currentStep=${outcome.currentStep}`);
|
|
2292
2334
|
}
|
|
2293
2335
|
// ---------------------------------------------------------------------------
|
|
2294
2336
|
// Tunnel script shortcuts
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Task 033 — pure parser for the OnboardingState read-back assertion.
|
|
2
|
+
//
|
|
3
|
+
// Extracted into a dedicated module (not src/index.ts) so the test
|
|
4
|
+
// suite can import it without triggering index's brand.json-at-load
|
|
5
|
+
// side effect. The installer's loud-fail branches at
|
|
6
|
+
// `assertOnboardingStateSeeded` consume the tri-state outcome.
|
|
7
|
+
/**
|
|
8
|
+
* Classify cypher-shell --format plain output into one of three states:
|
|
9
|
+
*
|
|
10
|
+
* - `unreachable` — non-zero exit (auth, network, syntax). Stderr tail
|
|
11
|
+
* (last 200 chars) is preserved so the install log carries the
|
|
12
|
+
* symptom verbatim.
|
|
13
|
+
* - `missing` — exit 0 but no data row beyond the header. cypher-shell
|
|
14
|
+
* prints the column name even on a zero-match query.
|
|
15
|
+
* - `present` — exit 0 with at least one data row. `currentStep` is the
|
|
16
|
+
* first field on row 2.
|
|
17
|
+
*/
|
|
18
|
+
export function classifyOnboardingReadBack(input) {
|
|
19
|
+
if (input.status !== 0) {
|
|
20
|
+
return { kind: "unreachable", stderrTail: input.stderr.trim().slice(-200) };
|
|
21
|
+
}
|
|
22
|
+
const lines = input.stdout.trim().split("\n").filter((l) => l.length > 0);
|
|
23
|
+
if (lines.length < 2) {
|
|
24
|
+
return { kind: "missing" };
|
|
25
|
+
}
|
|
26
|
+
return { kind: "present", currentStep: lines[1].trim() };
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -39,6 +39,29 @@ This installs all dependencies (Node.js, Neo4j, Cloudflare tunnel, Claude Code),
|
|
|
39
39
|
6. Starts the {{productName}} web server on port 19200
|
|
40
40
|
7. Configures systemd so everything restarts automatically if the Pi reboots
|
|
41
41
|
|
|
42
|
+
## First admin session — onboarding handover
|
|
43
|
+
|
|
44
|
+
After install, the first time you open the admin URL, {{productName}} walks you through a 9-step onboarding flow: plugin selection, output style, thinking-view, timezone, persona, Cloudflare, Anthropic API key, and the business-profile capture. The flow is gated on a single piece of Neo4j state, an `OnboardingState{accountId, currentStep}` node:
|
|
45
|
+
|
|
46
|
+
- `seed-neo4j.sh` writes the node at install time with `currentStep=0`. The installer re-reads it before exiting; a missing node or an unreachable Neo4j fails the install loudly (`[install-invariant] onboarding-state-MISSING` or `onboarding-state-UNREACHABLE`).
|
|
47
|
+
- Every admin session-create reads `currentStep`. Anything below 9 keeps `onboarding_complete=false` on `/api/health` and `/api/admin/session`, and the chat opens on the next step's component (multi-select, dropdown, etc.).
|
|
48
|
+
- The first input on a freshly-spawned admin claude session is prepended with an `<onboarding-state currentStep="N">` directive that tells the agent to call `skill-load skillName=onboarding`. Resumed sessions skip this prepend so the agent doesn't re-ask the same step.
|
|
49
|
+
- If Neo4j is unreachable at session-create, the prepend becomes a loud-fail block (`graphUnreachable="true"`) and `onboarding_complete` is reported false — never silently skipped.
|
|
50
|
+
|
|
51
|
+
Diagnostic command on the Pi (substitute the brand's Neo4j port from `~/.maxy/.env` or `~/.realagent/.env`):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cypher-shell -a bolt://localhost:<brand-neo4j-port> \
|
|
55
|
+
"MATCH (o:OnboardingState) RETURN o.accountId, o.currentStep"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Failure signals to grep in `~/.maxy/logs/server.log` (or `~/.realagent/logs/server.log`):
|
|
59
|
+
|
|
60
|
+
- missing `[onboarding-seed]` line in install output
|
|
61
|
+
- `[install-invariant] onboarding-state-MISSING`
|
|
62
|
+
- `[onboarding-gate] step=null complete=true` (the pre-Task-033 bug)
|
|
63
|
+
- missing `[skill-load] name=onboarding` while `[onboarding-gate]` reports `complete=false`
|
|
64
|
+
|
|
42
65
|
## Service Management
|
|
43
66
|
|
|
44
67
|
{{productName}} runs via systemd and starts automatically on boot. You don't need to start it manually. To check if it's running, ask {{productName}} "Check system status."
|
|
@@ -541,4 +541,39 @@ BACKFILL_EOF
|
|
|
541
541
|
echo " [backfill] $BACKFILL_RESULT"
|
|
542
542
|
fi
|
|
543
543
|
|
|
544
|
+
# ------------------------------------------------------------------
|
|
545
|
+
# 4. Seed OnboardingState (Task 033 — maxy-code)
|
|
546
|
+
# ------------------------------------------------------------------
|
|
547
|
+
# The first admin session reads OnboardingState.currentStep to decide whether
|
|
548
|
+
# the chat opens on step 1 of the 9-step onboarding flow or on a free-form
|
|
549
|
+
# greeting. Pre-Task-033 the node was never written at seed, so the post-PIN
|
|
550
|
+
# session-create's loadOnboardingStep returned -1 (no node) which used to
|
|
551
|
+
# conflate with null (Neo4j unreachable) and silently report
|
|
552
|
+
# onboardingComplete:true — the operator was dropped into the admin agent
|
|
553
|
+
# with no plugin selection, output-style, timezone, SOUL, Cloudflare,
|
|
554
|
+
# Anthropic-key, or business-profile setup.
|
|
555
|
+
#
|
|
556
|
+
# Keyed on accountId, not userId — fresh installs reach the seed before
|
|
557
|
+
# users.json exists (PIN is set later by the onboarding flow itself).
|
|
558
|
+
# MERGE is idempotent: re-runs leave currentStep untouched, refreshing only
|
|
559
|
+
# updatedAt.
|
|
560
|
+
SEED_NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
561
|
+
echo "==> Seeding OnboardingState for accountId=$ACCOUNT_ID"
|
|
562
|
+
ONBOARDING_SEED_RESULT=$("$CYPHER_SHELL" -u "$NEO4J_USER" -p "$NEO4J_PASSWORD" -a "$NEO4J_URI" --format plain << CYPHER_EOF
|
|
563
|
+
MERGE (o:OnboardingState {accountId: '$ACCOUNT_ID'})
|
|
564
|
+
ON CREATE SET o.currentStep = 0,
|
|
565
|
+
o.createdAt = '$SEED_NOW',
|
|
566
|
+
o.updatedAt = '$SEED_NOW'
|
|
567
|
+
ON MATCH SET o.updatedAt = '$SEED_NOW'
|
|
568
|
+
RETURN o.currentStep AS currentStep, o.createdAt = '$SEED_NOW' AS created;
|
|
569
|
+
CYPHER_EOF
|
|
570
|
+
)
|
|
571
|
+
ONBOARDING_STEP=$(echo "$ONBOARDING_SEED_RESULT" | awk 'NR==2 {print $1}')
|
|
572
|
+
ONBOARDING_CREATED=$(echo "$ONBOARDING_SEED_RESULT" | awk 'NR==2 {print $2}')
|
|
573
|
+
if [ "$ONBOARDING_CREATED" = "true" ]; then
|
|
574
|
+
echo " [onboarding-seed] accountId=$ACCOUNT_ID currentStep=$ONBOARDING_STEP idempotent=false"
|
|
575
|
+
else
|
|
576
|
+
echo " [onboarding-seed] accountId=$ACCOUNT_ID currentStep=$ONBOARDING_STEP idempotent=true"
|
|
577
|
+
fi
|
|
578
|
+
|
|
544
579
|
echo " Done."
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-
|
|
1
|
+
import{t as e}from"./jsx-runtime-BSJRynxp.js";var t=e();function n({checked:e,onChange:n,label:r,disabled:i}){return(0,t.jsxs)(`label`,{className:`maxy-checkbox${i?` maxy-checkbox--disabled`:``}`,children:[(0,t.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>n(e.target.checked),disabled:i}),(0,t.jsx)(`span`,{className:`maxy-checkbox__box`,children:`✱`}),r&&(0,t.jsx)(`span`,{className:`maxy-checkbox__label`,children:r})]})}export{n as t};
|