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.
| Id | Decision | Source |
|---|---|---|
| D1 | The registry is the Baseline distributor and the source for drift management. GitHub release artifacts stop. | user, 2026-09-27 |
| D2 | Built Managed Artifacts keep their install-time repository shape (workspace paths, Pack ids) in Project settings. | user, 2026-09-27 |
| D3 | hi builds each subagent body once and wraps it per harness. sync-subagents.mjs is removed. | user, 2026-09-27 |
| D4 | hi has its own small installer. Item JSON stays shadcn-compatible. | user, 2026-09-27 |
| D5 | Issue #232 is fixed inside the registry release. | user, 2026-09-27 |
| D6 | A session-start hook that checks the Baseline stays. | user, 2026-09-27 |
| D7 | Anti-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.tsbuilds 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 structuredstatusfield: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
| State | Owner and writer | Authoritative for | Location and lifetime |
|---|---|---|---|
Registry catalog registry.json | Publisher (CI) | Item list, latest version, per-item sha256 | Remote, mutable pointer to immutable versions |
Registry item /<version>/<id>.json | Publisher (CI) | Item files and metadata at that version | Remote, immutable |
Project settings settings.json | Human (agent on request) | Intent: registries, Packs, Software Scopes, providers, required tools | Tracked |
Installed record installed.json | hi installer only | Installed version, recorded shape (D2), item to path map, link-or-copy per symlink | Tracked, small |
| Item cache | hi installer | Nothing; a copy of immutable item JSON | ~/.cache, verifiable by catalog sha256 |
| Tier 1 files (skills, hooks, scripts, guides, lint plugin) | Registry | Content | Repository |
| Tier 2 built files (lint configs, shared prompt, subagent spec, commit gate, per-harness agents) | Registry version × settings × recorded shape × authored inputs | Content, by re-render | Repository |
Tier 3 authored files (AGENTS.md, manifest.mjs, wiki, codex config) | Repository | Content | Repository, 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
| Lens | Finding | Guarantee at stake | Candidate or unknown |
|---|---|---|---|
| 1. Entry points and path convergence | hi 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 rules | K6: document the fallback as files-only; hi diff reports its gaps as missing. |
| 2. Critical execution paths | Order: 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 candidate | K3: plan validates every merge target parses before any write. |
| 3. State ownership and authority | Registry 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 file | K1: two local files, one writer each. |
| 4. Transaction and side-effect boundaries | The 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 converges | K3 ordering; no pending-publication marker. Evidence: the marker scheme produced publication-stale (update/run.ts:6825-6836). |
| 5. Concurrency and stale state | Two 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 version | Unknown, non-material: concurrent updates in one worktree. |
| 6. Idempotency and retries | A 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 safe | None. |
| 7. Partial failure and recovery | Crash 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 archiving | K3; K7 for removal policy on failure. |
| 8. Execution lifetime and durability | No 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 owner | None. |
| 9. Lifecycle and dependency transitions | Item 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 dependents | K7: removal policy for stale devDependencies and tier 3 files. K5: when manifest.mjs changes, who re-renders. |
| 10. Completion and observability | The 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 failed | K2: 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.jsonfor intent,installed.jsonfor 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 offerhi update, not block edits. - K2. Structured status. Every command returns
statusfrom a closed set; the session hook and the operator skill key on it. A failed fetch isunavailablewith the cached installed version. Evidence: the deaddrift-detectedbranch. 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 diffreports 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: offlinehi diffat the installed version stays trustworthy. Tradeoff: none found. - K5. Subagent projection trigger. Option A: only
hi updateandhi diffrender and compare the 88 files. Option B: the edit hook also re-renders whenmanifest.mjsis 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 diffreconciles. Evidence: lens 1. Consequence:shadcn mcpdiscovery 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 areauthority: 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 handoffprints them; no trackedAGENT-HANDOFF.mdorAGENT-SYSTEM-PROMPT.md. Evidence: no hook or script reads them; the handoff tells the agent to runhi checkfirst. 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: thebaselineHTTP API group (resolve,artifact,promote) inpackages/contract/src/baseline.ts:289-303becomes obsolete under D1. Consequence: the control plane loses one API group or gains a static mount. Tradeoff: anapps/apiroute 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
registriesmap carriesheaderswith${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
copiedin the installed record;hi diffthen compares the copy by content. Evidence: today's receiptcopyFallbacks. 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, dropsHI_STAGED_FILES, and sets an explicit buffer ongit 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 ofLICENSEandindex.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 unknown | Decision | Disposition |
|---|---|---|
| K10, U1 | Host 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, K2 | Session start runs the Baseline version check only, to learn whether a new Baseline exists. Full drift comparison is on demand. | accepted |
| K8, K9 | Rejected. 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 |
| K11 | Drop the bundled fallback. The registry is the only Baseline source. | accepted |
| K15, U4 | Rejected. Anti-slop files stay scoped to each app and package, like the per-package lint rules. Per-workspace copies remain. | rejected |
| K12, U3 | The registry needs credentials. Today Baseline access is only through the CLI with its login; the installer uses that CLI login for registry fetches. | accepted |
| K5 | Option A. Only hi update and hi diff rebuild and compare the per-harness subagent files. The edit hook does not rebuild them. | accepted |
| K7 | Option 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 initneeds 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 theregistriesmap 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 thehi-clioperator 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.