Harness Intelligence Wiki
Research

Registry Baseline: Target System Brainstorm

Registry Baseline: Target System Brainstorm

This is the brainstorm output for the target system after the user accepted the decisions in the registry architecture research report. It uses the ten flow failure lenses. Every observation traces to evidence or an explicit unknown. Candidates stay candidates until the user accepts them. The next consumer is requirements-grill, then create-architecture.

1. Boundary

System. Registry Baseline distribution: the registry publish step, the hi installer, Project settings, the installed record, the Drift check, the session-start hook, the edit hook, Harness adapters for subagents, built Managed Artifacts, and scaffold-once artifacts.

Operators. The coding agent (session start, edits, hi commands), the human (accepts updates, resolves conflicts), and the release publisher (CI).

Accepted decisions, used as constraints.

IdDecisionSource
D1The registry is the Baseline distributor and the source for drift management. GitHub release artifacts stop.user, 2026-09-27
D2Built Managed Artifacts keep their install-time repository shape (workspace paths, Pack ids) in Project settings.user, 2026-09-27
D3hi builds each subagent body once and wraps it per harness. sync-subagents.mjs is removed.user, 2026-09-27
D4hi has its own small installer. Item JSON stays shadcn-compatible.user, 2026-09-27
D5Issue #232 is fixed inside the registry release.user, 2026-09-27
D6A session-start hook that checks the Baseline stays.user, 2026-09-27
D7Anti-slop rules stay the default lint asset for TypeScript Software Scopes.user, 2026-09-27

Constraints from repository guidance. Shared skills come from the skills repo main branch. apps/cli owns the executable. apps/api owns the control plane. Changed changelog paths select the release product.

Canonical terms kept. Baseline, Managed Artifact, Pack, Project settings, Harness adapter, Drift check, Update flow, Software Scope, Lint Route, Commit Gate. Terms this design retires are listed in section 6.

Unknowns.

  • U1. Where the registry is hosted: static files on the existing Vercel deployment, a route in apps/api, or another static host. D1 says "over there" without a location.
  • U2. Whether consumer repositories ignore .devpunks/. Issue #231 shows one that does; this repository tracks it.
  • U3. Whether the current control-plane Baseline fetch needs credentials. baseline/resolve.ts builds the URL from configuration; no token handling was found in the traced code, but the server side was not read.
  • U4. Whether any workspace in a consumer repository is published on its own and therefore needs its own copy of vendored lint files.
  • U5. Whether D6 means the version comparison only, or also the local file comparison, at session start. This brainstorm assumes version comparison at session start and full comparison on demand.

2. The target system from the agent's seat

Intake

  • Session start runs hi check --json. The command reads the installed version from the installed record, fetches the small registry catalog, and compares. Output has a structured status field: current, update-available, unavailable. The hook keys on that field. Evidence: the current hook keys on an issue code that the CLI never emits (.agents/hooks/scaffold-update-check.mjs:140-151).
  • The edit hook reads the installed record for managed paths. Evidence: it needs paths only (.agents/hooks/format-edited-file.mjs:374-393).
  • The agent or human runs hi init, hi update, hi diff, hi add <item>.
  • A fallback path exists: npx shadcn add @hi/<item>. It writes tier 1 files only. It applies no symlinks, merges, or workspace dependencies.

State

StateOwner and writerAuthoritative forLocation and lifetime
Registry catalog registry.jsonPublisher (CI)Item list, latest version, per-item sha256Remote, mutable pointer to immutable versions
Registry item /<version>/<id>.jsonPublisher (CI)Item files and metadata at that versionRemote, immutable
Project settings settings.jsonHuman (agent on request)Intent: registries, Packs, Software Scopes, providers, required toolsTracked
Installed record installed.jsonhi installer onlyInstalled version, recorded shape (D2), item to path map, link-or-copy per symlinkTracked, small
Item cachehi installerNothing; a copy of immutable item JSON~/.cache, verifiable by catalog sha256
Tier 1 files (skills, hooks, scripts, guides, lint plugin)RegistryContentRepository
Tier 2 built files (lint configs, shared prompt, subagent spec, commit gate, per-harness agents)Registry version × settings × recorded shape × authored inputsContent, by re-renderRepository
Tier 3 authored files (AGENTS.md, manifest.mjs, wiki, codex config)RepositoryContentRepository, written once

