Development record
abcd-s-presence-should-be-visible-in-the-host-harness-s-stat
Summary
spc-70 delivers itd-200: in an abcd-managed repository the host's status
line becomes abcd's own row, led by one badge in three states (managed and
nobody waiting, waiting on the facilitator, waiting on the product thinker),
followed by the repository name, the branch, the model, the context
percentage, the five-hour and seven-day usage percentages, and the record's
intent and issue counts. Outside a managed repository the user's previous
status line runs untouched. The state behind the badge is a stored mode with
two writers, the agent and the human, read by the status render and by the
bare /abcd board alike. Where the host has no status surface, one line at
the stop names whose answer is owed. ahoy install offers the line, explains
it, takes the element configuration, and writes the wiring only on consent.
Scope
- One render in core.
internal/core/statuslinecomposes the row from three inputs: the harness payload on stdin, the repository, and the record. It returns a structured row (ordered elements, each with a key, a rendered form and a plain form) that the CLI prints and the/abcdboard reuses for its one-line state. No front door invents words. - The mode store. The waiting-on state lives in the repository's local
tier,
.abcd/.work.local/mode, one line, one ofmanaged,facilitator,product-thinker. Per worktree, gitignored, absent meansmanaged. Only a managed repository has the tier, which is what keeps the state managed-only by construction. - Two writers, one verb.
abcd modeprints the state;abcd mode <state>sets it. The agent calls it when it stops for a verdict, naming the addressee; the human calls it to say which hat they wear. The plugin surface page documents both uses. Where the host has no status surface, the set form also prints the one-line notice naming whose answer is owed, once, because the verb call is the stop. - The status verb.
abcd statuslinereads the harness's JSON payload on stdin and prints the row. When the current directory is not a managed repository it runs the user's previous status command, recorded at install time, with the same stdin, and prints its output verbatim; when none was recorded it prints nothing. This is how one harness-wide setting yields abcd's line in managed repositories and the user's line everywhere else. - Elements after the badge, in the fixed order the intent names. Each is
on by default and switchable in the user-level setting. Payload-sourced
elements (model, context, five-hour, seven-day) render only when the field
is present; an absent field drops the element with no placeholder. The
branch is read from the repository. The counts are open issues and intents
not yet shipped (drafts plus planned), taken as FOLDER COUNTS: the files
named
iss-*.mdin the ledger'sopen/, and the files nameditd-*.mdin the intent store'sdrafts/plusplanned/, one directory listing each, nothing parsed. Folder membership is the record's own status signal, so this is the number the board's readers give except for a record those readers would skip as unreadable — and the harness runs the composition on every refresh, where the board's readers, which load and parse every record, measured 0.96 s over 20,001 open records. (Written as "the same readers the board uses"; changed 2026-09-15 on that measurement.) - The user-level setting.
~/.abcd/statusline.json: the off switch, the per-element switches, the presence badge's foreground and background, and the recorded previous status command. The defaults ship with the binary and are written on first install. A presence pair below the contrast bar is refused at read time with the measured ratio and the default renders. - Install-time wiring.
ahoy installon the first harness detects the harness's status-line setting, offers the line with a one-paragraph reason, takes the element switches, records the previous command, writes the user-level setting, and points the harness atabcd statusline. Declining writes nothing.ahoy uninstallrestores the recorded previous command. - The board. The bare
/abcdrender gains the same one-line state, from the same render, so a host with no status surface still answers on demand. - Contrast. The role badges' pairs are fixed constants held to the same bar; the presence pair is checked when the setting is read.
Approach
The render is pure: payload in, row out, no network, no writes. The only state it reads beyond its inputs is the mode file and the user-level setting. The status verb is the harness-facing shell around it; the board is the second consumer. Truncation safety comes from order alone: the badge is element one and every later element is optional, so a narrow host cuts from the right.
The previous-command fallback is what makes "managed repositories only" true under a single harness-wide setting. It is recorded once at install from the harness's own configuration, never guessed, and it is run with the same payload the harness supplied, so the user's line is unchanged in every repository abcd does not manage.
The mode verb is deliberately small: three states, a print form and a set form. The one-line notice on set is the whole of the no-status-surface fallback, and it fires once per set, never per prompt.
How the Acceptance Criteria are satisfied
- ac-1 (managed, nobody waiting). Mode absent or
managedrenders the presence badge first; the render places nothing before it. - ac-2, ac-3 (stop parked on the product thinker or facilitator). The
agent runs
abcd mode product-thinkerorabcd mode facilitator; the next render reads the file; the board reads the same file. - ac-4 (hat set by hand). The same verb, run by the human; the agent's next read of the mode returns it.
- ac-5 (unmanaged repository). No managed marker means the status verb runs the recorded previous command and prints nothing of its own; no setting is written.
- ac-6 (switched off). The off switch in the user-level setting makes the status verb behave as in ac-5 everywhere.
- ac-7 (no status surface). The set form of the mode verb prints one line naming the addressee; the board renders the state on demand.
- ac-8 (install asks). The
ahoy installstep: offer, reason, element switches, recorded previous command, wiring on consent, nothing on decline. - ac-9 (contrast bar). The setting reader computes the ratio of the configured pair; below the bar it refuses with the ratio and substitutes the default.
- ac-10 (truncation). Badge first; the test renders a row and asserts that every prefix of it still begins with the badge.
- ac-11 (full row). A payload fixture carrying every field renders the nine elements in the named order with one separator. (The count was written as twelve and the list it refers to names nine: badge, repository, branch, model, context, five-hour, seven-day, intent count, issue count. Corrected 2026-09-15 when the render was built against it.)
- ac-12 (absent field). The same fixture minus one field renders one element fewer and no placeholder.
Tests
- Render tests over payload fixtures: full row, each field absent, each element switched off, each mode state, unmanaged directory.
- Mode verb tests: print and set, invalid state refused, the one-line notice on set and its absence on print.
- Setting tests: defaults written on first install, off switch, contrast refusal with the measured ratio, previous command recorded and restored.
ahoy installtests on a fixture harness config: offer and decline write nothing; consent writes the setting and the wiring; uninstall restores.- Board test: the one-line state matches the render's plain form.
- Zero-network harness: the status and mode verbs make no request.
Out of scope
- Any second harness; guard health, peer sessions and other candidate elements; update-available signalling; the role-adapted communication path.
Frontmatter
| id | spc-70 |
|---|---|
| type | spec |
| lifecycle | closed |
.abcd/development/specs/closed/spc-70-abcd-s-presence-should-be-visible-in-the.md
open on GitHub ↗ · commit history ↗
References1
- itd-200A managed repository shows it is managed, and whose answer the loop is waiting on, in the host's status lineimplements
mentions5
- dcn-26091500000000082026-09-15 — itd-200 / spc-70 ship with five implementation rulings the spec left open, taken by the implementing session and reversible by the maintainer (recorded here so none is silent). (1) The status-line offer is its own consent category, `status-line`, advisory and never approved by `--yes`, exactly as the git-identity pin is: it rewrites a harness-wide user setting and takes element choices, so only an answered prompt writes it, and `yes |` answers it. A decline is never persisted; the offer returns on the next install until the user-level setting exists. (2) Harness detection is positive evidence only: the harness's user settings file exists and parses (its directory from `$CLAUDE_CONFIG_DIR`, else the harness home); no file means nothing offered and nothing written. Ownership of a status command is decided by shape (`<absolute entry with leaf abcd> statusline`), which is what makes a dangling entry decidable when the binary is gone. (3) The two record counts on the row are FOLDER counts (files named `iss-*.md` in the open ledger; `itd-*.md` in drafts plus planned), not the board's parsing readers, because the verb runs on every status refresh and a parse over a clone-controlled record measured 0.96 s at twenty thousand records; folder membership is the record's own status signal, so the number differs only where a parser would skip an unreadable record. The spec's Scope text is corrected to say so. (4) Two guards the reviews required and the spec did not name: the previous-command fallback refuses to run when its own marker is already in the environment and marks its child, so a recorded command that reaches `abcd statusline` in any spelling terminates instead of forking without bound, and the install refuses to record such a command at all; and every write to the harness settings re-reads the file immediately before the act and merges into the fresh document, refusing when the status-line key changed under the prompts (itd-193's rule applied to a user file a live harness also writes). (5) `abcd mode <state>` prints the owed-answer line only when the user-level setting is absent or disabled — the setting is the only evidence of a status surface abcd has — and `managed` prints nothing; the bare board renders the presence line even when the line is disabled, because the switch silences the line and the board is the fallback. Rejected: making the offer a config-change gap (one consent for the PATH entry and the status line would let the reason paragraph be skipped); counting through the board's readers with a cache (a second mechanism to keep correct for the cheapest surface in the tree). The fidelity audit rcp-636b39d5541a records five criteria met with concerns, all disclosed on the shipped record; the one the record could close is closed: the GRILL rule domain now tells an agent to set the mode before it stops for a verdict.
- iss-2609020734198139The v0.7.1 brief-surface crosscheck (Direction A, tier full, over the sixteen first surface chapters) found four false claims in the design record, none in a user-facing page. 01-ahoy.md line 225 says every non-SessionStart shim attempts hooks/bootstrap.sh when the plugin-root binary is missing; hooks.json wires bootstrap into UserPromptSubmit, SessionStart, PreToolUse and PreCompact but not SessionEnd, which resolves the plugin root, then a vouched PATH abcd, then fails loudly, so a machine with no plugin-root binary never stages its transcript at exit and the chapter says otherwise. 01-ahoy.md line 28 lists status among the sub-verbs that ship on the CLI; abcd ahoy status exits 2, status being a plugin-side alias for the bare render, and the chapter's own sub-verb table omits it. 07-memory.md line 3 disambiguates spc-38 and spc-39 by saying the store's ids stop well short of spc-38; the store now runs to spc-70 and both ids name unrelated specs, so a dozen bare references on the page point at the wrong records. 07-memory.md line 116 enumerates launch --dry-run's gates as five, omitting semantic-receipts, which 04-launch.md documents. Each is a one-line correction; the receipt for the v0.7.1 cut defers them to this record.
- iss-2609261536147903Planned intents and disciplines still cite specs of the retired predecessor store unqualified, and such an id at or below spc-70 resolves to a live spec on another subject (spc-12, for one, is live as the disembark grounding spec): itd-48, itd-50 and itd-53 name spc-12, spc-28, spc-29, spc-31, spc-33, spc-43 and spc-52 for the fidelity reviewer, lifecycle hook and cleanup work (which of these are predecessor ids is itself the reading this record owes); itd-24 names spc-66 as the phase-audit receipt; itd-1 and itd-37 name spc-12 as the manual reviewer. The specs charter (Two spc-N Namespaces) rules that every predecessor citation carries the '(predecessor store)' qualifier; iss-239 applied it to the draft corpus only. Each site needs a reading to tell a predecessor citation from a live one, which is why the sweep was not folded into iss-239.
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- iss-2610262036097307Draft itd-169 asks that a stopped agent loop say who it is asking; 26-mode already records whom the loop waits on in the badge's waiting-on state.