Skip to main content

Install-Lane Plan: Governance Hierarchy Env Vars + Directory Skeletons

Status: v0.7 — Wave 3 SPEC-080 Phase 2 install-lane (SPEC-080 v0.3 accepted). PRISM_GOVERNANCE_LOOKUP_ENABLED added via the Option B 2-line pattern PR #120 established. v0.7 trigger: SPEC-080 v0.3 accepted (DB row 4b19377c; rename recall→lookup landed via PR #126 / 20e1e4a). Donna TaskAssigned 306d06fa authorizes the trivial 2-line add — sequencing dependency for Donna’s backend Phase 2 PR #127 (lookup verb default-off until this flag flips). v0.7 changelog (vs v0.6):
  • §3: Add row for PRISM_GOVERNANCE_LOOKUP_ENABLED (default false, per SPEC-080 §13). Identical shape to GOV / CONSENSUS / MEMDOM flags.
  • §12.2: 2-line edit per Option B pattern — append PRISM_GOVERNANCE_LOOKUP_ENABLED to FEATURE_FLAGS + add optional override field on EnvBlockInputs. Third config-only flag add since the refactor; pattern remains 2 lines.
  • §lifecycle: Wave 3 install-lane prerequisite for SPEC-080 Phase 2 (prism_governance_lookup verb) — once this PR deploys to server1, Donna’s PR #127 deploy gate clears. Verb default-off invariant preserved: flag’s existence in env file does NOT trigger any new behavior in this PR.

Status (historical, v0.6): Wave 2 Blocker #5 install-lane (SPEC-079 ratified). PRISM_MEMORY_DOMAINS_ENABLED added via the Option B 2-line pattern PR #120 established. v0.6 trigger: SPEC-079 v0.2 ratified by Donna PO 2026-05-04 (DB row eface81a; Texi clean signoff d802efdd). Donna TaskAssigned dc9f56f5 authorizes the trivial 2-line add per the v0.5 refactor. v0.6 changelog (vs v0.5):
  • §3: Add row for PRISM_MEMORY_DOMAINS_ENABLED (default false, per SPEC-079 §13). Identical shape to GOV + CONSENSUS flags.
  • §12.2: 2-line edit per Option B pattern — append PRISM_MEMORY_DOMAINS_ENABLED to FEATURE_FLAGS + add optional override field on EnvBlockInputs. Validates the Option B refactor’s promise: subsequent flags really are config-only.
  • §13: 4 Wave 2 SPEC-079 smoke cases verified pre-PR (21 assertions PASS) — all 3 flags default-false on fresh install; operator-set MEMDOM=true preserved; cross-flag independence (GOV=true + MEMDOM=true + CONSENSUS=false coexist); byte-compat for pre-PR-#121 envs.
  • §lifecycle: Wave 2 install-lane fully closed once this PR + PR #120 both deploy. Wave 2 Blockers #4 + #5 install-lane DONE.

Status (historical, v0.5): Wave 2 Blocker #4 install-lane (SPEC-078 ratified). envBlockWriter refactored to FEATURE_FLAGS array; PRISM_CONSENSUS_PARALLELISM_ENABLED added. v0.5 trigger: SPEC-078 v0.2 ratified by Donna PO 2026-05-04 (DB row a9e87f35; Texi clean signoff 17ff83d3). Donna TaskAssigned 5fc94cac authorizes envBlockWriter Option B refactor (per 5739aa38 design call) + PRISM_CONSENSUS_PARALLELISM_ENABLED flag add. v0.5 changelog (vs v0.4):
  • §3: Add row for PRISM_CONSENSUS_PARALLELISM_ENABLED (default false, per SPEC-078 §13). Same shape as PRISM_GOVERNANCE_RESOLVER_ENABLED.
  • §12.2: envBlockWriter.ts refactored to FEATURE_FLAGS array (Option B). Adding a new flag is now a 2-line change: append to FEATURE_FLAGS + add optional override field on EnvBlockInputs. SPEC-079’s PRISM_MEMORY_DOMAINS_ENABLED will follow this pattern when ratified.
  • §13: 5 Wave 2 smoke cases verified pre-PR — both flags default-false on fresh install; operator-set GOV=true preserved; operator-set CONSENSUS=true preserved; mixed flag values preserved; byte-compat for pre-Wave-2 envs.
  • §lifecycle: Plan #10 Wave 1 Blocker #1: CLOSED (PR #114+#115+#116+#117 merged+deployed+smoked). Wave 2 Blocker #4 install-lane: PR drafted (this revision).

