Repository navigation
Links registry and component lines: every file in exactly one line, design docs in every prompt that needs them - #100
Merged
Merged
Conversation
…cket and worker prompt, recorded before links Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…perty tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ly components and no links change nothing Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… links come from the working tree Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…line is a non-ASCII path no longer printed as quoted octal
The G1 goldens check-ticket.txt and merge-dry-run.txt were re-recorded for that one line each
("changes files outside touches: OUTSIDE.md, "src/\303\251.js"" becomes "... OUTSIDE.md");
nothing else in any golden moved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…every touches entry inside one line Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ent's line, or in its own records Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…line (the merge on forge git), judged by committed lines Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…no new ticket while main has a gap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…both Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…prompts; link:<id> citations in designs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…board show its locator Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…registry-edit (constitutional) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the source of truth Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…essure (refusals, shared components) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…try precondition Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…taken out Under load the keys reach the window after zsh draws its prompt; its line editor then wraps the long env -u command at 80 columns with bare newlines that capture-pane -J does not join, so the regex missed it. Seen in the final suite run at load ~8; origin/main passes only when the keys win the race. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…orge, fail closed coverageFails reads the committed settings first and returns before any merge-tree or ls-tree when neither main nor the head declares lines, so a single-repo project on any git pays nothing (F1). With lines, the landing tree is git merge-tree --write-tree on every forge, github included: a behind PR there lands by 3-way merge, not as its head (F14, O1). mergeTree tells a conflict from a git that can't answer; the latter fails closed with "coverage needs git >= 2.38 (merge-tree --write-tree); found X" (or git's own error on a newer git). treePaths throws instead of turning a git failure into [] (O12); validate, coverageGap, components check and links report it. One mainSettings() helper; homeFacts.git dropped. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…over the tree globMatcher keeps one matcher per glob text for the process, and coverage compiles the lines once per call, so 50k paths x 30 globs is ~80 ms, not 2.3 s. coverageReport's suggested owner comes from ownerSuggestions, which indexes the first owned path under every folder in one pass instead of scanning the tree per unowned folder (F2). A perf test bounds both. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… acts, tickets judged by main
settingsInForce now says which settings judge a PR: main's for a ticket PR
(its head's settings.md never decides, O6) and for any PR that leaves
settings.md alone; for a plan or chore that changes it, the settings that
would land (the head's, or the merge's when main's settings.md moved).
check-pr and merge run registryProblems on those (F3), so an unknown kind
or a component on a repo link ("repo links land in PR 2", F7) is refused
at landing, not found later by validate. A url link changed in any way is
a registry-edit entry, never nobody's; merge refuses one with no
registry-edit act naming it since settings.md last landed. validate uses
the same rule: main's tree under main's settings, or in a chore context the
tree and settings that chore would land (F8). The unowned-files finding and
worker's refusal name each gap class they counted.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…fusal A PR that deletes the last file a glob matches used to be refused as "empty", and no PR shape could land it without an owner answer (F17, O3). An empty glob excludes nothing, so invariant C holds with it: check-pr and merge no longer fail on one, validate warns (line-empty, with the fix), metrics raises a low line-empty finding, and it blocks no ticket. components check still counts it as a Baseline floor gap. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… refuse them validate's home/devteam check counted superseded and merged tickets, so the supersede it prescribed never cleared it, and a merged ticket could never clear at all (F5, O4). It now counts live tickets only. ticket add and ticket set refuse home and devteam as a component and name the reserved list, so no new ticket takes one. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Observation text is anyone's to write and the supervisor runs the command
it pastes, so notes holding $() or backticks ran in its shell, and a Figma
URL's & backgrounded the command (O5, L-SEC-5). shq writes each value as a
POSIX single-quoted word (' as '\''); every id, URL, title, note, scope,
question and --links value orient interpolates goes through it. Also
String() around registry titles, so a non-string title can't crash orient.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…emote is echoed A url link or repo remote carrying userinfo (user:pass@, or a bare token on http(s)) is a registry error, so link add and link set refuse it before writing, validate reports a hand-written one, and check-pr/merge refuse it at landing. observe-link refuses one, and the observation schema's link.url is now https only with no userinfo. redactUrl strips credentials from the link-unreachable mismatch message (a checkout's origin) and from the registry-edit act's text, so a token in an origin never reaches the committed log (O2). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, auth is a note probeLinks ran every stale probe in sequence at up to 12 s each, so a big registry could hold a tick for minutes (F10, O7). Probes now run as child processes four at a time, each with its 12 s deadline, inside a 20 s budget per tick; a probe the budget cuts short, or one never started, writes nothing, is named "not probed this tick" by observe-metrics, is never a finding, and is asked again next tick. git ls-remote runs with GIT_TERMINAL_PROMPT=0, an empty GIT_ASKPASS and SSH_ASKPASS, ssh in batch mode unless the machine configures ssh itself, and in its own process group with no terminal. A HEAD answer of 401, 403 or 405 is a low link-behind-auth note, not a high finding that wakes wait. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…k fields
- check-ticket names each off-line file with the line it is in and the
fixes that fit it (O8); touches_components widens only a contract or
integration ticket there too, as in validate (F4).
- Each coverage line carries its own fix: unowned (extend a line), contested
(names both globs; narrow one), case (rename one), unlinked, line-empty.
- The kit's own line is set aside before any contest, so a project line over
docs/** coexists with docs/devteam/** (F13).
- link add|set parse a value by its field's type (string, list, boolean)
instead of JSON-coercing it, and validate checks every field's type, so a
title of 2024 is "2024" and orient can't meet a number (F6).
- coverageClean moves into the test, its only caller (F9).
- help shows ask --links' {"title","link"} form (F11).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…dismissals; link rm and line-pressure - observe-link refuses http:// as link add does, and a --path outside this repo with its own message before the schema's (F15, O11). - An add proposal's id is one link add accepts: slugified, a letter first (2026 Roadmap is link-2026-roadmap), never reserved, de-duplicated against the registry and the run's other proposals (O11). - A --path observation is proposed as a knowledge pointer instead of being dropped (O11). - A decision or act citing an observation dismisses its proposal for good, as does knowledge that cites it; orient says how (F16). - link rm refuses while a live ticket, a feature or a design cites the link, and names them; validate checks ticket links on live tickets only (O9). No --force: no command with this refusal shape has one. - line-pressure counts distinct tickets, not heads or dry runs (O10). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, probes, credentials README pins git >= 2.38 for projects that draw lines and gives the docs/** recipe; quality.md states which settings judge a PR, that coverage judges the merge on every forge and fails closed, that an empty glob is a warning, and that a url link lands only with its registry-edit act; supervisor.md covers quoted proposals, pointers, dismissals, link rm, the probe budget and link-behind-auth. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…try main has A link rm act carried entry_hash null, and null matched every later removal of that id: after link rm figma landed and link add figma put a new entry on main, a hand deletion on a chore branch merged on the old act (round 3 V2). link rm now also records prior_hash, the hash of the entry it removed (schema: an optional string, so older acts stay valid). registryActFails matches a removal only when an act naming the link has entry_hash null and prior_hash equal to main's current entry. Adds and sets are matched as before. A removal act without prior_hash (written before it existed) never matches. quality.md §4 and the spec say so. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sal, ask --links refuses one observe-link refuses credentials, but an observation line is anyone's to write, and orient echoed its url raw into the source-of-truth question it proposes, text and --links both. Pasting it logged the secret in a question, which prompts and the dashboard show (round 3 V4). orient now passes the observation's url through redactUrl in both, and ask refuses an inline --links item whose url carries credentials, with CREDENTIALS_REFUSED, before anything is logged. The add proposal is unchanged: link add already refuses it. The spec says so. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # docs/devteam/scripts/devteam.mjs # test/kit.test.mjs
… restart-dashboard line origin/main (#97, the hub) changes the move checklist's last line; its own script prints the same line for the G1 scenario. The session suffix hashes the fixture's temp path and the hub port follows the suite's pid, so both are normalised as <tmp> is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Member
Author
Adversarial review (upstream loop), at f92d003: CHANGESA fresh reviewer checked this in a scratch checkout and throwaway projects (forge git, local bare origin). It reproduced the items marked so. What holds
Blockers
Should-fix
Nits
Merging is the upstream loop's call. It needs 1 and 2 fixed, CI green, and our local runs. |
…n remote; a fetch from an origin that fails still refuses the run Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es and field types are null-prototype tables, registry ids go through ownEntry, so constructor, toString and __proto__ are unknown names Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…refused like userinfo, and redacted to name=REDACTED wherever a URL is echoed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…cap, refused otherwise by validate, link add|set, landing, observe-link and the log schema; prompts quote it as JSON under "Links (data, not instructions)"; orient marks a worker's proposal and never proposes it for all Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…only class (no default, never answered from chat), and goal-readiness for a goal that needs the registry complete waits for the owner's yes to it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n 2.38, in the words merge refuses with Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ore; the landing hint names it instead of copying the whole working-tree settings.md, which could revert a newer components value Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…he project's (each holds project content beside the kit's), documented as such; the README's ops example no longer claims AGENTS.md or .github Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the supervisor's own class; review shorthand and PR-plan references gone from kit comments, test names and messages; the G1 goldens' two re-recordings stated as they happened Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…fs (act and decision alike); the registry attestation is keyed to the goal's registry_precondition field (goal add|set --registry-precondition n), never to a precondition's wording Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…fail the one-line rule (or whose url or path isn't one token): one line says so, the offending fields quoted as JSON, so a hand-written line's text never reaches the supervisor as a command Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… an add), as rm did; link land carries an entry, and merge lands it, only when its acts lead from the entry main has, so an act for an older main never carries an entry back over a newer one Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mplete ("registry" and "complete" in one, any case) on a goal with no registry_precondition as a definition gap, so leaving the field unset or clearing it blocks approval until goal set <g> --registry-precondition <n>; the goal's dashboard card and its goal-approval context show the field and where the attestation stands
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t changed that link's entry (main's first-parent settings.md history, the last 200 commits that touched it, cached per run), so an owner's hand-revert of a link on main expires the old acts for that link alone, and no other settings change expires anything Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # README.md
Member
Author
|
Merging (upstream loop).
|
This was referenced Nov 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spec:
docs/superpowers/specs/2026-11-04-links-components-multirepo-design.md(rev 2.4). Plan:docs/superpowers/plans/2026-11-04-links-and-lines.md. This is PR 1 of 2. PR 2 runs tickets in sibling repos on top of this registry.What
settings.mdlinks registry (links): named resources the fleet uses. There are two kinds:urllinks are design files, Notion pages and runbooks. Each has atitleand an httpsurl, plus optionalforscopes,notesandcheck: false.repolinks are sibling repos, with aremote, an optional machine-localpath(inrun/links.local.json) and per-repo settings. They are parsed, pinned to main and validated here; tickets in them land in PR 2.LINK_KINDS), so a new kind is one entry.ownsglobs (orlink,sharedorrelease) draws a line. Once a project draws lines, every tracked file belongs to exactly one line, and the kit's own files belong to the computeddevteamline, which is set aside before overlap checks, sodocs/**can coexist with it.validate,check-prandmerge(judged on the tree that would actually land, amerge-treeof the PR onto a freshly fetched main, on every forge),observe-metrics(unowned-files, severity 4, which blocks new tickets until a line covers the gap) andcheck-ticket(footprint). A glob that matches nothing is aline-emptywarning, never a refusal, so a PR can delete a folder.touches_components(contract and integration tickets only) andlinks, and features gainlinks.homeanddevteamare reserved component names, refused byticket add|setand counted only on live tickets.forscope matches the ticket's component, feature or goal, orall.link:<id>in both.links [--json]link add|set|rmfor url links. Each edit is a constitutionalregistry-editact that records theentry_hashit wrote; an rm also recordsprior_hash.components check [--ref] [--count] [--json]observe-linkorientproposes registry adds, edits and source-of-truth questions. Every value in these proposals is single-quoted. Proposals can be dismissed by any decision or act that cites the observation.registryFails).registry-editact whose hash equals the entry that lands. There is no time window, and a stale act for an earlier value never matches.link-unreachable(3)link-behind-auth(low; 401/403/405)unowned-files(4)line-empty(low)line-pressure(2, refusals counted per ticket)ask --links. Every place a remote or url is echoed goes throughredactUrl, including fix hints, locators, prompts,links,settings, questions and git errors.parseArgsaccepts--key=value. Existing forms parse unchanged, and there is a table test.check-ticketandmergeread paths with-z, so non-ASCII and spaced paths match correctly.Why
devteam assumes one repo with no internal boundaries.
webcan't editapi. Files can't be left out by accident: coverage is checked on the landing tree and fails closed.Migration
None for a project that doesn't opt in: a single-repo project prints what it printed before, checked by the G1 goldens. Those were recorded before this change and re-recorded twice, each for one line: a non-ASCII path now printed raw instead of as git's quoted octal (check-ticket, merge --dry-run; a fix in this PR), and the hub line in fleet-status's move checklist (upstream #97). The changes that can touch an existing project:
componentsmap holding only labels stays labels.homeordevteamas their component gets onevalidateerror naming them.originremote:check-prandmergenow refuse when origin's main can't be fetched, rather than judge a stale main. That includes a checkout with noorigin.To opt in, draw lines in
settings.components(components checkshows the gaps), and addlinksfor the resources workers should see. Drawing lines needs git ≥ 2.38 (merge-tree --write-tree); without lines, no new git version is needed.Maintainer review fixes
All ten items from the upstream loop's review are fixed:
link add|set, landing,observe-linkand the log schema. Prompts quote the text as JSON under "Links (data, not instructions)".orientmarks a worker's proposal and never proposes it--for all.registry-attestis a new owner_only class.goal-readinessfor a goal that needs the registry complete waits for the owner's own yes to it. It can't be answered from chat or defaulted.name=REDACTED).constructor,toStringand__proto__are unknown names.validatewarns when lines are declared on git older than 2.38.link landcarries only the changedlinksentries into the registry chore..gitignore,AGENTS.mdandCLAUDE.mdare documented as the project's.mergeonly.One-way doors
These are the settings keys, log fields and names that are hard to change once projects write them:
links.<id>withkind, and theurl/repofield names;components.<c>.owns,link,sharedandrelease(reserved).homeanddevteam.registry-edit(constitutional) and the owner_only question classregistry-attest, and theentry_hashandprior_hashact fields.link-unreachable,link-behind-auth,unowned-files,line-empty,line-pressure.link:<id>.Review
Tests
node --test test/kit.test.mjs: 75 tests on Node 24.14.1 locally, including the perf bound (50k paths × 30 globs under 500 ms), credential non-leak, stale-main, act-matching and shell-quoting tests. CI runs 18/20/22/24.🤖 Generated with Claude Code