v3.4.0 - the tracker enters the spine #172

Merged
john merged 19 commits from cadence/v3.4.0 into main 2026-08-15 17:00:53 +00:00
Owner

/cad-land step 1 now reads the issue tracker. It scans git log <base>..HEAD
for #N, closes #N and fixes #N and names each referenced issue with its
state ("your branch references #42 and #47; #42 is still open"). Reference
nothing and it lists the open issues instead, as the fallback rather than the
headline. It reads, it never writes: landing closes no issue.

The host comes off the origin URL the same way step 1 already picked the PR
mechanism: gh, glab, or tea for a host your tea login list names. All
nine paths that cannot answer print exactly one line and the land carries on. A
forge CLI that never returns is killed at 10 seconds. git.issue_check (bool,
default true) turns the whole thing off, and with it false no forge CLI is
spawned at all.

The blocking risk_surface review caught three real defects before close: a
forge CLI's stderr riding the envelope past a URL-only redactor, an off switch
that still printed a tracker line, and a control character in an origin
hostname breaking the one-line guarantee.

Known limits, both one-line degradations rather than wrong answers: tea
clamps a page at 50 server-side, so a repo with 50 or more issues reports the
truncation line, and a host with no matching tea login reads as unrecognized.

18 commits, manifest at 3.4.0. Closes #121.

`/cad-land` step 1 now reads the issue tracker. It scans `git log <base>..HEAD` for `#N`, `closes #N` and `fixes #N` and names each referenced issue with its state ("your branch references #42 and #47; #42 is still open"). Reference nothing and it lists the open issues instead, as the fallback rather than the headline. It reads, it never writes: landing closes no issue. The host comes off the origin URL the same way step 1 already picked the PR mechanism: `gh`, `glab`, or `tea` for a host your `tea login list` names. All nine paths that cannot answer print exactly one line and the land carries on. A forge CLI that never returns is killed at 10 seconds. `git.issue_check` (bool, default `true`) turns the whole thing off, and with it false no forge CLI is spawned at all. The blocking `risk_surface` review caught three real defects before close: a forge CLI's stderr riding the envelope past a URL-only redactor, an off switch that still printed a tracker line, and a control character in an origin hostname breaking the one-line guarantee. Known limits, both one-line degradations rather than wrong answers: `tea` clamps a page at 50 server-side, so a repo with 50 or more issues reports the truncation line, and a host with no matching `tea` login reads as unrecognized. 18 commits, manifest at `3.4.0`. Closes #121.
john added 19 commits 2026-08-15 16:59:44 +00:00
Scoped from Forgejo milestone v3.4.0, which holds one issue: #121.

LND-01 promoted out of REQUIREMENTS ## Deferred, where it sat from
2026-08-14 when it was cut from the v3.2.0 cycle before execution. Its
deferral reason survives as a planning constraint rather than a blocker:
glab is absent here, so the GitLab arm ships behind the same resolved-CLI
seam as gh and tea and is proven by a stubbed CLI path.

PROJECT ### Active carries the theme and the four hard constraints - one
line of degradation, never blocking a land, bounded against a hanging
forge CLI, never auto-closing an issue - plus the git.auto_close naming
trap the new git.issue_check key has to stay clear of.

Cursor reset to phase 1 of 0, ready to plan.
LND-01 / #121 as the milestone's single phase. Six criteria: the
referenced-issue report and its open/closed marking, the bare-list
fallback, one-line degradation on all five failure paths, a hard timeout
against a hanging forge CLI, git.issue_check kept clear of the
git.auto_close vocabulary, and the GitLab arm proven through a stubbed
glab path with registration landing alongside the code.

Cursor total re-derived to 1, next /cad-plan 1.
#171. At the default stakes level a plan had no second opinion of any
kind, and the two decisions that produced that each named the other as
the remaining net:

- e0b5448 cut shipped plan adjudicated -> advisory, reasoning "a plan at
  shipped has already passed cad-plan-checker, a blocking gate that
  forces a revision on any BLOCKER and is on by default"
- b20fd14 took the same cell advisory -> off
- 70007f7, one day later in the same cycle, flipped
  workflow.plan_check to default false, reasoning "the plan review
  trigger remains the default second opinion"

The checker was off because the review covered it; the review was off
because the checker covered it. Both shipped.