Status (historical, v0.4): install-verb activation. PR #114 + #115 + #116 all merged + deployed; this revision flips the held-comments to live-call sites. Date: 2026-05-04 Author: Lafonda (install lane) Origin: TaskAssigned 0af3c095-3b83-4ec9-a496-32e3a41f7968 from Candi; shaping reply 6d76624f answered by Candi e08fcfea (decision: go) on 6 draft dispositions. Reviews:
  • Architecture (v0.1): Texi 26e74209accept_with_amendments. All amendments folded into v0.2.
  • Engineering authorization (v0.2): Donna d9cd9d0cengineering_authorization_granted_for_phase_2_PREP_only.
  • v0.3 input: SPEC-077 v0.2 (Donna e29ecde6, Texi d15c8380 7 binding amendments folded) + ADR #47 v0.2 (Donna 7fff65bd, supersedes ADR #45). Donna PO ratified per 639e652f Donna as PO.
  • v0.4 trigger: PR #116 boot-report extension merged at 1dcf5f3 + Samantha deploy-green at image 6a5ff3387422.... Donna chained TaskAssigned f8cbe3d9 → Lafonda activation per signal 13d22051 standby commitment.
Live-behavior status: ACTIVE — install_local + install_lan handlers now invoke runGovernanceSetup(); governance block added to return shape per §12.3. Pending Samantha deploy + smoke verification on this PR for Plan #10 Wave 1 Blocker #1 full closure. v0.4 changelog (vs v0.3):
  • §11: Status flipped from “held” to “active”. Wave 1 install-lane Blocker #1 closure pending this PR’s deploy + smoke verification.
  • §12.2: Removed “(held)” annotation on tier1c.ts wiring; helpers now actively called.
  • §13: Smoke matrix annotated — cases 1-9 all PASS pre-activation (5 helper-level + 4 just-verified before this PR); cases 10-11 ready to run via integration through Samantha’s deploy lane post-merge.