Two local files, one writer each, no hashes. Evidence: the Project settings axiom "one writer per field" in the CLI context architecture glossary; the two-writer defect in #105.

Control

hi update runs one pipeline: fetch catalog, resolve selected Packs to items through registryDependencies, plan every file action, validate merge targets parse, apply content files, apply merges, apply symlinks, install workspace dependencies, write the installed record, run managed lint, report. hi diff runs the same pipeline up to plan and compares instead of writing. hi check runs fetch and compare only.

Subagent projection is a tier 2 render inside the same pipeline: body from manifest.mjs, envelope from the Harness adapter at the installed version. Evidence: the body is byte-identical across four harness outputs; only the envelope differs (packages-db in .claude, .cursor, .opencode, .codex).

Feedback

One JSON result for every command with status, the applied version, and one row per path: created, overwritten, skipped, merged, linked, copied, removed, conflict, missing, stale, shape-drift. Planned and applied are separate fields. Evidence: #41 and #215 conflated them.

Recovery

Re-running hi update converges: unchanged files are skipped by content compare, so a crash between two writes leaves a state that the next run completes. A conflict is resolved by hi update --overwrite <path> or by keeping the file. A corrupt cache entry fails the catalog sha256 check and is refetched. Offline, hi check reports unavailable and the cached installed version; it never reports "no drift confirmed" for a failed fetch.

Handoff

After update, the result lists tier 3 files whose template changed between the installed and applied versions. The agent reviews those by hand. The hi-cli operator skill and the scaffolding runbook describe this flow.

3. Flow failure lenses

LensFindingGuarantee at stakeCandidate or unknown
1. Entry points and path convergencehi init, update, add, diff, check, and the session hook share one resolve-plan-apply pipeline. The shadcn fallback bypasses merges, symlinks, and workspace dependencies. Evidence: shadcn writes content files only (update-files.ts:386-507).Every entry reaches the same rulesK6: document the fallback as files-only; hi diff reports its gaps as missing.
2. Critical execution pathsOrder: catalog, resolve, plan, validate merge targets, content files, merges, symlinks, workspace dependencies, installed record, lint, report. Dependency install is the only subprocess.Lint runs on the real repository, not a candidateK3: plan validates every merge target parses before any write.
3. State ownership and authorityRegistry owns tier 1 and templates. Human owns settings and tier 3. Installer owns the installed record. Tier 2 is derived and never edited by hand. Evidence: #52, #53, #61, #69, #71 came from unclear tier 3 ownership.One writer per fileK1: two local files, one writer each.
4. Transaction and side-effect boundariesThe filesystem gives no multi-file transaction. Writes are ordered so the installed record lands last. Between file writes and the record, hi diff shows transient local edits. Package-manager install mutates lockfiles outside the boundary.Re-run convergesK3 ordering; no pending-publication marker. Evidence: the marker scheme produced publication-stale (update/run.ts:6825-6836).
5. Concurrency and stale stateTwo updates in one worktree at once: unknown, not observed in the issue history. Registry latest can change between check and update: update records the exact version it applied, so the record is never ahead of the files. Immutable versions remove cache staleness.Applied version equals recorded versionUnknown, non-material: concurrent updates in one worktree.
6. Idempotency and retriesA repeated update or add is a no-op when converged, by content compare. A lost result is recovered by re-running. Evidence: shadcn skipped semantics (update-files.ts:144-260).Repeating is safeNone.
7. Partial failure and recoveryCrash mid-write: re-run. Dependency install failure: files are already written; result is partial with the failing step; re-run. Malformed merge target: caught at plan, nothing written.No manual archivingK3; K7 for removal policy on failure.
8. Execution lifetime and durabilityNo long-running process, no locks except atomic rename in the cache. Unfinished work does not exist; the next run recomputes everything from registry, settings, and record.Nothing survives that needs an ownerNone.
9. Lifecycle and dependency transitionsItem adds a file: created. Item drops a file: stale, removed for tier 1, reported for tier 3. Pack removed in settings: its items become stale. Workspace added: shape drift, tier 2 re-rendered. New harness: new adapter outputs. Stale devDependencies: shadcn never removes; policy needed. Immutable versions are never yanked.Old state has no hidden dependentsK7: removal policy for stale devDependencies and tier 3 files. K5: when manifest.mjs changes, who re-renders.
10. Completion and observabilityThe installed record plus the per-path rows prove the outcome. --dry-run sets planned only. Evidence: #39, #40, #41, #215 for today's gaps.Operator can tell applied from planned from failedK2: hook and JSON key on status.