blocking rather than a return to advisory: CST-01 measured findings
files referenced by no SUMMARY and no CONTEXT, which condemns the
ADVISORY gate and not the review. A plan is the cheapest artifact in the
pipeline to halt on - no code exists yet, the payload is one file, the
fix is an edit rather than a revert - and blocking costs no user-triage
turn, which is what adjudicated buys at critical. workflow.plan_check
stays default false: one net, on, before code.

config.schema.json:27 stops claiming a second opinion that was not
running. solo (advisory) and critical (adjudicated) are untouched.
METHOD trigger table, its two prose statements, README:56,
review-triggers.md and plan.md step review all restated; the two
reference budgets re-pinned for the prose that moved.

Suite 1799/1799, self-verify problems [], tsc exit 0.
Six tasks, one plan, under the ceiling of 8: the git.issue_check key,
the pure issue-decision core, the bounded PATH-resolved issue-check
seam, the /cad-land step-1 wiring, the fault-injection matrix, and
registration on COMMANDS/README/DOCS-CLAIMS.

ROADMAP phase 1 gains the **Goal:**/**Depends on:**/**Requirements:**
lines plan-size reads - without them the phase measured
requirements_found:false and was never compared against the ceiling.

Adjudicated plan review (openai gpt-5.6-sol @ high): 7 raised, 5
survived and all five are folded in - the paging bound and an
unreadable-response reason so a truncated page cannot report a
referenced issue as not-found, the repo binding on the forge call
(cwd plus an explicit selector; tea does not infer a repo at all),
no-login as a reason distinct from unrecognized-host, an assertion
that the key off spawns no forge CLI, and git.issue_check named in the
/cad-help surface. One killed: a task-ordering finding that holds only
if task 3 ships the bug it is responsible for not shipping.

LND-01 seeded into REQUIREMENTS Traceability; cursor planned.
`git.issue_check` joins the all-keys prose fixture so check 1 stops
reporting it inert, and the check-12 callsite pins go 11 -> 12 over
8 -> 9 files now that issue-check.mjs merges config in arm (a).

Both are count pins that exist to force this choice; the product is
unchanged.
redactUrl covers a credential in URL position only, so a forge CLI's auth
diagnostic carrying a bare token (Authorization: Bearer, *_TOKEN=, glpat-)
reached detail intact on a path /cad-land prints. The reason line already
names the degradation, so the raw stderr is dropped rather than routed
through a second regex: the child's stderr is discarded at the spawn and
detail is null on every check arm.
With git.issue_check false the seam answered skip, and cad-land step 1
prints every skip reason verbatim, so the off switch still printed a
tracker line on every land. The off case is the user's instruction rather
than a degradation, so it gets its own action: decideIssueCheck answers
off, the seam passes the action through, and step 1 branches on it and
says nothing. Structural rather than a reason-string match in the caller,
which would make a rewording a regression.
splitOrigin's [^/:]+ classes admit newlines, ESC and DEL, and the hostname
is interpolated into the unrecognized and no-login reasons, so a hostile
origin URL breaks the exactly-ONE-line guarantee /cad-land step 1 makes.
The hostname is rejected rather than cleaned - no forge serves such a host,
and a stripped one would be printed back as if the user had configured it -
so the origin reads as unrecognized and degrades to its own single line.
docs: open v3.4.1 - what the config says is what routing does
All checks were successful
test / node-test (git, 22) (pull_request) Successful in 25s
test / node-test (git, 24) (pull_request) Successful in 27s
test / node-test (other, 22) (pull_request) Successful in 19s
test / node-test (other, 24) (pull_request) Successful in 18s
test / node-test (planning, 22) (pull_request) Successful in 1m9s
test / node-test (planning, 24) (pull_request) Successful in 1m6s
test / node-test (prose, 22) (pull_request) Successful in 25s
test / node-test (prose, 24) (pull_request) Successful in 27s
test / node-test (review, 22) (pull_request) Successful in 15s
test / node-test (review, 24) (pull_request) Successful in 15s
test / node-test (routing, 22) (pull_request) Successful in 29s
test / node-test (routing, 24) (pull_request) Successful in 25s
test / self-verify (pull_request) Successful in 15s
test / typecheck (pull_request) Successful in 18s
62d9ddba36
john merged commit 57000abf4c into main 2026-08-15 17:00:53 +00:00
Sign in to join this conversation.
No description provided.