v0.3 changelog (vs v0.2):
  • §4: Stub frontmatter optionally accepts mandatory: true (per ADR #47 §3) for guardrail rules; installer never sets it (PO/operator-controlled), but the create-or-merge logic must preserve it on existing files.
  • §4: Idempotency report adds template_copied[] for PRISM_GLOBAL.md template-copy outcomes (per SPEC-077 §6); existed_preserved[] items for layer files with mandatory: true get an extra mandatory_guardrail: true flag for operator visibility.
  • §6: Boot-report skipped layer state is RESERVED for v1 (per SPEC-077 §4 + Texi v0.2 amendment 4); installer MUST NOT infer skipped from missing files. Lafonda’s install verbs only emit skipped once a PRISM_GOVERNANCE_LAYER_SKIPPED_<LAYER>=true env mechanism ships (post-v1).
  • §6: Add ORG.md dual-source row (per ADR #47 §4): canonical $PROJECT_ROOT/ORG.md vs repo-local ./ORG.md — installer writes to canonical location on sibling-projects layout; resolver reports repo_local_used when override active.
  • §6: Add feature flag row PRISM_GOVERNANCE_RESOLVER_ENABLED (default false, per SPEC-077 §13). Installer writes the flag to $HOME/.prism/env on every install with explicit false default so operators have a clear toggle; install-verb behavior is unaffected by the flag (only the runtime resolver checks it).
  • §10: Resolved — PRISM_GLOBAL.md source policy LOCKED by SPEC-077 §6: template-copy-if-present (schema-version-compatible) + report template_source_hash (sha256) + template_source_version; never overwrite without force=true.
  • §12.2: Add 6th helper templateCopier.ts for the PRISM_GLOBAL.md template-copy logic.
  • §12.3: Locked TS shape for template_copied[] and mandatory_guardrail flag.
  • §13: Add 6 new smoke cases — PRISM_GLOBAL.md template-copy compatible/incompatible/existing-not-overwritten; mandatory-guardrail preservation on re-run; feature-flag-OFF default written; skipped-state-not-inferred-from-missing.
v0.2 changelog (vs v0.1):
  • §3: Defer PRISM_USER_SLUG (Texi: PII / cross-machine drift); keep PRISM_CONFIG_PROFILE in v1; PRISM_SURFACE remains runtime-only.
  • §4: Add schema_version to stub frontmatter; explicit slug validation [a-z0-9-]+ with structured error and no silent normalization; asymmetric PRISM.md write policy spelled out.
  • §5: Resolve the v0.1 contradiction — installer-first-run vs runtime-resolver behaviors are now distinct sub-rules.
  • §4 (new): Structured idempotency report contract (counts + paths for created / existed_preserved / skipped_project_owned / drift_or_invalid_frontmatter).
  • §6: Boot-report layer states expanded from 4 to 5 (found_nonempty, found_empty_stub, missing, skipped, invalid).
  • §6 (new): Shared resolver helper + shared env-block writer helper; no separate prism_write_env verb yet.

1. Source Artifacts

  • governance-sim/README.md — locked boot model + governance precedence + 7+3 env var contract
  • governance-sim/central-registry/README.md — Option A layout (Prism-managed governance/ tree under $PRISM_ROOT)
  • governance-sim/sibling-projects/README.md — Option B layout (.prism-governance/ under $PROJECT_ROOT + project-local PRISM.md)
  • docs/research/prism-governance-improvement-recommendations-2026-05-04.md — P0–P2 recommendations including Agreement 1 (static BIOS first, prism_start first runtime action) and Agreement 2 (governance layers need discoverable filesystem roots)

2. Phase Split

Phase 1 — Plan & design (this document; no code changes)

  • Define env-var write contract for the installer.
  • Define directory skeleton creation logic per layout.
  • Define layout-detection and collision-handling rules.
  • Define idempotency / re-run behavior.
  • Define install-time defaults for each new env var.
  • Identify lane crossings and route them to the correct owners.

Phase 2 — Implementation (gated on governance-resolution spec approval)

  • Wire env-var write block into prism_install_local + prism_install_lan.
  • Wire directory skeleton creation per layout into the same verbs.
  • Implement PRISM_GOVERNANCE_LAYOUT explicit-wins → detect → ambiguity-stops resolver.
  • Update .env.example and any BIOS/install templates referencing the new vars.
  • Smoke on mini4.home.lan (single-operator local install path per memory reference_mini4_ssh.md) and on server1.home.lan (LAN install path).
  • Bake the prism_start boot-report extension hooks (cross-lane — see §6).

3. Env Var Contract (installer-written)

The installer writes a single canonical env block. Per memory project_host_contract.md, the Node CLI installer is the only writer; the mcp-node runtime reads, never re-detects. The new vars join the existing block at the same surface (location confirmed during implementation — likely $HOME/.prism/env or the per-host config file consumed by the existing host contract).

Minimum (must be written by every install verb)

VariablePurposeinstall_local defaultinstall_lan default
PRISM_ROOTPrism repo / install root$PWD (cwd at install time, validated as a Prism repo)per target registry entry
PROJECT_ROOTParent dir containing local project reposparent of $PRISM_ROOT (auto-detected); explicit flag/env overridesparent of $PRISM_ROOT on remote, mirrored locally
PRISM_GOVERNANCE_ROOTRoot of static governance hierarchy$PROJECT_ROOT/.prism-governance (sibling-projects default)same
PRISM_TENANT_SLUGTenant / company identifierpersonalderive-or-prompt
PRISM_ORG_SLUGOrg / department identifierpersonalderive-or-prompt
PRISM_PROJECT_SLUGProject identifierinferred from cwd dir name (lowercase, slugified)same
PRISM_GOVERNANCE_LAYOUTcentral-registry or sibling-projectssibling-projectssibling-projects

Optional / deferred

VariablePurposev1 disposition
PRISM_CONFIG_PROFILElocal / lan / cloud / hosted / testWrite in v1 — derivable from which install verb ran (local for prism_install_local, lan for prism_install_lan). Single value, not a list.
PRISM_USER_SLUGLocal/user preference layerDefer. Texi review (26e74209 §“Optional vars”): deriving from $USER is cross-machine / PII-prone and creates an inert env var with unclear semantics. Re-introduce only when the governance-resolution spec defines user-layer path/precedence, OR when an operator explicitly passes it at install.
PRISM_SURFACEAgent surfaceDefer to runtime. Surface is editor-determined at launch, not installer-knowable.

4. Directory Skeleton Contract

The installer creates the governance directory skeleton matching PRISM_GOVERNANCE_LAYOUT. Idempotent: create-or-merge — add missing dirs/files, preserve existing files, never overwrite project-owned PRISM.md (acceptance criterion #2).

Sibling-projects (default)

$PROJECT_ROOT/.prism-governance/
  global/
    PRISM_GLOBAL.md   ← stub if missing, untouched if present
  tenants/
    $PRISM_TENANT_SLUG/
      TENANT.md       ← empty stub
      orgs/
        $PRISM_ORG_SLUG/
          ORG.md      ← empty stub
Project PRISM.md lives in the project repo ($PRISM_ROOT/PRISM.md) and is never touched by the installer.

Central-registry (opt-in via flag/env)

$PRISM_ROOT/governance/
  global/
    PRISM_GLOBAL.md   ← stub if missing
  tenants/
    $PRISM_TENANT_SLUG/
      TENANT.md       ← empty stub
      orgs/
        $PRISM_ORG_SLUG/
          ORG.md      ← empty stub
          projects/
            $PRISM_PROJECT_SLUG/
              PRISM.md   ← stub if missing; never overwrite if present

Stub file shape (every empty placeholder)

Minimal YAML frontmatter so prism_start can distinguish empty from missing (per acceptance criterion #1) and so future resolver changes can report old stubs cleanly. Per Texi review (26e74209 §“Stub frontmatter”): YAML in the artifact itself is the right sentinel — avoids sentinel sidecar files / DB rows. Parser bounded to the first frontmatter block; resolver caches results so per-boot parser cost is negligible.
---
schema_version: 1
governance_layer: tenant   # or org / project / global
slug: personal
status: empty
created_by: prism_install_local
created_at: 2026-05-04T00:00:00Z
# mandatory: true            # OPTIONAL — operator/PO sets this on rules that
#                            # cannot be overridden by narrower layers
#                            # (per ADR #47 §3). Installer NEVER sets it.
---
Body is intentionally blank. Operator fills the file later; installer never re-edits an existing stub. Installer MUST preserve mandatory: true on existing files during create-or-merge; the resolver reads this field per ADR #47 §3 and reports it via governance.mandatory_guardrails[] per SPEC-077 §7.

PRISM_GLOBAL.md template-copy policy (per SPEC-077 §6)

On first install, the installer determines PRISM_GLOBAL.md content via:
  1. Template present + schema-version-compatible ($PRISM_ROOT/templates/PRISM_GLOBAL.md exists AND its frontmatter schema_version matches the installer’s expected version) → copy the template to $PRISM_GOVERNANCE_ROOT/global/PRISM_GLOBAL.md. Idempotency report records template_copied[] entry with path, source_path, source_hash (sha256 of source bytes), source_version (template’s schema_version).
  2. Template absent OR schema-version-incompatiblecreate empty stub with the standard frontmatter shape above. Idempotency report records the stub in created[].
  3. Existing PRISM_GLOBAL.md presentnever overwrite unless force=true flag passed to the install verb. Idempotency report records existed_preserved[] entry.

Slug validation (installer-written slugs only)

Allowed charset: [a-z0-9-]+. Lowercase, dash-separated. Per Texi (26e74209 nit #2): structured error before writing any files if a passed slug violates the rule. No silent normalization — if migration from legacy mixed-case names is needed, that becomes an explicit operator-driven mapping, not an installer side effect.

Asymmetric PRISM.md write policy (per Texi nit #3)

LayoutProject PRISM.md write rule
sibling-projectsNever written by the installer. Project PRISM.md lives in the project repo ($PRISM_ROOT/PRISM.md) and is owned by the PO.
central-registryInstaller may create $PRISM_GOVERNANCE_ROOT/tenants/$T/orgs/$O/projects/$P/PRISM.md as a stub if missing. Installer never writes the active repo’s $PRISM_ROOT/PRISM.md under any layout.

Idempotent re-run report contract (per Texi review §“Idempotent re-run” + SPEC-077 v0.2 §6)

Installer re-runs return a structured summary. Silent preservation is rejected — operators need to see drift even when no destructive change happens:
{
  "layout": "sibling-projects",
  "governance_root": "/Users/fpn/projects/.prism-governance",
  "created":                      [{"path": "...", "layer": "..."}],
  "existed_preserved":            [{"path": "...", "layer": "...", "mandatory_guardrail": false}],
  "skipped_project_owned":        [{"path": "...", "reason": "project_PRISM_md_never_overwritten"}],
  "drift_or_invalid_frontmatter": [{"path": "...", "issue": "schema_version mismatch | invalid layer field | slug mismatch"}],
  "template_copied":              [{"path": "...", "source_path": "...", "source_hash": "sha256:...", "source_version": 1}]
}
existed_preserved[].mandatory_guardrail flags layer files with mandatory: true frontmatter so operators see at a glance which rules will constrain narrower layers (per ADR #47 §3). template_copied[] reports PRISM_GLOBAL.md template-copy outcomes per SPEC-077 §6. Drift is reported, not corrected — preserves Texi’s “preserve existing files; never overwrite project-owned PRISM.md” while surfacing operationally relevant divergence to the operator.

5. Layout Detection / Collision Handling

Per governance-sim/README.md §“Open Design Question”, with Texi’s 26e74209 clarification that installer first-run and runtime resolver behave differently in the none-present case:

Common rule (both contexts)

  1. Explicit wins. If PRISM_GOVERNANCE_LAYOUT is set in the env or passed as an install flag, use it.
  2. Both detected → ambiguity-stops. If both .prism-governance/ (sibling) and governance/ (central) trees are present and no explicit selector resolves the conflict, fail-fast with a structured error listing every collision found and the explicit PRISM_GOVERNANCE_LAYOUT=… resolution. (Per feedback_preflight_checks.md.)

Installer-specific rule (first-run, none-present)

  • If no env / flag and no existing tree, the installer defaults to sibling-projects, creates the skeleton, and writes the env block.
  • The installer prints the chosen layout in its summary (and includes it in the re-run report) so the operator can override on re-run via PRISM_GOVERNANCE_LAYOUT=central-registry.
  • Rationale: the installer is the initialization surface — its job is to put the system into a known state. Leaving an uninitialized system because a default wasn’t explicit would be hostile.

Runtime resolver rule (prism_start, none-present)

  • If prism_start finds no env-block layout selector and no existing tree at any standard location, it reports missing / ambiguous per layer and does NOT silently choose a layout.
  • Rationale: the resolver is the enforcement surface — silently picking a layout at runtime would mask install drift. The fix is to re-run the installer (or set the env var explicitly), not to have the resolver guess.
This split removes the v0.1 contradiction where §5 both failed-fast and defaulted on the none-present case.

6. Lane Crossings (NOT in this plan)

Called out so reviewers can route in parallel:
Cross-lane workOwnerStatus
prism_start boot-report extension (report governance layers + per-layer state)Donna (engineering)SPEC-077 v0.2 §7 specifies the response shape. Layer state is 4-active + 1 RESERVED per SPEC-077 §4 + Texi v0.2 amendment 4: found_nonempty, found_empty_stub, missing, invalid actively used in v1; skipped is RESERVED — only emit when explicit PRISM_GOVERNANCE_LAYER_SKIPPED_<LAYER>=true opt-out env mechanism ships (post-v1). Installer MUST NOT infer skipped from missing files.
ORG.md dual-source resolution (canonical $PROJECT_ROOT/ORG.md vs repo-local ./ORG.md)Donna (engineering) — resolver helper modulePer ADR #47 §4: installer writes to canonical location on sibling-projects layout; resolver reports `repo_local_used: truefalse` + conflicts when dual sources detected
Feature flag PRISM_GOVERNANCE_RESOLVER_ENABLED (default false)Donna (engineering) — resolver-side respectPer SPEC-077 §13. Installer writes the flag with explicit false default to $HOME/.prism/env on every install so operators have a clear toggle point. Install-verb behavior is unaffected by the flag (installer always writes env-block + creates skeleton); the flag controls only prism_start resolver activation.
BIOS template updates to consume the new env vars (CLAUDE.md / AGENTS.md derive paths)Desiree (docs) or shared with installPure env-var path resolution; could ship as a templates/ patch
Architectural decisions: layout precedence, defaults, ambiguity-stop semanticsTexi (architect)✅ Reviewed v0.1 (26e74209); v0.2 folds amendments. ADR #47 v0.2 (7fff65bd) seals the architecture upstream.
Plan #9 hygiene cleanup (worktree list, branch prune, tag verify, draft PR cleanup)Donna (per ca359d88)In flight; zero overlap with this plan
Governance-resolution spec SPEC-077 v0.2 (the gate for Phase 2)Donna author + Texi review + Donna PO ratification✅ Drafted (e29ecde6); pending Texi re-review of v0.2 + Donna ratification

Implementation pattern (per Texi’s answers to optional questions in 26e74209)

  • Resolver code is shared, parametrized by layout. Both layouts resolve the same conceptual layers and differ only by path templates — separate code paths would drift.
  • Env-block writer is a shared internal helper used by both prism_install_local and prism_install_lan. Do not expose prism_write_env as a public verb yet; promote to a verb only if a real operator workflow needs repair/rotation without a full reinstall.
  • Naming is PRISM_GOVERNANCE_ROOT (long form) — semantic clarity wins over shell-typo risk; matches PRISM_GOVERNANCE_LAYOUT.

7. Acceptance Criteria Mapping (back to TaskAssigned 0af3c095)

CriterionHow this plan satisfies it
1. Installer establishes env/config for prism_start to report layout, governance root, slugs, paths, per-layer status§3 (env vars) + §4 (skeleton + stub frontmatter for empty/missing distinction). Cross-lane: Donna implements the prism_start reporting hook.
2. Local installs support sibling-projects without overwriting project-owned PRISM.md§4 sibling-projects layout: PRISM.md stays in project repo, installer never touches it; create-or-merge idempotency preserves all existing files.
3. Hosted/enterprise installs have a path to central-registry layout§4 central-registry layout + §5 explicit-wins via PRISM_GOVERNANCE_LAYOUT. Default for hosted: opt-in via install flag (deferred installer detection of “hosted” context).
4. No live behavior change until governance resolution spec approved§2 phase split: this is Phase 1 (plan only). Phase 2 implementation is gated on the spec.

8. Open Dependencies (block Phase 2)

  1. Texi architectural review of §3/§4/§5 dispositions — especially: stub-file frontmatter shape, PRISM_USER_SLUG/PRISM_CONFIG_PROFILE write decision, ambiguity-stop semantics.
  2. Donna engineering authorization once Texi review settles (Frank-away coverage path).
  3. Governance-resolution spec ratified by Donna.
  4. Confirmation of canonical env-block surface location (likely $HOME/.prism/env per host_contract; needs read of existing installer code at implementation time).
  5. prism_start boot-report extension specced + scheduled (Donna) so the hook exists when Phase 2 ships.

9. Smoke Test Plan (Phase 2 only — not exercised by this draft)

  • mini4 (Linux, lafonda@mini4.home.lan) — fresh prism_install_local against an empty $PROJECT_ROOT; verify env-block written with all 7 minimums + 2 optionals (PRISM_USER_SLUG, PRISM_CONFIG_PROFILE); verify .prism-governance/ skeleton created with correct stubs; re-run to confirm idempotency.
  • server1 (donna@server1.home.lan)prism_install_lan re-run against an installed target; verify env block + skeleton on the LAN target; verify deploy delta still ships per existing SPEC-055 contract.
  • Collision case — manually pre-seed both .prism-governance/ and governance/; run installer with no PRISM_GOVERNANCE_LAYOUT; assert structured failure listing both detected trees.
  • Override case — set PRISM_GOVERNANCE_LAYOUT=central-registry on a fresh local install; assert governance/ skeleton created under $PRISM_ROOT.

10. Open Questions

Resolved by v0.2 (Texi review 26e74209)

  • PRISM_USER_SLUG ship vs deferdefer (PII / cross-machine drift). §3.
  • PRISM_CONFIG_PROFILE single vs listsingle value derived from install verb. §3.
  • Interactive prompt vs fail-fast on ambiguityfail-fast at runtime; installer first-run defaults to sibling-projects. §5.
  • Slug charset validation[a-z0-9-]+ lowercase, structured error, no silent normalization. §4.

Resolved by v0.3 (SPEC-077 v0.2 + ADR #47 v0.2)

  • PRISM_GLOBAL.md template-vs-stub dispositiontemplate-copy-if-present + schema-version-compatible; report source_hash (sha256) + source_version; never overwrite without force=true per SPEC-077 §6. Plan §4 + §12.2 (templateCopier.ts) + §13.8 codify.

Still open (none — all routed)

All previously open questions have a binding contract or routed owner.

11. Plan Status & Next Step

  • v0.1 reviewed by Texi (26e74209accept_with_amendments).
  • v0.2 folds all 4 required changes + 4 architectural nits.
  • Donna engineering authorization (d9cd9d0c) for Phase 2 PREP; implementation behavior gated on Plan #10 Blockers #1 + #2 ratification.
  • Launcher source-block patch shipped as DRAFT PR #114 (queued for post-ratification merge).
  • v0.3 folds SPEC-077 v0.2 (e29ecde6) + ADR #47 v0.2 (7fff65bd) contract additions.
  • PRISM_GLOBAL.md source policy resolved by SPEC-077 §6 (template-copy-if-present + schema-version-compatible + sha256 hash report).
  • skipped state RESERVED for v1 per SPEC-077 §4; installer never infers from missing files.
  • Donna engineering authorization on v0.3 — pending; will be requested after install-verb PR draft lands.
  • Install-verb PR draft — Lafonda next deliverable; will queue alongside PR #114 for post-ratification merge.
  • Donna spec ratification — gates Phase 2 implementation behavior shipping.
  • Lafonda current activity: drafting install-verb PR per rule 7 (milestones not stops). Speculative draft per Donna 20460d0f decision (1 of 3 optional asks: q1_speculative_install_verb_pr: YES, start drafting).

12. Phase 2 Implementation Map (PREP — locked at v0.2 + Donna d9cd9d0c)

12.1 Env-block surface

Decision: new file at $HOME/.prism/env (POSIX) / $env:USERPROFILE\.prism\env (Windows). Shell-sourceable KEY=VALUE lines, no quoting, no expansion, atomic write. Confirmed by code read: No existing ~/.prism/env file in the repo. Existing ~/.prism/ artifacts: targets.json (LAN registry), credentials.personal.json (API key), backups/ (snapshots), sigcount-<Identity>.json + signals-<Identity>.jsonl (signal cache). The new env file slots in cleanly without colliding. Launcher patching required: both bin/coder.sh and bin/coder.ps1 must source $HOME/.prism/env early (before existing PRISM_AGENT_* exports) so the governance vars enter the same export chain. For Codex specifically (sh L387–390, ps1 L371+), the new vars must also be added to the mcp_servers.prism.env.X=Y Codex-passthrough config block since Codex doesn’t auto-inherit shell env into the MCP server process. start-all.sh exports its own env first; sourcing $HOME/.prism/env near the top would make per-launch overrides work. Bash export semantics (PR #114 in-flight catch): sourcing a plain KEY=VALUE env file with . "$HOME/.prism/env" sets shell vars but does not export them to children. Use the set -a / set +a (allexport) wrap so vars are auto-exported during sourcing. PowerShell’s Set-Item Env:$name exports automatically — no equivalent wrap needed. Verified empirically: bash -c '. "$HOME/.prism/env" && env | grep PRISM_GOVERNANCE_LAYOUT' returns empty without the wrap. Coordination flag: Phase 2 launcher patching touches the exact files that just landed in 64e26dc (bin/coder.sh, bin/coder.ps1, start-all.sh + mcp-node/src/verbs/lifecycle.ts). Sequencing question for Donna: ship launcher source-block patch as a separate PR (clean bisect lane) or bundle with the install-verb changes (atomic install behavior). Lafonda lean: separate PR.

12.2 Install-verb modification mapping

VerbFileLineModification
prism_install_localmcp-node/src/verbs/tier1c.ts560Insert await writeGovernanceEnvBlock({...}) and await ensureGovernanceSkeleton({...}) before docker-compose call. Bake structured re-run report into return shape (additive).
prism_install_lanmcp-node/src/verbs/tier1c.ts583Same pair of helper calls before upgradeLan(target, "full"). Return shape merges idempotency report alongside existing upgrade-full result.
prism_configure_lanmcp-node/src/verbs/tier1c.ts597No change in v1. Target registry shape stays orthogonal to governance hierarchy.
New helpers (proposed location — under mcp-node/src/ops/governance/):
  • envBlockWriter.ts — atomic write of $HOME/.prism/env with KEY=VALUE pairs, preserving operator-added vars not in the governance set. Always writes PRISM_GOVERNANCE_RESOLVER_ENABLED=false on first install so operators have a clear toggle (per SPEC-077 §13 + plan §6); preserves operator-set value on re-run if changed to true.
  • skeletonCreator.tsensureGovernanceSkeleton({layout, governanceRoot, tenantSlug, orgSlug, projectSlug}) — create-or-merge directory structure + stub frontmatter writes per §4. Calls templateCopier.ts for PRISM_GLOBAL.md specifically.
  • templateCopier.ts — PRISM_GLOBAL.md template-copy logic per SPEC-077 §6: check $PRISM_ROOT/templates/PRISM_GLOBAL.md presence + schema_version compatibility; on match, copy + compute sha256 + report template_copied[] entry; on mismatch or absence, fall through to stub creation; never overwrite existing without force=true.
  • layoutResolver.ts — explicit-wins → detect → ambiguity-stops logic per §5.
  • slugValidator.ts[a-z0-9-]+ validation, structured error before any write.
  • idempotencyReport.ts — type definition + builder for the §4 5-bucket report (4 original + template_copied[]).

12.3 Idempotency report — locked TypeScript shape

type GovernanceLayer = "global" | "tenant" | "org" | "project";

interface GovernanceIdempotencyReport {
  layout: "sibling-projects" | "central-registry";
  governance_root: string;
  created:                      Array<{ path: string; layer: GovernanceLayer }>;
  existed_preserved:            Array<{ path: string; layer: GovernanceLayer; mandatory_guardrail: boolean }>;
  skipped_project_owned:        Array<{ path: string; reason: "project_PRISM_md_never_overwritten" }>;
  drift_or_invalid_frontmatter: Array<{ path: string; issue: "schema_version_mismatch" | "invalid_layer_field" | "slug_mismatch" }>;
  template_copied:              Array<{ path: string; source_path: string; source_hash: string; source_version: number }>;
}
drift_or_invalid_frontmatter[].issue is a closed string set in v1 — open issues become typed enum members in later versions only when a specific drift class is observed in production. existed_preserved[].mandatory_guardrail is true when the existing file’s frontmatter contains mandatory: true — operator-visible flag for which preserved files will constrain narrower layers per ADR #47 §3. template_copied[].source_hash format: sha256:<hex> (66-char total). source_version is the integer schema_version from the source template’s frontmatter.

13. Phase 2 Smoke Test Checklist (post-ratification)

13.1 Local install — mini4 (lafonda@mini4.home.lan, Ubuntu 24.04)

  • Fresh empty $PROJECT_ROOT (no .prism-governance/); run prism_install_local.
  • Assert $HOME/.prism/env created with all 7 minimums + PRISM_CONFIG_PROFILE=local (8 vars total in v1).
  • Assert .prism-governance/ skeleton created per §4 with schema_version: 1 in every stub.
  • Assert structured re-run report returned (4 buckets present even if empty).
  • Re-run prism_install_local; assert created: [] + existed_preserved populated for every stub + drift_or_invalid_frontmatter: [].
  • Manually edit a stub frontmatter to break schema_version; re-run; assert drift_or_invalid_frontmatter lists the file with issue: "schema_version_mismatch".
  • Assert project repo’s PRISM.md untouched across all runs.

13.2 LAN install — server1 (donna@server1.home.lan)

  • Re-run prism_install_lan against installed target; assert governance env-block + skeleton present on remote + locally; assert existing upgrade-full deploy delta still ships per SPEC-055.
  • Assert remote $HOME/.prism/env matches local except for target-specific overrides (none in v1).
  • Confirm SSH-key-based deploy chain (reference_server1_ssh.md) unchanged.

13.3 Collision case (any host)

  • Pre-seed both .prism-governance/ (under $PROJECT_ROOT) and governance/ (under $PRISM_ROOT); run installer with no PRISM_GOVERNANCE_LAYOUT env.
  • Assert structured failure with both detected paths in error payload + the PRISM_GOVERNANCE_LAYOUT=… resolution hint.

13.4 Override case

  • Set PRISM_GOVERNANCE_LAYOUT=central-registry on a fresh local install; assert $PRISM_ROOT/governance/ skeleton created (not .prism-governance/); assert PRISM_GOVERNANCE_LAYOUT=central-registry written to $HOME/.prism/env.

13.5 Slug validation

  • Pass PRISM_TENANT_SLUG=PersonalCo (mixed case); assert structured error before any file write.
  • Pass PRISM_TENANT_SLUG=personal-co (valid); assert acceptance + skeleton created with that slug.

13.6 Launcher source-block

  • After prism_install_local, run bin/coder.sh -as Lafonda (or bin/coder.ps1 -as Lafonda on Windows); assert all 8 governance vars are visible to the spawned MCP server process (via mcp-node process.env read — verify with prism_status extended payload once Donna’s boot-report extension lands).

13.7 Idempotency-report consumer (post-Donna boot-report)

  • After install, run prism_start; assert per-layer state classification matches the v1-active vocabulary (found_nonempty, found_empty_stub, missing, invalid). Verify skipped is NEVER emitted for missing files (per SPEC-077 §4 + Texi v0.2 amendment 4); skipped reserved for explicit opt-out env mechanism (post-v1).

13.8 PRISM_GLOBAL.md template-copy (per SPEC-077 §6)

  • Template present + schema-compatible: seed $PRISM_ROOT/templates/PRISM_GLOBAL.md with schema_version: 1 frontmatter + content; run prism_install_local against fresh $PROJECT_ROOT; assert template_copied[] entry with correct path, source_path, source_hash (validate sha256 matches), source_version: 1.
  • Template absent: remove $PRISM_ROOT/templates/PRISM_GLOBAL.md; run prism_install_local; assert created[] entry for the global stub (no template_copied[] entry).
  • Template schema-incompatible: seed template with schema_version: 999; run prism_install_local; assert installer falls through to stub creation (created[] entry for global stub, NOT template_copied[]); structured warning surfaced about template version mismatch.
  • Existing PRISM_GLOBAL.md never overwritten: pre-seed governance root with operator-edited PRISM_GLOBAL.md; run prism_install_local; assert existed_preserved[] entry; file unchanged on disk; assert prism_install_local with force=true overwrites (operator confirmation path).

13.9 Mandatory guardrail preservation

  • Pre-seed $PROJECT_ROOT/.prism-governance/tenants/personal/TENANT.md with frontmatter including mandatory: true; run prism_install_local; assert existed_preserved[] entry has mandatory_guardrail: true. Re-run; assert flag still surfaces; file content unchanged.

13.10 Feature flag default-OFF

  • Fresh prism_install_local; assert $HOME/.prism/env contains PRISM_GOVERNANCE_RESOLVER_ENABLED=false; assert no governance block in prism_start response (per SPEC-077 §13 default-off invariant).
  • Operator manually flips to true in env file; re-run prism_install_local; assert installer preserves operator’s true value (does NOT reset to false on idempotent re-run).
  • Reset to false; re-run prism_install_local; assert idempotency report shows env block unchanged.

13.11 Cross-spec contract checks

  • Layout-collision case (§13.3) matches SPEC-077 §10 + ADR #47 §5 fail-fast contract: structured error includes both detected paths + the explicit PRISM_GOVERNANCE_LAYOUT=… hint.
  • Per ADR #47 §4: when both $PROJECT_ROOT/ORG.md and repo-local ./ORG.md exist post-install, prism_start.governance.layers.org.repo_local_used: true (cross-lane verification with Donna’s resolver — gated on Phase 2 + Donna’s helper landing).
Last modified on June 11, 2026