4. Candidates

Each candidate lists evidence, consequence, and the unresolved tradeoff. Accepted decisions D1 to D7 are not repeated.

  • K1. Two local files. settings.json for intent, installed.json for the installer's record (version, recorded shape, item to path map, link-or-copy per symlink). Evidence: one-writer axiom; edit hook needs paths; D2 needs the shape. Consequence: the edit hook and stale detection read one small tracked file; #231 and #204 cannot recur. Tradeoff: U2, a consumer that ignores .devpunks/ loses the record in fresh worktrees; the installer must then treat a missing record as "not installed" and offer hi update, not block edits.
  • K2. Structured status. Every command returns status from a closed set; the session hook and the operator skill key on it. A failed fetch is unavailable with the cached installed version. Evidence: the dead drift-detected branch. Consequence: the hook message is always true. Tradeoff: none found.
  • K3. Plan, validate, apply in fixed order; record last; no marker. Evidence: lens 4 and 7; the current marker scheme's failure codes. Consequence: re-run converges from any crash point. Tradeoff: a transient window where hi diff reports local edits on files that were just written.
  • K4. Catalog carries per-item sha256. Used for cache integrity only, never for repository drift. Evidence: today's archive sha256 check (baseline/resolve.ts:486-493) is the useful part of the current verification. Consequence: offline hi diff at the installed version stays trustworthy. Tradeoff: none found.
  • K5. Subagent projection trigger. Option A: only hi update and hi diff render and compare the 88 files. Option B: the edit hook also re-renders when manifest.mjs is saved. Evidence: D3; today the agent runs the sync script by hand. Consequence: A is simpler and keeps one writer; B keeps outputs fresh during authoring. Tradeoff: B puts a render inside every edit hook call.
  • K6. shadcn fallback is files-only. Document it; hi diff reconciles. Evidence: lens 1. Consequence: shadcn mcp discovery works with no extra work. Tradeoff: an operator who only uses shadcn gets no merges or symlinks.
  • K7. Removal policy. Tier 1 stale files are removed on update. Tier 3 stale files are reported, never removed. Stale devDependencies: unknown policy. Evidence: lens 9; shadcn removes nothing. Consequence: repositories do not accumulate dead managed files. Tradeoff: removing a devDependency that the project also uses directly would break it; the safe default is report-only.
  • K8. Prompt-spec skeletons render on demand. hi prompt-spec <scope> prints the skeleton instead of persisting 17 tracked files. Evidence: they are authority: repository, consumed once, and produced noise in #122. Consequence: 17 fewer managed paths and no drift on them. Tradeoff: the operator skill's post-command flow changes.
  • K9. Handoff and system prompt render on demand. hi handoff prints them; no tracked AGENT-HANDOFF.md or AGENT-SYSTEM-PROMPT.md. Evidence: no hook or script reads them; the handoff tells the agent to run hi check first. Consequence: two fewer managed paths. Tradeoff: the files are visible in git history today; on-demand output is not.
  • K10. Registry hosting. U1. Options: static files under the existing Vercel deployment; a static route in apps/api; another host. Evidence: the baseline HTTP API group (resolve, artifact, promote) in packages/contract/src/baseline.ts:289-303 becomes obsolete under D1. Consequence: the control plane loses one API group or gains a static mount. Tradeoff: an apps/api route keeps auth and telemetry in one place; a static host is simpler and cacheable by any CDN.
  • K11. Bundled fallback. Keep a bundled copy of the latest registry inside the npm package for offline hi init, or drop it. Evidence: today's bundled channel and its verified digest (baseline/bundled.ts:169-203); #43 shows a stale bundled copy applied by mistake. Consequence: dropping it removes one channel and one class of bug; keeping it allows offline first install. Tradeoff: offline first install versus one fewer source of truth.
  • K12. Private registry auth. U3. If the registry needs credentials, the registries map carries headers with ${ENV} expansion as shadcn does. Evidence: shadcn authentication docs. Consequence: no new mechanism. Tradeoff: unknown until U3 is resolved.
  • K13. Symlink fallback. When a symlink fails (Windows, #58), the installer copies and records copied in the installed record; hi diff then compares the copy by content. Evidence: today's receipt copyFallbacks. Consequence: Windows works without a separate code path in the hooks. Tradeoff: a copied hook drifts from its source until the next update.
  • K14. Issue #232 mechanism (D5). The lint runner streams oxlint JSON to a temp file and reads it, removing maxBuffer. The commit-gate runner passes file sets through stdin or a response file, drops HI_STAGED_FILES, and sets an explicit buffer on git diff --cached. Evidence: managed-lint-runner.mjs:229, commit-gate-runner.mjs:35,59-62,186-238. Consequence: large Software Scopes lint and commit. Tradeoff: whether the "expand the whole owner set on config change" rule survives when a config change is an ordinary diff.
  • K15. Anti-slop placement (D7). One root copy under tools/oxlint/anti-slop/ referenced by each workspace config with a relative path, instead of 26 vendored files. Evidence: the manifest lists 13 copies of LICENSE and index.mjs. Consequence: 24 fewer managed paths. Tradeoff: U4, a workspace published on its own would need its own copy.

5. Decisions recorded on 2026-09-27, second round

Candidate or unknownDecisionDisposition
K10, U1Host the registry with the existing HI API on Vercel. "Whatever is easiest." The exact mount (static files or an apps/api route) is delivery detail.accepted
U5, K2Session start runs the Baseline version check only, to learn whether a new Baseline exists. Full drift comparison is on demand.accepted
K8, K9Rejected. Prompt specs, AGENT-HANDOFF.md, and AGENT-SYSTEM-PROMPT.md are tied to the Baseline. They stay tracked Managed Artifacts produced from registry templates.rejected
K11Drop the bundled fallback. The registry is the only Baseline source.accepted
K15, U4Rejected. Anti-slop files stay scoped to each app and package, like the per-package lint rules. Per-workspace copies remain.rejected
K12, U3The registry needs credentials. Today Baseline access is only through the CLI with its login; the installer uses that CLI login for registry fetches.accepted
K5Option A. Only hi update and hi diff rebuild and compare the per-harness subagent files. The edit hook does not rebuild them.accepted
K7Option A. hi update removes stale devDependencies from the workspace package.json. The user accepted this with the stated risk that a project may use the same package directly.accepted

Consequences for the design above:

  • With K11 dropped, hi init needs network access and a CLI login. Offline first install is out of scope.
  • With K8 and K9 rejected, the tier 2 set keeps prompt specs, handoff, and system prompt. Their drift is handled by re-render at the installed version with the recorded shape, the same as lint configs.
  • With K12 accepted, the shadcn fallback (npx shadcn add @hi/<item>) works only when the same credential is exposed through the registries map headers. That is optional, not required.

5a. Unresolved decisions

None. Every candidate has a recorded disposition. The stated risk under K7 (removing a devDependency the project also uses directly) is not a decision gap; it is a guard for requirements-grill to specify, for example, removing only when no first-party source imports the package.

6. Required design-document changes

These are proposals; none is applied.

  • Retire in the manifest-driven update glossary: Scaffold Manifest, Validation Candidate, Prepared Installation, Validation Result, Cache Entry. Add: Registry, Registry Item, Installed Record, Recorded Shape, Tier. Route through requirements-grill.
  • Update the CLI update enforcement glossary: "CLI version pin" and "Baseline version pin" become the installed version in the installed record.
  • Rewrite docs/runbooks/hi-cli-scaffolding.md, docs/README.md, and the hi-cli operator skill post-command flow for the new commands and the structured status.
  • Refresh .agents/rules/repository/baseline-release-entrypoint.md (HI-REPO-002) for the registry publish entrypoint.
  • Record the release classification rule for the registry product under D1.

7. Validation of this brainstorm

  • Every finding above cites a file and line from the research report, an issue number, a shadcn source path, or a user decision dated 2026-09-27.
  • Lenses 5 and 9 carry explicit unknowns; both are judged non-material to the accepted scope and are listed in section 5.
  • No new mechanism or guarantee is accepted here; all are candidates.

On this page