This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

Reported from a downstream repository using abcd, where `abcd capture` (bare,

issueresolvedmajoriss-2609120452071388

Reported from a downstream repository using abcd, where abcd capture (bare, the read-only status render) printed three "skipped … malformed frontmatter" lines for records abcd itself had written. The status board's counts then silently exclude records that exist, and nothing tells the reader whether the writer or the validator is the side that is wrong.

Two distinct causes, and the first is the serious one.

1. The slug generator produces a slug its own validator rejects

Reported record: iss-190, refused with

slug "guard-notebook-coverage-reads-notebooks-yml-as-one-flat-" is not kebab-case

The slug was truncated to its length budget mid-word, leaving a trailing hyphen. SlugRe (internal/core/issueschema/issueschema.go:150) is ^[a-z0-9]+(-[a-z0-9]+)*$, which refuses a trailing hyphen — correctly. The defect is that the generator can emit one: the truncation does not trim the separator it cuts against, so writer and validator disagree about what a legal slug is.

This is the sharpest shape of a record defect: the tool wrote a record its own gate refuses to read. It is the same class as resolveShipImpact's stated purpose — that abcd must not "produce, out of its own verbs alone, a record its own record-lint refuses" (iss-126) — arriving on a different path.

The failure is also silent in the direction that matters. The record is skipped rather than reported as a fault, so a ledger quietly under-counts and the only signal is a line the reader may not connect to the count.

2. source: autonomous-hunt is not in the accepted set

Reported records: iss-299, iss-300, iss-301, refused with invalid source "autonomous-hunt". They were written by an autonomous bug-hunt loop, so a value one abcd workflow writes is not one the schema accepts.

Sources (issueschema.go:140-144) is plan-review, impl-review, manual-test, review-followup, agent-finding, agent-observation, user-observation, drift-detection, memory-curation.

Corroborated independently in this repository on the same day. Capturing findings during the v0.8.0 release, --source release-followup and --category reliability were both refused, each on the first attempt, each plausible-sounding and neither in the list. The vocabulary is closed, which is right, but it is discoverable only by being refused: capture --help renders --source string surfacing channel (default user-observation) and names no member, and the same is true of --category.

So the refusal is correct and the surface around it is not. Two sessions independently guessed values that do not exist, which is evidence about the help text rather than about the guessers.

The peer session supplied the controlled comparison that turns this from a complaint into a diagnosis. In the same --help output, --severity names its four members inline and --source and --category name none. Their report: severity was right first time because it was named; the other two were right only by accident. Two sessions, three flags, and the one flag that documents its vocabulary is the one nobody got wrong.

That isolates the cause. It is not that the vocabularies are closed, and not that the values are unguessable — it is that two of the three do not say what they accept, while the third, in the same help text, does. Whatever is decided about autonomous-hunt, naming the members would have prevented both of the day's wrong guesses independently of it.

What is owed

  • Trim the separator when truncating a slug, so the generator cannot emit what SlugRe refuses. Then sweep: any other writer that truncates into a bounded filename has the same exposure.
  • Decide autonomous-hunt. Either the bug-hunt loop uses an existing member (agent-finding is the obvious fit) or the value joins Sources. This is a vocabulary decision, not a bug fix, and it belongs to the maintainer.
  • Name the members in --help for --source and --category, the way --severity already does ("severity: nitpick | minor | major | critical"). Two independent wrong guesses in one day is the measurement.
  • Say which layer is wrong when a record is skipped. A record that fails validation should report that it does, distinguishably from a record that is absent, rather than being dropped from a count with a line above it.

Acceptance

  • Given any text a caller captures, when the slug is derived and truncated, then the result satisfies SlugRe — no trailing or doubled separator — and a property test asserts this over adversarial inputs.
  • Given a record whose frontmatter the schema refuses, when the status board renders, then the count and the diagnostic agree about what was excluded and why.
  • Given capture --help, when a caller reads it, then the legal values for --source and --category are named inline, as --severity already names its four.

Grounds

  • pursued: a reader shown a skipped record can now tell whether the writer or the schema is wrong; a skipped record whose layer is empty, or a board whose header omits a skip it lists, would show it wrong

Frontmatter

idiss-2609120452071388
typeissue
lifecycleresolved
severitymajor

mentions8