@mindrian_os/install 1.13.0-beta.12 → 1.13.0-beta.13
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +42 -0
- package/commands/auto-explore.md +1 -0
- package/commands/doctor.md +1 -1
- package/commands/operator.md +1 -1
- package/commands/setup.md +7 -3
- package/lib/core/active-plugin-root.cjs +71 -6
- package/lib/core/brain-client.cjs +451 -36
- package/lib/core/cache-prune.cjs +208 -0
- package/lib/core/navigation/memory-events.cjs +17 -1
- package/lib/core/navigation/neighborhood.cjs +5 -4
- package/lib/core/navigation/packet.cjs +87 -1
- package/lib/core/navigation.cjs +6 -0
- package/lib/core/resolve-brain-key.cjs +201 -0
- package/lib/memory/run-feynman-tests.cjs +85 -0
- package/lib/memory/security-trifecta.test.cjs +23 -6
- package/package.json +4 -1
- package/skills/brain-connector/SKILL.md +9 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mos",
|
|
3
3
|
"description": "MindrianOS -- Your AI innovation co-founder. Larry thinks with you through PWS methodology, builds your Data Room as you explore, and chains frameworks intelligently. Install and go.",
|
|
4
|
-
"version": "1.13.0-beta.
|
|
4
|
+
"version": "1.13.0-beta.13",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jonathan Sagir",
|
|
7
7
|
"url": "https://mindrian.ai"
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
<!-- When onboarding: true, the onboard_steps list is shown to returning users in the What's New flow -->
|
|
10
10
|
<!-- This allows new releases to automatically surface relevant guidance without code changes -->
|
|
11
11
|
|
|
12
|
+
## [1.13.0-beta.13] - 2026-05-13
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Install-state contract (Phase 123 Plans 02 + 03 -- HARNESS-123-05..10).** **One record** is the truth (`~/.mindrian/install-state.json`, written by `scripts/session-start` as the single writer in earliest steps; full D-04 snapshot incl. the 4 version-of-record cross-check values). **One manifest** says what should be on disk (`data/deployment-surfaces.json`, 6 hand-maintained surfaces with the D-07 schema -- id / `$HOME`-tokenized path / owner / topology_scope / check_kind / expected / reconcile / remediation; reused `data/` layout convention from Phase 122). **One command** enforces the contract: `mindrian-os doctor` gains two new drift classes -- **class I** (install-state record present + internally consistent + topology classification + 6-way version-of-record consistency tolerating non-semver 4-component versions like `1.12.5.1` via string-equality) + **class J** (deployment-surface manifest reconciliation with `path_within_file` extraction for JSON sub-fields like `settings.json.statusLine.command`) -- under one new flag `--install-state`; `--all` activates both. **Bug 7 dies**: a marketplace-cache-only install is a *healthy* topology, not drift -- "no legacy clone dir on a marketplace box" is expected, not a finding. Aggressive `doctor --fix` with hard guardrails (D-13): auto-recover missing record + drifted owned surfaces + wrong `~/.mindrian-last-version`; legacy-clone migration is backup-then-verify-then-remove and REFUSES on a dev-clone, uncommitted/unpushed work, or `MINDRIAN_OS_ROOT` pointing at the legacy dir; conservative `installed_plugins.json` repair (repoint at newest valid marketplace-cache dir, never wholesale rewrite, always back up first); 3 flag-only cases (`topology: not-found`, `$PATH` entry vanished, statusline-renders-wrong-version) reported with explicit remediation strings. `lib/core/active-plugin-root.cjs` extended with a `topology` field exposing `marketplace-cache | dev-clone | legacy | not-found`. Hermetic Wave-0 fixtures: `tests/test-install-state-record.cjs` (6/6) + `tests/test-doctor-class-i.cjs` (11/11) + `tests/test-doctor-class-j.cjs` (8/8) all green. (`scripts/session-start`, `lib/core/active-plugin-root.cjs`, `data/deployment-surfaces.json` [new], `data/ROOM.md`, `scripts/doctor.cjs`, `tests/test-install-state-record.cjs` [new], `tests/test-doctor-class-i.cjs` [new], `tests/test-doctor-class-j.cjs` [new], `lib/memory/run-feynman-tests.cjs`.)
|
|
17
|
+
|
|
18
|
+
- **`mindrian-os doctor --acceptance` release-gate command (Phase 123 Plan-04 -- HARNESS-123-11 + HARNESS-123-12).** Seven-point contract: (1) install-state record present + matches a live spot-check; (2) every owned deployment surface reconciled; (3) version-of-record consistent across `plugin.json` / `package.json` / CHANGELOG top entry / git tag / marketplace `source.ref` / published npm version; (4) `npx @mindrian_os/install` round-trip works (`mktemp -d`-backed `HOME`-sandbox -- the live install is never clobbered; `--light-npx` flag for slow networks asserts `npm view ... && npx ... --help` instead); (5) `doctor --all` exits 0. Two sub-modes: `--pre-tag` runs the 5 points knowable BEFORE the release (1, 2, 3-repo-half, 4-wrap-via-verify-release, 5); full `--acceptance` adds the 2 post-publish points (version-of-record-published + npx round-trip). Wraps `scripts/verify-release` -- no duplication. Wired into `scripts/release.sh` at Step 6.6 (`--pre-tag` before the tag) and Step 9.6 (full after the push); both HARD aborts, no override. Orchestration is node, shell-agnostic. "Release infrastructure ALWAYS ships as a beta validated by an external operator" now *means* "the operator ran `mindrian-os doctor --acceptance`, all green" -- not "the operator eyeballed the statusline." Hermetic Wave-0 test `tests/test-doctor-acceptance.cjs` (6/6) green. (`scripts/doctor.cjs`, `scripts/release.sh`, `tests/test-doctor-acceptance.cjs` [new], `scripts/release-beta-smoke.sh` [deleted].)
|
|
19
|
+
|
|
20
|
+
- **`scripts/release.sh` owns ALL version bumps incl. pre-releases (Phase 123 Plan-01 -- HARNESS-123-01..04).** Pre-release algebra via the `semver` npm package added as a **devDependency** (NOT a runtime dep -- stays out of the `files` allowlist; the published `@mindrian_os/install` tarball is still zero-runtime-dep). New flags: `--prerelease` (`beta.N -> beta.N+1` via `semver.inc(v, 'prerelease', 'beta')`); `--finalize` (promote a beta to its core via `semver.inc(v, 'patch')` -- which *strips* the suffix, so `1.13.0-beta.11 -> 1.13.0`, NOT `1.13.1`); `--start-prerelease <core> <channel>` (open a fresh series via `semver.inc(v, 'preminor', 'beta')`); `--allow-ahead` (escape hatch for the dirty-repo guard). **TWO-COMMIT next-bump form** (per RESEARCH override 1 -- verified against Claude Code's Version Management spec; `plugin.json` wins over the marketplace entry for installed-version reporting): commit A finalizes `CHANGELOG [vN]`, sets `plugin.json` + `package.json` to `vN`, the `vN` git tag points at commit A; commit B bumps to `vN+1` + resets the CHANGELOG `[Unreleased] -- vN+1` heading; `main` HEAD lands on commit B. `marketplace.json` `version` + `source.ref` pin to `vN` -- so an install via `ref: vN` checks out commit A and self-reports `vN`. **Dirty-repo / ahead-of-origin guard**: before pushing, `release.sh` snapshots `git log origin/main..HEAD --oneline`, prints it, aborts unless the only commits ahead are the release commits it just made (or `--allow-ahead` set); blocks on dirty tracked files except the bumped ones; no author heuristics. **Step 9.5 renamed** `@mindrian_os/cli` -> `@mindrian_os/install` (publish target + `next`/`latest` dist-tag derivation + `npm pack --dry-run` payload-allowlist gate + recovery instructions). Hermetic Wave-0 test `tests/test-release-bump-algebra.cjs` (7/7) green; `tests/test-release-npm-gate.sh` updated to the `@mindrian_os/install` expectations (6/6 gates green). beta.13 is the first `release.sh`-cut pre-release after the run of hand-rolled beta.10 / 11 / 12. (`scripts/release.sh`, `package.json`, `tests/test-release-bump-algebra.cjs` [new], `tests/test-release-npm-gate.sh`.)
|
|
21
|
+
|
|
22
|
+
- **Cache pruning on update (Phase 123 Plan-05 -- HARNESS-123-13).** `lib/core/cache-prune.cjs` keeps the active version + N=2 most recent `<pluginsDir>/cache/<marketplace>/mos/<version>/` dirs; NEVER deletes the active (belt-and-suspenders -- the active is unconditionally in the keep-set regardless of mtime); skips entirely if `installed_plugins.json` is missing, unparseable, or has no `mos@mindrian-marketplace` entry. Runs in `scripts/session-start` on version change (best-effort, `|| true`) AND in `scripts/doctor.cjs::performClassJFix` unconditionally on `--fix`. Hermetic Wave-0 test `tests/test-cache-prune.cjs` (6/6) green. (`lib/core/cache-prune.cjs` [new], `scripts/session-start`, `scripts/doctor.cjs`, `tests/test-cache-prune.cjs` [new].)
|
|
23
|
+
|
|
24
|
+
- **Phase 123 Plan-07 -- single Brain-key resolver + positive session-start status (HARNESS-123-15 + HARNESS-123-16).** Three independent Brain-key lookups (`brain-client.cjs::getApiKey`, `scripts/session-start`'s shell test of `MINDRIAN_BRAIN_KEY`, the `brain-connector` skill's detection order) are collapsed into one source of truth, `lib/core/resolve-brain-key.cjs`. The resolver mirrors `lib/core/active-plugin-root.cjs`'s shape (`{ key, source, available, reason }`) and order (env -> `~/.mindrian.env` -> CWD `.env` -> not-found, the D-31 precedence); SEC-02 POSIX `0o077` permission rejection routes through an explicit `reason` string -- never a silent null. `brain-client.cjs::getApiKey()` is now a one-liner delegating to the resolver (the previous inline 3-path lookup is gone; the docstring is fixed; `Authorization: Bearer` at L218 + L279 and the `BRAIN_REQUEST_TIMEOUT_MS` / `AbortSignal.timeout` / memoized `schema()` / `async function ask` precondition are all upstream of this and untouched). `scripts/session-start`'s Brain block (~L1290-1313) replaces the pre-Plan-7 MCP-centric WARN that tested only the shell env var with a positive 3-case status line: `Brain: HTTP client active (mindrian-brain.onrender.com)` when the key resolves; `Brain: NOT loaded -- permissions too open: ... (run: chmod 600 ~/.mindrian.env)` when SEC-02 rejects; `Brain: not configured (Tier 0)` when nothing is found. The `brain-connector/SKILL.md` Detection section gains a new step 0 (HTTP-path detection via the resolver) and a CLI row in the Tool Names table. `commands/setup.md`'s `~/.mindrian.env` write is now followed by `chmod 600` (SEC-02 fix; no-op on Windows). `install.sh` is annotated -- it does NOT write `~/.mindrian.env` today; if a future code path adds a write, it MUST chmod 600 the file. `docs/install/BRAIN-SETUP.md` and `.env.brain.template` state Bearer-only explicitly and surface the `https://mindrianos.vercel.app/brain-access` request URL + `MINDRIAN_BRAIN_URL` override. Wave-0 hermetic test `tests/test-resolve-brain-key.cjs` (9 scenarios -- env wins / mindrian-env wins over CWD / CWD fallback / not-found / SEC-02 reject / Canon Part 8 grep / getApiKey delegation / brain-client preconditions / FLAG-3 home-default structural assertion) all green; registered in `lib/memory/run-feynman-tests.cjs`. (`lib/core/resolve-brain-key.cjs` [new], `lib/core/brain-client.cjs`, `scripts/session-start`, `skills/brain-connector/SKILL.md`, `commands/setup.md`, `install.sh`, `docs/install/BRAIN-SETUP.md`, `.env.brain.template`, `tests/test-resolve-brain-key.cjs` [new], `lib/memory/run-feynman-tests.cjs`, `lib/memory/security-trifecta.test.cjs`.)
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **Statusline deployment-topology gap (the last thread in the install-machinery family).** A Windows live test on beta.12 confirmed: the statusline-wrapper fix shipped in the plugin cache, but `~/.claude/settings.json` runs the *deployed* `~/.claude/statusline-mos`, which `scripts/session-start` had been re-copying from this hook's `PLUGIN_ROOT` every session -- so when the running hook lagged the just-updated version, the deployed copy stayed stale. Fix: `~/.claude/statusline-mos` is now a **dumb dispatcher shim** (`scripts/statusline-mos-dispatch`, marker `MINDRIAN-STATUSLINE-DISPATCH`) -- zero logic, it just finds an installed plugin version and `exec`s that version's `scripts/statusline-mos`, which does the real (installed_plugins.json-first) resolution and rendering. So a wrapper fix in plugin vN+1 reaches every user on their next session with no re-stamp, and a wrapper bug can never sit stale on the deployment surface. `scripts/session-start` Step A now deploys/migrates the dispatcher: one-time migration from an old logic-bearing `~/.claude/statusline-mos`; no-op once it's already the dispatcher; never touches a non-MindrianOS file at that path (it must contain `MindrianOS statusline` to be replaced). Falls back to the prior full-wrapper copy for plugin versions predating the dispatcher. (`scripts/statusline-mos-dispatch` [new], `scripts/session-start`, `scripts/statusline-mos` header.)
|
|
29
|
+
|
|
30
|
+
- **`scripts/release.sh:40`'s `IFS='.' read -r MAJOR MINOR PATCH`** mangled pre-release versions (`PATCH=0-beta` from `1.13.0-beta.11`), which is why beta.10 / 11 / 12 were hand-rolled and beta.13 is the first `release.sh`-cut pre-release. Replaced with `semver.inc()` (Plan 123-01).
|
|
31
|
+
- **`scripts/doctor.cjs:40`'s hardcoded `INSTALL_DIR = ~/.claude/plugins/mindrian-os/`** was the `MODULE_NOT_FOUND` source on marketplace-only installs (the disease that surfaced Bug 7). NEW code (class I + class J + new wire-ins) resolves via `resolveActivePluginRoot()`; `INSTALL_DIR` is preserved for existing class A but no longer the source of truth for new code (Plan 123-03).
|
|
32
|
+
- **`scripts/session-start:419`'s `~/.mindrian-last-version` write inside the cold-start `else` branch** never fired on a session WITH an active room -- which is why room-sessions read stale (Pitfall 7). The new install-state record block writes it unconditionally as the single writer in earliest steps; the line-419 write is removed; the line-101 read of the PREVIOUS value is preserved for the transition banner (Plan 123-02).
|
|
33
|
+
- **`commands/setup.md:145`'s stale URL `mindrianos-jsagirs-projects.vercel.app/brain-access`** -> `mindrianos.vercel.app/brain-access` (Plan 123-05; reaffirmed Plan 123-07).
|
|
34
|
+
- **Brain client CHANGELOG prose softened** -- the client currently calls `mindrian-brain.onrender.com`; `brain.mindrian.ai` is the future host; `MINDRIAN_BRAIN_URL` overrides either (Plan 123-07).
|
|
35
|
+
- **`scripts/release-beta-smoke.sh`** retired -- hard-pinned to a stale Phase-89.6 artifact `EXPECTED_VERSION="1.11.0-beta.1"`; `doctor --acceptance --pre-tag` supersedes it (Plan 123-04).
|
|
36
|
+
- **`brain-client.cjs::getApiKey()` precedence** -- was env -> CWD `.env` -> `~/.mindrian.env`; now (via the resolver delegation) env -> `~/.mindrian.env` -> CWD `.env` per D-31. Deliberate: on a maintainer's machine the home file is the canonical key, the CWD file is project-local override (Plan 123-07).
|
|
37
|
+
- **Plan-02 amendment: install-state record `active_version` derivation** -- the original session-start block preferred the dev workspace's `plugin.json` version over the resolver's root basename, so on a maintainer's box (where the workspace can lead the live install) the record contained an internal contradiction (`active_root` pointed at the live install dir; `active_version` named a different version). Surfaced by Plan-06's pre-flight class-I gate 2026-05-13 (commit `69a5240`).
|
|
38
|
+
- **Plan-06 release-flight: `scripts/verify-release` Step 12 "Git State"** died silently on a clean working tree (`git status --porcelain | grep -v "^??" | wc -l` exited non-zero with no tracked uncommitted changes; `set -e` killed the script). Wrapped the grep in `{ ... || true; }` (commit `267d395`).
|
|
39
|
+
- **Plan-06 release-flight: `commands/operator.md` + `commands/doctor.md` YAML frontmatter parse error** -- `argument-hint: [history] [set <op>] [reset] [--json]` confused YAML (multiple flow-sequence-looking tokens on one line); the parser bailed at line 3 and both commands loaded with empty metadata. Wrapped both argument-hint values in double-quoted strings. Latent in `main` for at least a session before Plan-06's stricter pre-flight caught it (commit `b41f232`).
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- **`data/deployment-surfaces.json`** added -- hand-maintained static manifest; 6 surfaces; reuses the `data/` layout convention from Phase 122 but NOT the generator/`--check` pattern (this file isn't derived from anything; nothing to `--check` it against). Schema extension in Plan-03: optional `path_within_file` field on `exact-value` surfaces points at a JSON sub-field (e.g. `statusLine.command` inside `settings.json`); class-J's `exact-value` check extracts via that path before comparing.
|
|
44
|
+
- **`docs/install/BRAIN-SETUP.md`** + **`.env.brain.template`**: state explicitly that auth is `Authorization: Bearer <key>` only (NOT `x-api-key`); surface the `https://mindrianos.vercel.app/brain-access` URL in the no-key fallback (Plan 123-07).
|
|
45
|
+
- **`docs/CANON-PHASE-MAP.md`**: Phase 123 mapped under **Part 6** (dog-fooding the install lifecycle -- one record + one manifest + one command + one release script; the plugin's own install state honors the plugin's canon) and **Part 7** (reuse justification -- ~90% of Phase 123 extends shipped code; net-new files are `data/deployment-surfaces.json`, `lib/core/resolve-brain-key.cjs`, `lib/core/cache-prune.cjs`, the per-class fixtures) (Plan 123-06 Task 4).
|
|
46
|
+
- **`@mindrian_os/cli` -> `@mindrian_os/install` doc/test sweep** -- forward-facing references across `docs/install/PACKAGING-PATHS.md`, `tests/manual/95.6-windows-cold-install-acceptance.md`, `tests/test-release-npm-gate.sh`, `docs/INSTALL-LIFECYCLE-HARNESS.md` (lines 91/104/124), plus older `@mindrian/os` mentions in `docs/autopsies/2026-05-09-gary-laben-install-failure.md`, `docs/UI-UX-CONVERGENCE-2026-05-10/04-REVERSE-SALIENT-INSTALL.md`, `docs/testers/gary-laben/FEEDBACK.md`, `docs/testers/outbox/2026-05-07-gary-laben-welcome.md`. Historical CHANGELOG entries stay as the historical record. After the sweep, `grep -rln "@mindrian_os/cli" docs/install/ commands/ tests/test-*.sh scripts/release.sh` returns nothing (Plan 123-05).
|
|
47
|
+
|
|
48
|
+
### Notes
|
|
49
|
+
|
|
50
|
+
- **Path C re-route status** (2026-05-05): v1.13.0-beta.13 carries Phase 123 (install-lifecycle-harness). Phase 110 (Brain Context Packet Contract) shipped in parallel during the Phase-123 execution waves; its 6 plans + verification completed on `main` between Plan-05 and Plan-07; it rides along here.
|
|
51
|
+
- **Promotion to clean 1.13.0** gated on a real-Windows `mindrian-os doctor --acceptance` run (Lawrence / operator), per Canon Part 5 (Evidence Is Graded By Context) + Part 6 (Product-as-Venture / dog-fooding mandate). A follow-up `bash scripts/release.sh --finalize` -- NOT this release's work -- cuts the clean `1.13.0` after the Windows gate is green.
|
|
52
|
+
- **Concurrent-execution incidents during the Phase 123 + Phase 110 parallel run** (2026-05-12 to 2026-05-13): a Phase-110 `git add -A` swept Plan 123-05's GREEN files into the wrong commit (`4453292`; work correct, attribution muddled); a Phase-110 commit re-introduced `release-beta-smoke.sh` after Plan 123-04 deleted it (`231f5cd`; Plan-04 re-deleted cleanly); the `fix/brain-client-timeout-ask-schema-cache` branch checkout yanked Plan-123 research's HEAD mid-run (cherry-picked back to `main` as `f03195a`). All recovered without data loss. Pattern documented for a future `gsd-executor` worktree-isolation-by-default improvement.
|
|
53
|
+
|
|
12
54
|
## [1.13.0-beta.12] - 2026-05-12
|
|
13
55
|
|
|
14
56
|
The v1.13.0 CAPSTONE release -- headline content is the **Workflow Layer** (Phase 122: framework <-> command registry + reliable invocation; spec at `.planning/WORKFLOW-LAYER-SPEC.md`, doc at `docs/WORKFLOWS.md`) plus the npm-installer overhaul (`npx @mindrian_os/install` is now a real one-command installer), the `@mindrian_os/cli` -> `@mindrian_os/install` rename, and the install-machinery fixes a Windows live test surfaced (doctor/update path resolution, the statusline pre-release blind spot, and the single plugin-root resolver that retires that whole bug family). Version trail to here: `1.13.0-beta.10` (a token-validation npm publish on 2026-05-12 -- now deprecated), `1.13.0-beta.11` (the real npm installer + the package rename, npm-only -- now deprecated, doctor path bug), `1.13.0-beta.12` (this release: the capstone, tagged `v1.13.0-beta.12`, marketplace `source.ref` pinned, `@mindrian_os/install` published with the `@next` dist-tag).
|
package/commands/auto-explore.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Manually trigger auto-explore on a specific file (Desktop fallback when PostToolUse hook does not fire per RESEARCH 4.8)"
|
|
3
3
|
argument-hint: "<file_path>"
|
|
4
|
+
serves_jtbd: ["find-problem", "understand-market", "explore"]
|
|
4
5
|
allowed-tools:
|
|
5
6
|
- "Bash"
|
|
6
7
|
- "Read"
|
package/commands/doctor.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: doctor
|
|
3
3
|
description: Diagnose and optionally repair MindrianOS install — detects install-cache drift, .room-root sentinel gaps, active-room guard silence, surface-verification gaps, ROOM.md/MINTO.md drift, UI Ruling System compliance, and statusline visibility drift
|
|
4
|
-
argument-hint: [--fix] [--cascade-rooms] [--verify-surface] [--room-md] [--ui-compliance] [--statusline-visibility] [--all] [--json]
|
|
4
|
+
argument-hint: "[--fix] [--cascade-rooms] [--verify-surface] [--room-md] [--ui-compliance] [--statusline-visibility] [--install-state] [--all] [--acceptance] [--pre-tag] [--light-npx] [--json]"
|
|
5
5
|
body_shape: E (Action Report)
|
|
6
6
|
body_shape_detail: per-class status rows with [before → after] pattern, summary totals, F.1 Next Move selector when drift detected without --fix
|
|
7
7
|
serves_jtbd: ["audit-room"]
|
package/commands/operator.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: operator
|
|
3
3
|
description: Show or manually set the conversation operator (JUST_TALK / EXPLORE_CAPTURE / BUILD_ROOM / METHODOLOGY / DECISION_GATE) -- the per-room state machine that governs how Larry renders responses
|
|
4
|
-
argument-hint: [history] [set <op>] [reset] [--json]
|
|
4
|
+
argument-hint: "[history] [set <op>] [reset] [--json]"
|
|
5
5
|
body_shape: E (Action Report)
|
|
6
6
|
body_shape_detail: current state + last 5 history (default), full history (history subcommand), Shape F.1 picker (set subcommand), Shape F.4 confirmation (reset subcommand)
|
|
7
7
|
serves_jtbd: ["explore"]
|
package/commands/setup.md
CHANGED
|
@@ -142,7 +142,7 @@ Remove `neo4j-brain` and `pinecone-brain` from `.mcp.json` if present.
|
|
|
142
142
|
|
|
143
143
|
Ask the user:
|
|
144
144
|
|
|
145
|
-
> "Do you have a Brain API key? If not, request one at mindrianos
|
|
145
|
+
> "Do you have a Brain API key? If not, request one at mindrianos.vercel.app/brain-access -- you'll get it within 24 hours."
|
|
146
146
|
|
|
147
147
|
If the user provides a key:
|
|
148
148
|
|
|
@@ -163,9 +163,13 @@ if [ -f ~/.mindrian.env ] && grep -q "MINDRIAN_BRAIN_KEY" ~/.mindrian.env; then
|
|
|
163
163
|
else
|
|
164
164
|
echo "MINDRIAN_BRAIN_KEY=<their-key>" >> ~/.mindrian.env
|
|
165
165
|
fi
|
|
166
|
+
# SEC-02 (Phase 123 Plan-07): lock down permissions on POSIX (no-op on Windows).
|
|
167
|
+
# Without this, lib/core/resolve-brain-key.cjs refuses to load the key from a
|
|
168
|
+
# group/world-readable file and session-start shows "Brain: NOT loaded".
|
|
169
|
+
chmod 600 "$HOME/.mindrian.env" 2>/dev/null || true
|
|
166
170
|
```
|
|
167
171
|
|
|
168
|
-
Tell the user: "Key saved to both your project `.env` and `~/.mindrian.env` (global backup). Brain will connect from any directory now."
|
|
172
|
+
Tell the user: "Key saved to both your project `.env` and `~/.mindrian.env` (global backup, chmod 600). Brain will connect from any directory now."
|
|
169
173
|
|
|
170
174
|
### 4. Test Connection
|
|
171
175
|
|
|
@@ -206,7 +210,7 @@ curl -s -w "\n%{http_code}" --max-time 15 \
|
|
|
206
210
|
> "Brain connected and verified. Larry just got smarter. Your existing commands now have graph intelligence behind them. Try `/mos:suggest-next`."
|
|
207
211
|
|
|
208
212
|
**On health OK but key auth failure (401):**
|
|
209
|
-
> "Brain server is up, but your key was rejected. Double-check the key you received, or request a new one at mindrianos
|
|
213
|
+
> "Brain server is up, but your key was rejected. Double-check the key you received, or request a new one at mindrianos.vercel.app/brain-access"
|
|
210
214
|
|
|
211
215
|
**On health OK but key verification timeout:**
|
|
212
216
|
> "Brain server is up and your key is saved. Verification timed out but that is normal on first connect. Try `/mos:suggest-next` to confirm it works."
|
|
@@ -116,19 +116,84 @@ function fromLegacyClone(home) {
|
|
|
116
116
|
return isPluginDir(legacy) ? legacy : null;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// Phase 123 Plan-02 (HARNESS-123-05): classify the resolved plugin root into one
|
|
120
|
+
// of the 4 known topologies. RESEARCH Pitfall 4: a legacy-clone dir can carry an
|
|
121
|
+
// unrelated origin remote (the dogfood box's ~/.claude/plugins/mindrian-os/ has
|
|
122
|
+
// its origin pointed at mindrian-agno-backend.git) so a naive "has origin ->
|
|
123
|
+
// dev-clone" heuristic mis-classifies it. The order below is precedence-locked:
|
|
124
|
+
// env override and explicit legacy path win before the structural git probe.
|
|
125
|
+
//
|
|
126
|
+
// Returns one of: 'marketplace-cache' | 'dev-clone' | 'legacy' | 'not-found'.
|
|
127
|
+
function classifyTopology(root, source) {
|
|
128
|
+
if (!root) return 'not-found';
|
|
129
|
+
// env override -> always treated as a dev clone (tests, dev boxes, hand clones).
|
|
130
|
+
if (source === 'MINDRIAN_OS_ROOT') return 'dev-clone';
|
|
131
|
+
|
|
132
|
+
const home = os.homedir();
|
|
133
|
+
// Explicit legacy path wins before the structural check -- some legacy clones
|
|
134
|
+
// carry an unrelated origin remote (Pitfall 4).
|
|
135
|
+
try {
|
|
136
|
+
if (path.resolve(root) === path.resolve(home, '.claude', 'plugins', 'mindrian-os')) {
|
|
137
|
+
return 'legacy';
|
|
138
|
+
}
|
|
139
|
+
} catch { /* ignore */ }
|
|
140
|
+
|
|
141
|
+
// Marketplace cache: under ~/.claude/plugins/cache/<mp>/{mos|mindrian-os}/<version>/.
|
|
142
|
+
try {
|
|
143
|
+
const cacheBase = path.resolve(home, '.claude', 'plugins', 'cache');
|
|
144
|
+
const resolved = path.resolve(root);
|
|
145
|
+
if (resolved.startsWith(cacheBase + path.sep)) {
|
|
146
|
+
return 'marketplace-cache';
|
|
147
|
+
}
|
|
148
|
+
} catch { /* ignore */ }
|
|
149
|
+
|
|
150
|
+
// Dev clone structural probe: a .git + install.sh + an origin remote URL that
|
|
151
|
+
// mentions the plugin repo name. execSync is wrapped in try/catch so a missing
|
|
152
|
+
// git binary or a non-git dir falls through cleanly.
|
|
153
|
+
try {
|
|
154
|
+
if (fs.existsSync(path.join(root, '.git')) && fs.existsSync(path.join(root, 'install.sh'))) {
|
|
155
|
+
const cp = require('node:child_process');
|
|
156
|
+
let originUrl = '';
|
|
157
|
+
try {
|
|
158
|
+
originUrl = cp.execSync('git -C ' + JSON.stringify(root) + ' remote get-url origin', {
|
|
159
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
160
|
+
encoding: 'utf8',
|
|
161
|
+
timeout: 1500,
|
|
162
|
+
}).trim();
|
|
163
|
+
} catch { /* no origin remote, swallow */ }
|
|
164
|
+
if (/mindrian-os-plugin/i.test(originUrl)) return 'dev-clone';
|
|
165
|
+
}
|
|
166
|
+
} catch { /* ignore */ }
|
|
167
|
+
|
|
168
|
+
// Defensive defaults: respect the resolver's source classification.
|
|
169
|
+
if (source === 'legacy-clone') return 'legacy';
|
|
170
|
+
// A resolved plugin dir that is not under a recognized cache path and not the
|
|
171
|
+
// legacy fixed path and does not pass the dev-clone probe -- treat as
|
|
172
|
+
// marketplace-cache (the bin/cli.js + installed_plugins.json path).
|
|
173
|
+
return 'marketplace-cache';
|
|
174
|
+
}
|
|
175
|
+
|
|
119
176
|
function resolveActivePluginRoot() {
|
|
120
177
|
const envRoot = process.env.MINDRIAN_OS_ROOT;
|
|
121
|
-
if (envRoot)
|
|
178
|
+
if (envRoot) {
|
|
179
|
+
return { root: envRoot, source: 'MINDRIAN_OS_ROOT', topology: classifyTopology(envRoot, 'MINDRIAN_OS_ROOT') };
|
|
180
|
+
}
|
|
122
181
|
|
|
123
182
|
const home = os.homedir();
|
|
124
183
|
let r;
|
|
125
|
-
if ((r = fromInstalledPlugins(home)))
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
184
|
+
if ((r = fromInstalledPlugins(home))) {
|
|
185
|
+
return { root: r, source: 'installed_plugins.json', topology: classifyTopology(r, 'installed_plugins.json') };
|
|
186
|
+
}
|
|
187
|
+
if ((r = fromMarketplaceCache(home))) {
|
|
188
|
+
return { root: r, source: 'marketplace-cache', topology: classifyTopology(r, 'marketplace-cache') };
|
|
189
|
+
}
|
|
190
|
+
if ((r = fromLegacyClone(home))) {
|
|
191
|
+
return { root: r, source: 'legacy-clone', topology: classifyTopology(r, 'legacy-clone') };
|
|
192
|
+
}
|
|
193
|
+
return { root: null, source: 'not-found', topology: 'not-found' };
|
|
129
194
|
}
|
|
130
195
|
|
|
131
|
-
module.exports = { resolveActivePluginRoot };
|
|
196
|
+
module.exports = { resolveActivePluginRoot, classifyTopology };
|
|
132
197
|
|
|
133
198
|
// CLI entry point.
|
|
134
199
|
if (require.main === module) {
|