Registry Baseline
Spec: Registry Baseline
Context
The operating agent and the human operator need the harness content in a
repository to be current, to know when it is not, and to update it without
manual repair. Today the hi CLI proves its own previous output with 654
recorded hashes, stages a temporary copy of the repository for every update,
and regenerates files the operator tailored. Of 47 CLI issues, 15 trace to
persisted derived state, 19 to generation logic, and 6 to the temporary
candidate; hash drift and candidate failures each recurred after four fix
waves. Issue #232 is open: the generated lint runner caps output at 10 MiB and
the commit gate inlines the full owner file set into one shell string.
The user closed the grill
on 2026-09-27 with Q1 to Q35 and Glossary Q32a accepted in the
decision log. The
glossary defines canonical
terms. The retained architecture is
ARCHITECTURE.md at commit 3e63ec3cdb0a07922db908dc625b6cfabfdb2a1a
(blob https://github.com/wearedevpunks/harness-intelligence/blob/3e63ec3cdb0a07922db908dc625b6cfabfdb2a1a/apps/wiki/content/docs/project/specs/cli/registry-baseline/ARCHITECTURE.md). Source evidence: the
architecture research report
and the target system brainstorm.
Non-Goals
hi report and telemetry; the backoffice; a selectable harness set per
repository (parked, Q29); single Registry Item selection outside Packs
(parked, Q35); registry credentials or a CLI login (rejected, Q19); a bundled
offline Baseline (rejected, Q10); on-demand rendering of prompt specs, handoff,
or system prompt (rejected, Q9); a copy fallback for failed symlinks (rejected,
Q27); a hi add command (rejected, Q30); implementation order, task
breakdown, and backlog projection.
Requirements Outcomes
OUT-001: One public Registry is the only Baseline source
Source: Q1, Q8, Q10, Q19.
- A Registry in the shadcn registry format is the only Baseline distributor and the only source for drift management. GitHub release artifacts and the control-plane promotion path are retired.
- The Registry is hosted with the existing HI API on Vercel. The exact mount is delivery detail.
- The Registry is public. The installer sends no credential. No
hi login, header configuration, or token storage is introduced. - No bundled Baseline exists inside the npm package.
hi initneeds network access.
OUT-002: Immutable Baseline identity and catalog
Source: Q14, Q15, Q17, Q18.
- A Baseline is one Registry version named
YYYY.MM.DD-<short sha>and is immutable once published; a correction is a new Baseline. - The catalog
registry.jsonholds onelatestpointer that moves on publish. There is no promotion step. - Each Baseline declares a compatible CLI version range. The CLI refuses a Baseline outside its range and tells the user to upgrade.
- The catalog carries a sha256 per Registry Item, used only to verify the installer's download cache, never for repository drift.
OUT-003: Registry publication from the existing release flow
Source: Q4, Q16.
- The existing release workflow builds the Registry from
apps/cli/skillsandapps/cli/src/dataand publishes it.BASELINE_CHANGELOG.mdremains the product selector. Theskillsrepository remains the source of truth through the existing sync. - Registry Item JSON stays byte-compatible with the shadcn registry-item schema
so
npx shadcn addandshadcn mcpremain usable fallbacks for Copied Artifacts. Harness-specific needs live under itemmeta: symlinks, structured merges into repository-owned JSON and YAML, per-workspace devDependencies, and templates with declared inputs.
OUT-004: The Registry serves the full harness context
Source: Q7, Q9, user constraint recorded in the brainstorm boundary.
- Registry Items cover skills, hooks, runtime scripts, source guides, lint
assets, prompt specs, the shared prompt, the subagent spec,
AGENT-HANDOFF.md,AGENT-SYSTEM-PROMPT.md, the Commit Gate, the wiki starter, and the required tools list. - Anti-slop rules stay the default lint asset for TypeScript Software Scopes. Their files stay scoped to each app and package.
- Prompt specs, handoff, and system prompt stay tracked Built Artifacts produced from Registry templates.
OUT-005: Two local state files with one writer each
Source: Q2, Q20, Q22.
.devpunks/settings.jsonholds intent only: registries, selected Packs, Software Scopes, providers, required tools. A human, or the agent on request, writes it..devpunks/installed.jsonis the Installed Record: installed Baseline version, Recorded Shape (workspace paths, Pack ids, detected technologies), item-to-path map, and failed symlinks. Only the installer writes it.- Selected Packs are explicit in settings. Detection runs at
hi initand on request and only proposes. A detected but unselected Pack is information, never drift. - No content hash of any Managed Artifact is stored in the repository.
OUT-006: Three Managed Artifact kinds with three rules
Source: Q9, Q24, Q31, Glossary Q32a.
- A Copied Artifact is written verbatim from a Registry Item. Update overwrites it; identical content is skipped.
- A Built Artifact is rendered from a Registry Item template, Project settings, and the Recorded Shape. Update re-renders it; identical content is skipped.
- An Authored Artifact is written once when absent and never compared or
overwritten afterwards.
AGENTS.mdfiles,.agents/subagents/manifest.mjs, the wiki starter,.codex/config.toml, and Project Skills are Authored Artifacts. - With
--yes, a Copied Artifact that has both a local edit and an upstream change is overwritten and its path is reported; git keeps the local version.
OUT-007: One idempotent update pipeline
Source: Q13, Q23, Q26, Q27.
hi updateruns in this order: fetch catalog and check the CLI range; resolve selected Packs to Registry Items through registry dependencies; plan every path; validate that every structured merge target parses; write Copied Artifacts; render Built Artifacts; write absent Authored Artifacts; apply merges; create symlinks; add required workspace devDependencies and remove stale ones; remove stale Copied Artifacts and report stale Authored Artifacts; write the Installed Record last; run managed lint on the real repository; report.- No temporary repository candidate, lint preview, or pending-publication marker exists. Any invalid merge target stops the run before any write.
- A stale devDependency is removed only when no first-party source file in that workspace imports the package; otherwise it is reported and kept.
- A symlink that cannot be created is reported with its path and target. No copy is made. The next update retries.
- Re-running update after a failure at any step converges without manual repair.
OUT-008: Three-way Drift Check
Source: Q2, Q25, Q27.
hi diffcompares, per managed path, local bytes, the Registry Item at the installed Baseline, and the Registry Item at the latest Baseline, and writes nothing.- Copied Artifacts compare after normalizing line endings and trailing
whitespace only. Built Artifacts compare by re-rendering at the installed
Baseline with the Recorded Shape; a re-render with the current shape that
differs is
shape-drift. Authored Artifacts are never byte-compared; a changed template is reported as information. - Every path reports exactly one class:
update-available,local-edit,conflict,shape-drift,missing,stale, orlink-failed.
OUT-009: Cheap, honest check and session start
Source: Q6, Q21.
hi checkfetches the catalog, compares the installed Baseline version withlatest, verifies required tools, and returnsstatusfrom the closed setcurrent,update-available,unavailable,not-installed. It does not run the full Drift Check.- When the Registry cannot be reached,
statusisunavailableand the output includes the cached installed version. The output never states that no drift was confirmed after a failed fetch. - The session-start hook keys on
statusonly and stays installed for Claude, Codex, Cursor, and OpenCode. - The edit hook reads protected paths from the Installed Record. When the record is missing, it treats nothing as managed and never blocks an edit.
OUT-010: Harness Adapters replace the shipped projection script
Source: Q3, Q12, Q29.
- The
hiCLI builds each subagent body once from.agents/subagents/manifest.mjsand wraps it in one envelope per harness through a Harness Adapter for Claude, Codex, Cursor, and OpenCode, always all four. sync-subagents.mjsand.agents/scripts/harness-projection/*are no longer distributed or executed in consumer repositories.- Per-harness subagent files are rebuilt only by
hi updateandhi diff. The edit hook does not rebuild them.
OUT-011: Command surface
Source: Q30.
- The commands are
hi init,hi update,hi diff,hi check. hi initdetects the repository once, proposes Packs and Software Scopes, writes Project settings from the confirmed selection, then runs the update pipeline.hi scaffoldis retired intoinit. Nohi addexists.
OUT-012: Project Skills are preserved
Source: Q31, Q34.
- Skills present in a repository before Harness, and skills no Registry Item
provides, are Project Skills under
.agents/skills/<id>. They are reachable through the existing harness symlinks. - The installer never removes, compares, or overwrites a Project Skill.
- When a Registry Item later provides a skill with a Project Skill's id, the
Baseline skill wins: the Project Skill directory is renamed
[DEPRECATED] <name>, the Registry skill is installed under the original id, and the command reports each such case. - The
replaced-scaffold,replaced-skills, andpre-existing-skillsarchives are retired. A conflict shows as a git diff.
OUT-013: One-run migration of manifest-based repositories
Source: Q33.
- The first registry-based
hi updatein a repository that has.devpunks/scaffold-manifest.jsonand no Installed Record migrates in the same run: it reads the old settings for Packs, Software Scopes, providers, and required tools; runs detection once to build the Recorded Shape; moves skills frompre-existing-skillsinto.agents/skillsas Project Skills; deletesscaffold-manifest.json,harness-projection-receipt.json,context-plan.json,specs/lint/assets.json,replaced-scaffold,replaced-skills, and the emptied archive; keeps every Authored Artifact; writes the Installed Record; and reports each deletion. - No separate migrate command exists.
OUT-014: Managed lint and Commit Gate work on large Software Scopes
Source: Q5, Q28.
- Issue #232 is fixed in the same release that ships the Registry.
- The managed lint runner preserves lint-finding exit semantics for any output size; a 13.5 MB oxlint JSON report is classified as findings, not as an operational failure.
- The Commit Gate passes file sets to lint and format commands without exceeding operating-system argument limits, and keeps the rule that a lint configuration change lints the full owner file set.
- The Commit Gate's staged-file listing does not fail on large staged sets.
OUT-015: Aligned language and operator knowledge
Source: Q32, repository guidance on docs updates.
- The canonical terms Registry, Registry Item, Baseline, Installed Record, Recorded Shape, Copied Artifact, Built Artifact, Authored Artifact, Project Skill, Harness Adapter, and Drift Check are used in CLI output, docs, and the operator skill. Scaffold Manifest, Validation Candidate, Prepared Installation, Validation Result, Cache Entry, and Context Plan as a file are retired from current documentation.
docs/README.md, the scaffolding runbook, thehi-clioperator skill post-command flow, and ruleHI-REPO-002describe the delivered behavior in the same delivery.
Acceptance Criteria
- AC-001: With the control-plane
baselineendpoints and GitHub release artifacts unavailable,hi initandhi updatesucceed against the Registry alone.- Covers: OUT-001
- AC-002:
hisends noAuthorizationheader and reads no credential when fetching the Registry, and the Registry responds without one.- Covers: OUT-001
- AC-003: The published
@punks/clipackage contains no bundled Baseline, andhi initwithout network access reportsunavailableinstead of installing.- Covers: OUT-001
- AC-004: Re-publishing an existing version identifier is rejected by the publisher, and fetching a version returns the same bytes on every request.
- Covers: OUT-002
- AC-005: After a publish,
registry.jsonlatestequals the new version and no promotion call is required forhi updateto select it.- Covers: OUT-002
- AC-006: With a Baseline whose CLI range excludes the installed CLI,
hi updatewrites nothing and reports the required CLI range.- Covers: OUT-002
- AC-007: A cached Registry Item whose bytes do not match the catalog sha256 is discarded and refetched, and the sha256 is never used in a Drift Check class decision.
- Covers: OUT-002
- AC-008: The release workflow produces
registry.jsonand one item JSON per Registry Item fromapps/cli/skillsandapps/cli/src/data, and a run whose changed changelog paths excludeBASELINE_CHANGELOG.mdpublishes no Registry.- Covers: OUT-003
- AC-009: Every published item JSON validates against the shadcn registry-item schema, and
npx shadcn addof a Copied-only item writes its files under the repository root.- Covers: OUT-003
- AC-010: For a repository selecting all default Packs,
hi updateinstalls every artifact kind listed in OUT-004, including anti-slop files inside each TypeScript Software Scope and tracked prompt spec, handoff, and system prompt files.- Covers: OUT-004
- AC-011: After
hi update,.devpunks/containssettings.jsonandinstalled.jsonand no file containing a content hash of a Managed Artifact.- Covers: OUT-005
- AC-012:
hi updatenever modifiessettings.json, and no command other thanhi initandhi updatemodifiesinstalled.json.- Covers: OUT-005
- AC-013: A Pack detected but absent from
settings.jsonis reported as information and produces no drift class and no non-zero exit.- Covers: OUT-005
- AC-014: A locally edited Copied Artifact is overwritten by
hi update --yeswith its path in the report, and an identical file is reportedskipped.- Covers: OUT-006
- AC-015: A Built Artifact changes after
hi updateonly when its template, Project settings, or the Recorded Shape changed.- Covers: OUT-006
- AC-016: An existing Authored Artifact is byte-identical before and after
hi update, with or without--yes.- Covers: OUT-006
- AC-017:
hi updateperforms its steps in the order in OUT-007, andinstalled.jsonis written after every other file effect.- Covers: OUT-007
- AC-018: With one unparsable merge target,
hi updateexits non-zero and no repository file changes.- Covers: OUT-007
- AC-019: A devDependency no longer required by any installed lint asset is removed when no first-party source in that workspace imports it, and kept with a report when one does.
- Covers: OUT-007
- AC-020: When symlink creation fails,
hi updatereports the path and intended target, creates no copy, records the failure ininstalled.json, and completes the remaining steps.- Covers: OUT-007
- AC-021:
hi updateinterrupted after any step, then re-run, produces a repository byte-identical to an uninterrupted run.- Covers: OUT-007
- AC-022:
hi diffreports one class per managed path from the set in OUT-008 and modifies no file.- Covers: OUT-008
- AC-023: A Copied Artifact that differs only in line endings or trailing whitespace is reported as no drift; one that differs in other bytes is reported
local-edit.- Covers: OUT-008
- AC-024: Adding a workspace to a repository makes
hi diffreportshape-drifton affected Built Artifacts andlocal-editon none of them.- Covers: OUT-008
- AC-025:
hi check --jsonreturnsstatusfrom the set in OUT-009, completes without fetching any Registry Item, and does not read repository file contents.- Covers: OUT-009
- AC-026: With the Registry unreachable,
hi check --jsonreturnsstatus: unavailablewith the installed version and the session hook message contains no statement that drift is absent.- Covers: OUT-009
- AC-027: In a git worktree without
installed.json, the edit hook allows every edit, andhi checkreturnsstatus: not-installed.- Covers: OUT-009
- AC-028: After
hi update, each subagent inmanifest.mjshas one file in each of.claude/agents,.codex/agents,.cursor/agents,.opencode/agentswith an identical body and the harness envelope, and nosync-subagents.mjsorharness-projectionscript exists under.agents/scripts.- Covers: OUT-010
- AC-029: Editing
manifest.mjschanges no harness agent file untilhi updateruns, andhi diffreports those filesstalein between.- Covers: OUT-010
- AC-030:
hi --helplists exactlyinit,update,diff,checkas scaffold lifecycle commands, andhi scaffoldandhi addare unknown commands.- Covers: OUT-011
- AC-031: In a repository with a skill under
.claude/skills/foothat no Registry Item provides,hi initleavesfooinstalled under.agents/skills/foo, reachable through.claude/skills, and never modifies or removes it on later updates.- Covers: OUT-012
- AC-032: When a later Baseline provides
foo,hi updaterenames the Project Skill directory to[DEPRECATED] foo, installs the Registryfoo, and lists the rename in its report.- Covers: OUT-012
- AC-033: After
hi update, noreplaced-scaffold,replaced-skills, orpre-existing-skillsdirectory exists under.devpunks/.- Covers: OUT-012
- AC-034: In a repository with
scaffold-manifest.jsonand noinstalled.json, onehi updaterun leavesinstalled.jsonpresent, every file in the OUT-013 deletion list absent, every Authored Artifact byte-identical, archived skills present as Project Skills, and each deletion listed in the report.- Covers: OUT-013
- AC-035: A Software Scope whose oxlint JSON output exceeds 10 MiB returns lint findings and the findings exit code, not an operational failure.
- Covers: OUT-014
- AC-036: A lint configuration change followed by
git commitlints the full owner file set for a scope whose file list exceedsARG_MAX, and the gate exits with the lint result.- Covers: OUT-014
- AC-037: Current
docs/README.md, the scaffolding runbook, thehi-clioperator skill, and ruleHI-REPO-002use the OUT-015 canonical terms and contain none of the retired terms except in historical references.- Covers: OUT-015
Constraints
- Shared skills stay sourced from the
skillsrepositorymainbranch through the existing sync;apps/cliowns the executable and generated assets;apps/apiowns the control plane (repository guidance). - Changed changelog paths remain the release product selector;
BASELINE_CHANGELOG.mdselects the Registry (Q16). - Each local state file has exactly one writer (glossary axiom).
- A Baseline is immutable; a correction is a new Baseline (glossary axiom).
- Compare and report in ASD-STE100 Simplified Technical English using the canonical terms (repository guidance).
Dependency Readiness
No Stack Required. The retained architecture is a source, not a delivery
dependency. The unmerged branch team/stefan/codex-edit-hooks (commit
ffee129a, issue #231) is superseded by OUT-009 and is not a dependency.
Branch/Base Intent
Not applicable. No parent or base constraint was accepted. The architecture and
this spec are retained on team/stefan/registry-baseline-architecture as
requirements bookkeeping; delivery chooses its own branch.
Accepted Technical Decisions
The architecture's blocks ARC-001 to ARC-012 and flows FLOW-001 to FLOW-005
are the accepted design. In summary: a static, public, versioned Registry with
a latest pointer; an in-house installer that reads shadcn-compatible item
JSON plus meta extensions; two local files with one writer each; Copied,
Built, and Authored Artifact rules; a plan-validate-apply pipeline that writes
the Installed Record last and has no candidate or marker; a three-way Drift
Check; Harness Adapters inside the CLI; and a migration branch inside hi update. Retired: the baseline HTTP API group and promotion store, the bundled
channel, the Scaffold Manifest, projection receipt, context plan, Validation
Candidate, sync-subagents.mjs, the harness-projection scripts, and the three
archives.
Delivery detail left to planning: the exact Vercel mount, the meta extension
field names, the Harness Adapter envelope formats, the migration branch's
internal structure, and the lint runner's streaming mechanism.
Accepted Testing Decisions
No testing decisions were accepted upstream. Verification derives from the
seams below and from the acceptance criteria; create-plan owns test files,
fixtures, and commands. The issue #232 reproduction (13.5 MB oxlint output;
owner file set beyond ARG_MAX) is the accepted regression witness for
OUT-014.
Verification Seams
hi init,hi update,hi diff,hi checkJSON output:status, applied version, one row per path with its action or drift class..devpunks/installed.jsoncontents after each command.- Registry catalog and item JSON as served, and the release workflow's publish step.
- Repository file effects: Copied, Built, and Authored Artifacts, harness agent
files, workspace
package.jsondevDependencies, symlink presence, Project Skill directories. - Session-start and edit hook outputs for Claude, Codex, Cursor, OpenCode.
- Managed lint runner and Commit Gate exit codes and reports under the #232 reproduction.
Parked Decisions
- Selectable harness set per repository. Owner: user. Resume trigger: a repository that must exclude one harness (Q29).
- Single Registry Item selection outside Packs. Owner: user. Resume trigger: a real request for one skill that no Pack contains (Q35).
Decision Log
| Decision | Evidence | Rationale |
|---|---|---|
| One public Registry replaces artifacts, promotion, and bundle | Q1, Q8, Q10, Q14–Q19 | Nine authority issues came from three sources and a promotion step |
| Two intent and record files, no hashes | Q2, Q20–Q22 | Six hash-drift and two portability issues came from persisted derived state |
| Copied, Built, Authored rules; Project Skills preserved | Q9, Q24, Q31, Q34 | Seven issues came from overwriting tailored files |
| Plan-validate-apply, record last, no candidate | Q23, Q26, Q27 | Six issues came from the temporary candidate |
| Three-way Drift Check; version-only session check | Q2, Q6, Q25 | Drift without stored hashes; session hook's drift branch was dead |
| Harness Adapters in the CLI | Q3, Q12, Q29 | Body is identical across harnesses; the script was a second writer |
| Four commands; one-run migration | Q30, Q33 | Smallest surface that converges existing repositories |
| #232 fixed in the same release | Q5, Q28 | Runner and gate are Registry Items in that release |
Compilation Evidence
15 unique outcomes and 37 uniquely identified acceptance criteria cover Q1 to Q35 and Glossary Q32a; Q11 is superseded by Q19. Every criterion names its outcome. Two branches are parked with owner and trigger. Compilation is not implementation, release readiness, or remote retention.
Current compilation validation
- HI-WIKI-001: pass — owning route metadata registered;
bun run --cwd apps/wiki check:contentpassed. - HI-WIKI-003: pass — frontmatter validates; links resolve in the routed tree.
- HI-DOCS-001: pass for this artifact — requirements and glossary stay in routed project knowledge; implemented docs are OUT-015 delivery work.
- API, runtime, UI, release, and generated-asset checks: not-applicable to this documentation wave.