Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
paths:
- 'packages/**'
- 'plugins/**'
- '.llm/tools/quality/**'
- '.llm/tools/**'
- 'deno.json'
push:
branches: [main]
Expand All @@ -36,10 +36,11 @@ jobs:
- name: Scan changed source files
shell: bash
run: |
mapfile -t files < <(git diff --name-only --diff-filter=ACMR "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}" -- packages plugins)
changed_files=$(deno run --allow-run .llm/tools/quality/changed-source-files.ts "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}")
mapfile -t files <<< "$changed_files"
args=()
for file in "${files[@]}"; do args+=(--changed-file "$file"); done
if ((${#args[@]})); then deno task quality:scan --pretty "${args[@]}"; fi
deno task quality:scan --pretty "${args[@]}"
- run: deno task arch:check
- name: Lint changed publish surfaces
run: |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Context pack: PR-B #1403

## Current state

- Draft PR #1570 is open from bootstrap commit `059576fcd`.
- The formal quality-rail plan revision 4 passed PLAN-EVAL cycle 5.
- RED-first fixtures cover B1 and B3 and currently fail because both planned contracts are absent.
- B1/B3 implementations make the focused fixtures green. B2 exposes the passed-plan contradiction
recorded as `drift.md` D-1: the final 36 roots contain 54 known A14 failures while this slice is
forbidden to change A14 and is required to keep `arch:check` green.

## Locked implementation

- Discover exactly the 36 top-level package/plugin units; never use every workspace member.
- `packages/cli/e2e` is nested and excluded, with the reason written into doctrine.
- `arch:check` consumes discovery in the same change that removes the curated task list.
- The PR selector includes `packages`, `plugins`, and `.llm/tools`, reports empty explicitly, and
diffs `BASE...HEAD`.
- Findings are triaged only; package/plugin source is out of scope.
- `triage.md` records 1 actionable `plugin-streams-core` doctrine warning plus a 2-entry temporary
#1549 allowance register for changed-tool comment false positives. The focused package quality
scan is green with zero findings and zero allowances.

## Orchestrator decisions applied

- R-5 moved into PR-B. A14 is lexical-origin-aware and retains a synthetic unresolved RED case.
- The two tool-comment false positives now have reversible #1549 per-line allowances; current
triage is 1 actionable package finding plus a 2-entry temporary allowance register.
- Final wrapper roots are the owned `.llm/tools/quality` and `.llm/tools/fitness` trees.

## Next

Commit and push the resolved B1–B3 implementation with generated assets, rerun the final-head
idempotence/status check, and update draft PR #1570. The orchestrator then re-syncs against main and
owns the ready transition plus separate-session IMPL-EVAL.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Drift: PR-B #1403

Append-only. No drift from the passed plan at bootstrap or RED-first fixture time.

## D-1 — significant: final 36-root selector conflicts with required green `arch:check`

After implementing the locked R-6 transition, `deno task arch:check` exits **1**. Discovery reaches
all 36 intended roots, but 54 pre-existing A14 findings become blocking: 52 under `packages/cli`,
one under `packages/database`, and one under `packages/mcp`. This is the same known population the
passed plan records inside the baseline `arch:check:repo` result (55 total = 54 A14 + root-level
A1).

The brief simultaneously requires the final 36-root selector, requires `arch:check` to remain exit
0, forbids changing A14 (PR-C #1380 owns it), and forbids fixing surfaced findings. Those conditions
cannot all hold. No suppression or source fix was applied. B1/B3 continue; B2's final gate is
escalated to the orchestrator.

## D-2 — minor: mandatory root formatter has unrelated pre-existing red

The exact scoped check and lint wrappers over `.llm/tools --ext ts` pass. After formatting every
PR-B-owned TypeScript file, the exact format wrapper still exits **1** solely for the pre-existing,
out-of-scope `.llm/tools/harness/extract-verdict.ts`. PR-B boundaries allow changes only under the
fitness and quality tool subtrees, so this slice does not edit that file. A focused format check of
all owned TypeScript is green; the root-wrapper residue is escalated rather than folded into this
PR.

## D-3 — significant: repaired PR scan truthfully reds on two pre-existing comment false positives

The exact workflow-equivalent changed-file scan at `ca52c3a8f` executes and exits **1** on
`.llm/tools/fitness/check-doctrine.ts:169` and `:237`. Both lines contain the English word “any” in
comments; neither is TypeScript `any`. They predate PR-B's semantic changes but become visible
because the repaired gate scans the changed tool file. C6 forbids fixing surfaced findings here,
and the boundaries forbid allowance comments, so both are recorded in `triage.md` without a fix.
This is evidence that C4 is no longer silently green, but it also prevents the workflow job from
being green at this head.

## D-4 — orchestrator resolution: R-5 moves from PR-C to PR-B

The orchestrator confirmed D-1 was a plan-ordering defect. The 36-root transition and A14
origin-awareness are a matched pair, so R-5 now lands in PR-B. `resolveIdentifierOrigin()` performs
lexical import and local-binding collection and returns `imported | locally-bound | unresolved`;
A14 fires only on `unresolved`. One test exercises all three origins through the actual CLI, with a
synthetic unresolved fixture that exits 1. `deno task arch:check` now exits 0 across all 36 roots.
#1380 remains open; its box 5 implementation is provided here for PR-C to cite and tick.

## D-5 — orchestrator resolution: temporary #1549 allowances

D-3's two comment false positives receive exactly two per-line `quality-allow:` comments. Each
reason says the scanner matched an English comment word rather than TypeScript `any` and routes the
durable comment-awareness fix to #1549. The PR-owned repo scan allowance count rises **8 → 10**;
both additions are designed to be deleted by #1549.

## D-6 — orchestrator correction: wrapper scope is the owned tool trees

The brief's `.llm/tools` wrapper root was too broad. Final wrapper evidence uses only
`.llm/tools/quality` and `.llm/tools/fitness`; the pre-existing unformatted
`.llm/tools/harness/extract-verdict.ts` remains untouched and outside PR-B.
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
use harness

# PR-B — #1403: make `quality:gate` informative, in all three of the ways it currently is not

You are the **implementation agent** for the p0 of the 0.0.6 internals quality rail. The plan passed a
formal PLAN-EVAL (cycle 5, `PASS`); your job is to implement it, not to redesign it.

Your orchestrator is a Claude Opus 5 high session in `/home/codex/repos/netscript-006-internals`. It holds
merge authority and owns the draft → ready flip.

## SKILL

- `netscript-harness` — run artifacts, slice discipline, commit trail.
- `netscript-doctrine` — `arch:check`'s role, archetypes, fitness gates. **Read before touching
`check-doctrine.ts`.**
- `netscript-tools` — scoped wrappers; what is a verdict and what is not.
- `netscript-pr` — branch/PR/label mechanics, closing keywords, the fenced `acceptance-evidence` block.
- `rtk` — prefix read-heavy `git`/`gh`/`grep`.

## Identity

| Field | Value |
| --- | --- |
| Worktree | `/home/codex/repos/ns006-qualitygate` |
| Branch | `fix/1403-quality-gate-coverage` |
| Base | `3c9dc1f39` (= `origin/main`) |
| Slice dir | `.llm/runs/release-0.0.6-internals--orchestration/slices/pr-b-1403/` |
| Closes | #1403 |
| Route | Codex · gpt-5.6-sol · **low** |
| Plan | `plan-quality-rail.md` revision 4 (`PASS`), slices **B1–B3** in `worklog.md` § Design |

Measured at your base: `deno task arch:check` exit **0**, `deno task quality:scan:repo` exit **0**.
Both green, so any red you produce is yours.

## What is actually wrong — three independent defects, one gate

#1403 was filed about **root lists**. Cross-lane work then found two more, and all three are now acceptance
boxes. A fix for one alone leaves a gate that looks covered and is not — which is the class this issue exists
to close, so do not stop at the first.

### Defect 1 — the curated root list omits a package

`deno.json`'s `arch:check` is `deps:check` plus **16** hand-listed `check-doctrine.ts --root` invocations in
one shell string. `packages/plugin-streams-core` is the only `plugin-*-core` package absent — an omission,
not a decision.

### Defect 2 — the PR gate never scans `.llm/tools/**`, and skips entirely when nothing else changed

`.github/workflows/code-quality.yml:36-42`:

```bash
mapfile -t files < <(git diff --name-only --diff-filter=ACMR "$BASE" "$SHA" -- packages plugins)
args=(); for file in "${files[@]}"; do args+=(--changed-file "$file"); done
if ((${#args[@]})); then deno task quality:scan --pretty "${args[@]}"; fi
```

The pathspec is `-- packages plugins`, so a `.llm/tools/**` change can never enter the set; and
`if ((${#args[@]}))` means an empty set runs **no command** and reports success. Every PR in this rail —
including this one — is `.llm/tools`-only, so that step has been reporting success having executed nothing.

### Defect 3 — the range is two-dot, so a stale base scans other lanes' merged work

Same line: the two SHAs are passed as separate arguments, which is two-dot semantics — a literal tree
comparison. On PR #1539 that enumerated **nine** already-merged files belonging to other PRs and **zero**
lines of the PR under review. Audited across `main`, this is the **only** affected site:

```text
surface-diff.yml:54 "$BASE_SHA...$HEAD_SHA" three-dot — safe
ci.yml:142 "$BASE_SHA...$HEAD_SHA" three-dot — safe
e2e-cli.yml:140 "$BASE_SHA...$HEAD_SHA" three-dot — safe
code-quality.yml:39 "$BASE" "$SHA" TWO-DOT — fix this one
```

`A...B` diffs from the **merge-base**, so a stale base self-heals — it is always a former `main` commit and
therefore an ancestor. Demonstrated on identical inputs: `cd24e1679 2a4102600` → 9 files;
`cd24e1679...2a4102600` → 0 files.

**#1564** owns this root cause across consumers. **You fix only `code-quality.yml:39`.** Do not touch the
three safe sites; do not widen into #1564.

## Contract

### C1 — one transition to discovered roots, not two (rail `R-6`)

Introduce `discoverDoctrineRoots()` in `.llm/tools/fitness/check-doctrine.ts` returning the **final** root
set, and repoint `arch:check` at it **in one step**. No interim list, no checked-in root data file. Two
earlier PLAN-EVAL cycles rejected a two-step version; do not reintroduce it.

### C2 — the selector is the 36 top-level units, not every workspace member (rail `R-4`)

Expanded top-level `packages/*` + `plugins/*` — **30 + 6 = 36**. Root `deno.json`'s workspace list also
includes `packages/cli/e2e`, `examples/*` and `apps/*`; those are **not** doctrine roots.
`packages/cli/e2e` is **excluded**, and that exclusion must be **stated in the doctrine document**, not left
implicit in code.

### C3 — the coverage test must not ask the implementation what to expect

Derive the expected set **independently** — enumerate publishable units from the filesystem or the workspace
list — then assert `discoverDoctrineRoots()` equals it. A test that computes its expectation *by calling the
function under test* cannot fail; PLAN-EVAL cycle 3 caught exactly that and it is a blocking defect here.

### C4 — the PR gate must execute on a `.llm/tools`-only diff

Widen the changed-file computation so `.llm/tools/**` is in scope, and make the **empty set** fail closed or
report "not scanned" explicitly — never silently green. Prove both red-first.

### C5 — the range becomes three-dot

One character at `code-quality.yml:39`, plus a fixture proving a stale recorded base no longer admits foreign
already-merged files.

### C6 — surfaced findings are triaged, never fixed here (rail `R-8`)

Running the repaired gate over newly covered surfaces will surface real findings. **Do not fix any of them.**
Write them into a triage list in your slice dir with file, line, rule, and a one-line assessment, and say
plainly how many there are. #1403 box 5 requires exactly this; a diff that "helpfully" cleans them up fails
the slice. If a finding is severe enough that you think it must be fixed now, say so and stop — the
orchestrator decides.

## Acceptance mapping

#1403 has **8** boxes (5 original + 3 added today; read them from the live issue). Provide a fenced
`acceptance-evidence` block using **`box-index: 1..8`** — **not** exact box text. `acceptanceCheckboxes`
keeps only each checkbox's **first raw line, backticks preserved**, so any box that wraps is unmatchable by
exact text and you cannot see the wrapping. This cost PR #1560 a full failed IMPL-EVAL cycle earlier today.

## Gates — deliverables, not a checklist. Paste real output with exit codes.

| # | Gate | Command |
| --- | --- | --- |
| 1 | fitness + quality tests | `deno test --allow-read --allow-env --allow-write --allow-run .llm/tools/fitness/ .llm/tools/quality/` |
| 2 | doctrine (curated) | `deno task arch:check` — must stay **exit 0** |
| 3 | quality gate | `deno task quality:gate` — exit 0 |
| 4 | repo quality scan | `deno task quality:scan:repo` — must stay **exit 0** (it is green at your base; PR-E fixed it) |
| 5 | scoped check / lint / fmt | `.llm/tools/run-deno-{check,lint,fmt}.ts --root .llm/tools --ext ts` |
| 6 | **asset-barrel freshness** | `deno task gen:assets-barrel`, then `git status --porcelain` **must be empty** |
| 7 | new-workflow sanity | confirm `code-quality.yml` still parses |

Gate 6 is mandatory and non-obvious: tool sources are embedded as strings in
`packages/cli/src/kernel/assets/*.generated.ts`, so editing a bundled tool makes them stale and reds
`ci.yml`'s `quality` job. This cost PR-E a CI cycle. The empty `git status` on a **second** run is also your
idempotence proof.

Run **all** gates before you report done, so the head is final when the orchestrator flips to ready — that
flip triggers the formal IMPL-EVAL, and a commit landing after it invalidates the verdict.

## PR mechanics

1. First commit is the slice-dir bootstrap; open the **draft PR** in that same session, comment per slice.
2. Slice artifacts (`worklog.md`, `context-pack.md`, `drift.md`) updated in the **same commit** as the code
they describe.
3. `## Scope` carries `Closes #1403` on its own line. Reference `#1564` **without** a closing keyword — it
owns the shared root cause and stays open.
4. Labels: `type:fix`, `area:tooling`, `area:packages`, `priority:p0`, `status:impl`, milestone `0.0.6`.
Exactly one `status:`.
5. **Leave the PR draft.** The flip is the orchestrator's action.
6. **State gate claims as evidence, not buckets.** If a scaffold tier reports SUCCESS, say which step number
ran and whether step 2 was "Skipped by policy" — `scaffold-runtime: SUCCESS` is not a provable claim.
Likewise do **not** cite `quality:gate` as coverage of your own diff; on a `.llm/tools` change it is
precisely the defect you are fixing.
7. Resolve commit hashes in a separate shell step and paste literal values.

## Boundaries

- Touch only `.llm/tools/fitness/**`, `.llm/tools/quality/**`, `deno.json` tasks,
`.github/workflows/code-quality.yml`, `docs/architecture/doctrine/` for the C2 exclusion statement, and
your slice dir.
- Do **not** change `arch:check:repo`'s behaviour, the A14 rule, or the doctrine verdict table — that is
PR-C (#1380), which consumes your `discoverDoctrineRoots()` unchanged.
- Do **not** add export-awareness, allowance issue-links, `--max-allow` wiring, or docs-fence scanning —
that is PR-D (#1549).
- Do **not** touch `surface-diff.yml`, `ci.yml` or `e2e-cli.yml`; all three are already three-dot.
- Do **not** fix findings the repaired gate surfaces (C6).
- Do **not** add `deno-lint-ignore`, `@ts-ignore`, `as any`, `as unknown as`, or `quality-allow:`.
- Do **not** merge, flip to ready, or apply `status:ready-merge` / `status:impl-eval` / `impl-eval:skip`.

## Escalate instead of going idle

If a gate is red and you cannot green it, or a contract here is wrong, write it in your slice `drift.md`,
post it as a PR comment, and continue with what is not blocked. On this lane escalation has three times found
the orchestrator's brief wrong rather than the code — missing `--allow-write`, then `--allow-run`, then the
asset-barrel gate. Raising it is the expected behaviour, not a failure.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Newly surfaced findings triage

The repaired scans leave **1 actionable finding** in `packages/plugin-streams-core`. Two additional
scanner reports in the changed tool file were classified as comment false positives and carry
temporary, per-line allowances linked to #1549. No package finding is fixed in PR-B.

| File | Line | Rule | Assessment |
| --- | ---: | --- | --- |
| `packages/plugin-streams-core/src/application/durable-stream-producer-supervisor.ts` | 501 | `A8/AP-1/F-1` | The file is 515 lines, crossing the doctrine's 500-line warning threshold. This is pre-existing decomposition debt and should be handled in a package-owned follow-up, not in the gate-coverage PR. |

Focused quality scan evidence:

```text
deno task quality:scan --pretty --root packages/plugin-streams-core
exit 0; findings=0; allowCount=0
```

Focused doctrine evidence reports the one warning above and one informational A9 reminder that the
package has no `docs/architecture.md`. The A9 record is informational rather than a finding, so it
is not counted in the triage total.

## Temporary allowance register

| File | Line | Rule | Assessment |
| --- | ---: | --- | --- |
| `.llm/tools/fitness/check-doctrine.ts` | 210 | `explicit-any` | The scanner matches the English word “any” in an existing comment (`any export abstract class`), not a TypeScript `any`. A per-line allowance names #1549; delete it when that issue adds comment-awareness. |
| `.llm/tools/fitness/check-doctrine.ts` | 278 | `explicit-any` | The scanner matches the English word “any” in an existing heuristic comment (`any class chain`), not a TypeScript `any`. The same reversible #1549 allowance applies. |

The committed pre-allowance changed-file run at `b64550722` exited 1 on these two lines. That is the
red-first proof that a `.llm/tools`-only PR now executes and reports; before PR-B the workflow ran no
command and returned success. The final scan is green with two reported allowances.
Loading
Loading