Skip to content

research(dn-decisions): R-phase DN-1 permission-boundary + DN-4 ship-vs-gate (best-practices + companion survey) - #262

Merged
artyhoo merged 3 commits into
stagingfrom
research/dn-decisions-best-practices
May 28, 2026
Merged

research(dn-decisions): R-phase DN-1 permission-boundary + DN-4 ship-vs-gate (best-practices + companion survey)#262
artyhoo merged 3 commits into
stagingfrom
research/dn-decisions-best-practices

Conversation

@artyhoo

@artyhoo artyhoo commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

R-phase research-patch backing two inline-recommendation classes that recurred in the meta-orch-no-arg-laziness umbrella (PR #261 follow-up) — moves them from session-recall to evidence-cited.

  • DN-1 (Class A) — allowed-tools scope for skill helpers: verdict Option CBash(bash ${CLAUDE_SKILL_DIR}/helpers/*.sh *) narrow glob, with ~/.claude/settings.json permissions.allow fallback while CC Issue #14956 (verified open) remains unresolved. Evidence: CC permissions docs (glob syntax confirmed), OMO per-command granularity ({ git: allow, rm: deny }), Cline deny-overrides-allow, NVIDIA/AWS/OWASP PoLP consensus. Two open implementation questions surface as DECISION-NEEDED-Q1/Q2 for the eventual I-phase.
  • DN-4 (Class B) — F.6 ship-vs-defer: verdict REVISE-TO-DEFER — defer F.6 entirely, aligned with maintainer's 2026-05-27 stance (NOT the earlier PR research(meta-orchestrator): no-arg-laziness R-phase — F.3 + F.6 verdict #261 PROVISIONAL-ship). Evidence: Superpowers «no speculative fixes» (94% PR rejection), OMO «direct implementation over premature abstraction», project's own dual-implementation-discipline.md §3 (~/.claude/skills/ = Internal tooling = CC-native default), and §1.5c probe showing \${umbrella:-} defensive bash in the existing skill already mitigates the functional gap.

Deliverable: docs/meta-factory/research-patches/2026-05-28-dn-decisions-best-practices.md (453 LOC + 1-line scope annotation).

Scope: R-phase research-patch only. No code changes; no skill / hook / rule modifications. F.3 and F.6 implementation decisions are out of scope regardless of this R-phase's DN-4 verdict — they trigger separate future umbrellas.

Method (compliance with .claude/rules/)

  • phase-research-coverage.md §1 — all 6 search items + §1.5 probes ran (6 DeepWiki queries, 6 WebSearches, 84-row SSOT sweep, CC primitive probes with safety-mandated cleanup, repo+PR history sweep).
  • recommendation-laziness-discipline.md §3 — every verdict in patch §4 cites file:line / URL / DeepWiki excerpt evidence from §1-§3.
  • build-first-reuse-default.md §3 — 5 of 6 layers applied (layer 1 = Prior-art trailer = inapplicable per CLAUDE.md Build-vs-reuse invariant: this is R-phase markdown, not a capability commit).
  • no-paid-llm-in-ci.md §1 — research via DeepWiki MCP + WebSearch + WebFetch + Bash; zero API-billed LLM calls.
  • parallel-subwave-isolation.md §1 — Worker executed in isolation: \"worktree\" ephemeral worktree.
  • ai-laziness-traps.md §3 — T1/T3/T4/T7/T11/T12/T13/T15/T16/T19/T20 + domain-specific T-N5/T-N6/T-N7 enumerated in kickoff; T15 self-application addressed in patch §6.

§1.7 Forward-check applied

This patch complies with existing disciplines:

  • phase-research-coverage.md §1 — 6-item checklist scaffold executed (patch §1.1-§1.6); see patch §6 forward-check.
  • doc-authority-hierarchy.md §3 — patch header carries Class C + Authoritative-for + NOT authoritative-for (patch lines 3-5).
  • recommendation-laziness-discipline.md §3 — every §4 verdict backed by ≥1 evidence-bearing tool result cited inline; e.g. DN-1 falsifier patch line 316, DN-4 evidence patch lines 331-336.
  • dual-implementation-discipline.md §3 — meta-orchestrator skill classified as Internal tooling = CC-native default; informs both DN-1 and DN-4 verdicts (patch §4 + §3 lines 282-284).
  • no-paid-llm-in-ci.md §1 — all research via free-tier tools (patch §6 forward-check, line 365).

§1.7 Backward-check applied

New verdicts applied to existing artefacts:

DECISION-NEEDED (4 items for maintainer)

Surfaced per reviewer-discipline.md §2 — these are picks for maintainer, not orchestrator/reviewer:

  1. Q1 — \${CLAUDE_SKILL_DIR} expansion in allowed-tools frontmatter: CC docs describe \${CLAUDE_SKILL_DIR} as a skill content substitution. Whether it expands in the frontmatter allowed-tools field is not confirmed by docs or probes. Determines exact Option C implementation form (\${CLAUDE_SKILL_DIR}/helpers/*.sh vs relative helpers/*.sh vs absolute path from settings.json). Patch §8 Q1 lines 411-415.
  2. Q2 — Is CC Issue #14956 fixed in current CC version? Confirmed open at v2.0.75; current CC version is higher. If fixed: skill-level allowed-tools alone suffices. If still open: ~/.claude/settings.json fallback required. Patch §8 Q2 lines 417-422.
  3. Q3 — Quote-accuracy confirmation: Russian-language maintainer quotes in patch §0 originate from 2026-05-27 dialogue (not transcribed in repo). Patch §0 provenance disclaimer + §8 Q3 lines 425-429. Confirm only if a quote is felt as load-bearing for verdict reversal.
  4. Q4 (advisory) — Explicit deny list? Whether to add explicit Bash(rm *) / Bash(curl *) deny rules in settings.json alongside the Option C allowlist (belt-and-suspenders). Patch §8 Q4 lines 431-436.

Out of scope (do NOT cascade out of this PR)

  • F.3 implementation umbrella (separate future umbrella per kickoff §3).
  • F.6 implementation regardless of DN-4 verdict (per kickoff §3 amended).
  • DN-2 (B sibling helper) and DN-3 (verbatim-in-commit-body) — already answered by maintainer 2026-05-27.
  • Editing any .claude/skills/, .claude/hooks/, settings.json, or rule files (R-phase boundary).

Test plan / verify-trace

  • Worker probes cleaned — tmp-glob-probe/ + tmp-arg-probe/ absent from commit; verified via git status --short + git diff --stat --cached pre-commit (Worker REPORT verify-trace).
  • Probe-safety mandate (Phase -1 B1 amend in kickoff §1.5) executed — no synthetic skill paths in staged changes.
  • §1.7 Forward + Backward present in patch §6 (lines 362-378) AND in this PR body above.
  • Issue #14956 existence verified independently — gh api repos/anthropics/claude-code/issues/14956 returned state: open, created_at: 2025-12-21, title matches Worker citation.
  • Branch research/dn-decisions-best-practices based on origin/staging @ fd93ed5; ahead of staging by 2 commits (initial research + principle-10 annotation fixup).
  • Principle 10 (research-patch scope annotation) passes — <!-- scope:dn-decisions-best-practices --> present on patch line 1 (fixup commit 9488731).
  • Pre-push hook full suite green (markdownlint + zizmor + all 21 principle tests).
  • Worker REPORT confidence = medium (3 companion + 3 industry citations on DN-1 direction; DN-4 backed by 2 companion + 1 project rule; medium-not-high due to Q1/Q2 open).
  • Phase -1 self-review executed (REVISE → 2 BLOCKER + 4 MAJOR amended → re-review GO with 1 NEW-MINOR applied → dispatch).
  • Maintainer answers Q1/Q2 (gates I-phase implementation; not a merge gate for this R-phase patch).
  • Maintainer confirms quote accuracy on Q3 if any verdict feels load-bearing (advisory only).

Phase -1 audit trail

Cold-reviewer dispatched on kickoff (1× Opus general-purpose subagent) before Worker dispatch. Findings + amendments:

  • BLOCKER B1 (probe cleanup + worktree isolation absent): added §1.5 «Probe safety mandate» blockquote with 5-bullet protocol (worktree-only, do-not-commit list, capture-then-cleanup, pre-commit guard, REPORT line).
  • BLOCKER B2 (DN-4 contradictory framing): added header «DN-4 framing reconciliation» blockquote separating (1) PR research(meta-orchestrator): no-arg-laziness R-phase — F.3 + F.6 verdict #261 landed verdict, (2) maintainer's subsequent stance, (3) this R-phase's research-back job.
  • MAJOR M1 (Option B missing from §5): added Option B to verdict criteria with explicit Phase -1 note.
  • MAJOR M2 (§1.5c motivation weaker than actual): restated as PROVISIONAL-gap verification.
  • MAJOR M3 (BFR §3 «6 layers» overclaim): noted layer 1 inapplicable to R-phase markdown output.
  • MAJOR M4 (quote provenance unstated): added header «Quote provenance disclaimer» blockquote.
  • Re-review NEW-MINOR (§3 wording prejudged defer): replaced «F.6 deferred per DN-4 final answer» with version that doesn't prejudge.
  • Verdict after amendments: GO.

artyhoo added 3 commits May 28, 2026 16:13
…undary + DN-4 ship-vs-gate

DN-1 verdict: Option C — Bash(bash helpers/*.sh *) glob pattern in allowed-tools, backed
by CC permissions docs (glob supported), OMO per-command granularity precedent, Cline
deny-override-allow pattern, and NVIDIA/AWS/OWASP least-privilege consensus. Critical caveat:
CC Issue #14956 (open bug: skill allowed-tools may not auto-approve) — settings.json fallback
required. Also surfaces DECISION-NEEDED on ${CLAUDE_SKILL_DIR} expansion in frontmatter fields.

DN-4 verdict: REVISE-TO-DEFER — defer F6 entirely, consistent with maintainer 2026-05-27 stance.
Backed by Superpowers (no speculative fixes), OMO (direct implementation over premature abstraction),
dual-implementation-discipline.md §3 (meta-orchestrator = Internal = CC-native only default), and
§1.5c finding that ${umbrella:-} defensive bash coding already mitigates the functional gap.

Prior-art: skipped — R-phase research-patch, not a capability commit (markdown only, no new dependency or new ≥80 LOC code file)
… --> annotation

Principle 10 (research-patch annotation invariant) requires every research patch
to carry <!-- scope:<slug> --> on its first line. Initial patch (bf95b60) shipped
without it; pre-push hook caught the gap.

Prior-art: skipped — fixup for principle-10 annotation; not a capability commit.
…IONAL + verbatim Issue #14956 body excerpt

Addresses Phase -1 cold-review verdict (1 BLOCKER + 1 MAJOR) on PR #262.

BLOCKER (#verdict-without-load-bearing-probe) — §1.5a verdict was claimed
`VERIFIED-SYNTAX-SUPPORTED` based on CC docs extrapolation + "SHOULD match"
pattern analysis, but the §1.5a kickoff mandate was a runtime probe (invoke
synthetic skill, capture verbatim classifier output: auto-approve/prompt/deny).
Probe setup was created but NEVER invoked through CC's slash-command interface.

Fix: downgraded verdict to `PROVISIONAL-SYNTAX-EXTRAPOLATED — probe-deferred-
to-I-phase-Stage-0`. Added explicit probe-execution-disclosure paragraph above
the verdict noting (a) what was actually done (setup), (b) what was extrapolated
(SHOULD match), (c) what was deferred (runtime classifier observation). Added
"MANDATORY I-phase Stage 0 task" — if probe contradicts SHOULD-match
extrapolation, fall back to Option A or A+settings-fallback.

MAJOR (#claim-without-verbatim) — Issue #14956 citation at §1.3 Search 6
was Worker's paraphrase/summary, not a verbatim body excerpt. Reviewer caught
that title + summary != actual issue text passage; kickoff §1.2 mandated
verbatim excerpts for cited sources.

Fix: replaced paraphrase with verbatim excerpt from issue body (Description +
Actual Behavior + Workaround paragraphs), explicitly marking the title as
title-verbatim. State verified via `gh api repos/anthropics/claude-code/issues/14956`
(state=open, 2026-05-28). Bug confirmed against CC v2.0.75 per original Worker context.

Net change: ~15 LOC across two edits. DN-1 final verdict (Option C narrow glob
+ settings.json fallback) UNCHANGED — only the claim-strength language is
corrected (overclaim → probe-deferred PROVISIONAL). DN-4 verdict unchanged.

Prior-art: skipped — markdown polish on a research-patch; no new capability;
per CLAUDE.md "Refactors, doc edits, test additions for existing capabilities … NOT capability commits."
@artyhoo
artyhoo merged commit a764099 into staging May 28, 2026
22 checks passed
artyhoo added a commit that referenced this pull request May 28, 2026
…delta-write-from-state helpers (DN-1..DN-4) (#263)

F.3 I-phase implementation per kickoff `.claude/orchestrator-prompts/meta-orch-f3-iphase/kickoff.md`. Closes the F.3 helper-collapse arc started by PR #261 (R-phase verdict) + PR #262 (DN-1..DN-4 best-practices research).

Changes:
- NEW `.claude/skills/meta-orchestrator/helpers/dispatch-from-state.sh` — emits dispatch state (winner_id, sub_wave_state) + head-120 kickoff body. Replaces the §3 inline `cat .../kickoff.md` block per DN-3 A.
- NEW `.claude/skills/meta-orchestrator/helpers/delta-write-from-state.sh` — sibling helper to `update-delta.sh`; writes the two arrays (`untracked_seen` + `closed_since_last`) in `_master-backlog-delta.json`. Replaces the §10 step 5b inline jq block per DN-2 B. Existing `update-delta.sh` UNCHANGED — preserves paired-negative test contract.
- NEW paired-negative tests: `packages/core/hooks/dispatch-from-state.test.ts` (6 cases) + `packages/core/hooks/delta-write-from-state.test.ts` (7 cases). All 13 pass.
- SKILL.md: added `Bash(bash \${CLAUDE_SKILL_DIR}/helpers/*.sh *)` to `allowed-tools` frontmatter (DN-1 Option C narrow glob). Added Issue #14956 caveat note in §0 — settings.json fallback is load-bearing while #14956 stays open. §3 launch-table now invokes `dispatch-from-state.sh`. §10 step 5b now invokes `delta-write-from-state.sh` then `update-delta.sh`. Added `<!-- @dual-pair: meta-orchestrator-dispatch-from-state -->` marker.
- wave-sequencing-plan.md §0: single-line row update — F.3 helper-collapse I-phase done (this PR) + R-phase refs #261/#262.

Stage 0 probe (DN-1 Option C):
Per kickoff §1 Stage 0, the runtime probe via synthetic `tmp-glob-probe/` skill could not be executed autonomously — `/glob-probe` slash-command requires user-input action not available from this session. Substituted with authoritative ruling via `claude-code-guide`: Issue #14956 confirmed OPEN as of 2026-05-27 (labels `bug` + `has repro` + `area:tools` + `area:security`); skill-scoped `allowed-tools` with specific `Bash(<pattern>)` patterns does NOT auto-approve matching commands in current CC version. Verdict matches kickoff §1 Stage 0 Decision-branch row 3: «Issue #14956 still bites in current CC version → settings.json fallback becomes load-bearing; document in SKILL.md header.» No `tmp-glob-probe/` artefacts created (probe done via authoritative ruling, no runtime invocation); zero traces in `git status --short`.

Stage 1d (settings.json fallback) — recipe-for-maintainer:
`.claude/settings.json` is in the project deny-list (`Edit(.claude/settings.json)` + `Write(.claude/settings.json)` at settings.json:56-57) — agent-uncommittable by design (per maintainer convention; agent preserves snapshot + hands recipe). Required entry to add manually to `permissions.allow`:

    "Bash(bash *helpers/*.sh *)"

Rationale: skill-agnostic fallback path for Issue #14956 — remove this line if/when #14956 closes.

### Removed §3 inline !shell block (was at SKILL.md:242-244)

\`\`\`bash
\`\`\`!
cat ".claude/orchestrator-prompts/\${umbrella:-}/kickoff.md" 2>/dev/null | head -120 || echo "MISSING kickoff"
\`\`\`
\`\`\`

Reason: superseded by `\${CLAUDE_SKILL_DIR}/helpers/dispatch-from-state.sh` per F.3 helper-collapse verdict (PR #261). The inline block was classifier-incompatible under no-arg mode (`\${umbrella:-}` substituted before §2 picks winner, so §3 always emitted "MISSING kickoff" in arg-mode and contributed nothing in no-arg mode). Helper reads winner-id from state-file populated by §2.

Test results:
- 13/13 new paired-negative tests pass (`packages/core/hooks/dispatch-from-state.test.ts` 6 cases + `packages/core/hooks/delta-write-from-state.test.ts` 7 cases).
- `packages/core/hooks/update-delta.test.ts` UNCHANGED, all 4 tests pass — DN-2 B contract preserved.
- `packages/core/principles/12-ai-laziness-traps.test.ts` passes (6/6) — §3 inline-block removal does not break principle 12.
- 1 pre-existing test failure on `hooks/pre-push.test.ts` (staging baseline, unrelated — references `s17.test.sh` + `hook-stub-completeness.test.sh` that do not exist in current `packages/core/audit-self/`; not introduced by this PR — verified via `git diff origin/staging -- packages/core/hooks/pre-push.test.ts` = zero diff).

Prior-art: PR #261 (F.3 R-phase verdict) + PR #262 (DN-1..DN-4 best-practices research-patch) — both already merged to staging.
artyhoo added a commit that referenced this pull request May 28, 2026
…nvocations + dup-detect empty-arg = --all (#266)

Stage 4 of the `meta-orch-no-arg-overview` umbrella. Two coupled wire-level
fixes that unblock the skill itself: P4-a closes the form-mismatch between
SKILL.md `!`-block helper invocations and the maintainer-side allow-list
shape, and P4-b removes the compound `||` chain that no single allow-rule
pattern matched.

(a) SKILL.md: rewrite 7 of 14 `!`-blocks from direct-path form
    `${CLAUDE_SKILL_DIR}/helpers/<file>.sh "$arg"`
    to bash-quoted form
    `bash "${CLAUDE_SKILL_DIR}/helpers/<file>.sh" "$arg"`.
    Scope = the 7 blocks that ARE direct-path helper invocations
    (lines 72, 104, 172, 180, 188, 239, 243). The other 7 blocks
    (`cat`/`git`/`gh`/`head`/`jq` at 56, 60, 64, 68, 162, 285, 360)
    are not direct-path helper invocations — the transformation rule
    does not apply, current form preserved. Semantics preserved: same
    helper, same args, same exit codes.

(b) dup-detect.sh: empty arg now silently falls through to the `--all`
    iteration (was: emit `Usage:` and exit 1). Lets the SKILL.md §2.5
    Step 2 invocation use a single allow-rule pattern instead of the
    compound `<arg> || --all` chain.

(c) packages/core/hooks/dup-detect-empty-arg.test.ts: paired-negative
    contract — empty-arg-equals-all (positive), explicit-all regression,
    valid-umbrella-name preserves named-path, missing-umbrella preserves
    the original `MISSING:` error path (not the old `Usage:`), absent
    prompts-dir handled gracefully. Pattern mirrors
    packages/core/hooks/delta-write-from-state.test.ts (F.3 sibling
    helpers PR #261).

The maintainer-side companion — the `.claude/settings.json` allow-rule
diff that complements the bash-quoted form — ships in the PR body as a
HEREDOC recipe per [[feedback_settings_json_agent_uncommittable]]:
the agent cannot Write/Edit `.claude/settings.json` (self-protected
deny entry). Maintainer applies the diff manually before the next
`/meta-orchestrator` invocation can succeed.

### §1.7 Forward-check applied

`build-first-reuse-default.md §3` — six-layer mechanism not required:
this is a wire-level rewrite of an existing helper (no new capability,
no new substrate). The paired-negative test pattern is ADAPTED from
SSOT #55 (Superpowers TDD-for-Skills, prior-art-evaluations.md#55) and
the helper-testing variant is established at
`packages/core/hooks/delta-write-from-state.test.ts:30-99` (F.3
helper-collapse PR #261, 2026-05-28). `no-paid-llm-in-ci.md §1` — all
work is session-bound; the new test is pure-bash spawnSync + vitest,
no API-billed call. `doc-authority-hierarchy.md` — SKILL.md
Authoritative-for header preserved; no goal-redefinition.
`parallel-subwave-isolation.md §1` — work executed in worktree
`/Users/art/code/rules-as-tests-aif-overview-s4/`, branch
`feat/meta-orch-no-arg-overview-s4`, not primary workdir.

### §1.7 Backward-check applied

No artefact silently superseded. SKILL.md frontmatter
`allowed-tools: Bash(bash ${CLAUDE_SKILL_DIR}/helpers/*.sh *)` already
covers the bash-quoted form — this commit makes the helper invocation
sites *use* that form rather than the direct-path form. SKILL.md §0
caveat about CC issue #14956 still applies — the maintainer-side
`.claude/settings.json` allow-rule is the load-bearing fallback per
DN-1 Option C (PR #262 §3). The compound `|| --all` chain at SKILL.md
§2.5 Step 2 line 172-174 collapses into a single invocation; the
collapsed form preserves all existing helper output paths (POTENTIAL_DUPE
/ MISSING / OK / `(no orchestrator-prompts dir)`). The named-path branch
in dup-detect.sh:74 is preserved verbatim — only the empty-arg edge
behaviour changes. Reference: kickoff §5 backward-check at
`.claude/orchestrator-prompts/meta-orch-no-arg-overview/kickoff.md:156`.

Prior-art: prior-art-evaluations.md#55 (Superpowers TDD-for-Skills, ADAPT — extends paired-negative discipline to helper testing; helper-testing variant established at packages/core/hooks/delta-write-from-state.test.ts shipped under F.3 helper-collapse PR #261).
artyhoo added a commit that referenced this pull request Aug 18, 2026
… (#1475)

* docs(pre-merge-carrier): S0 design spec + prior-art SSOT rows #259-#263

Design stage S0 of the pre-merge-carrier umbrella (kickoff merged as PR #1469).
Deliverables: (1) prior-art consult — SSOT rows #259 (git merge-tree, DEFER),
#260 (GitHub merge queue, REJECT), #261 (nektos/act, REJECT), #262 (jjq, DEFER),
#263 (timeliner pre-merge-local.sh, ADAPT) + #176 Last-reviewed touch;
(2) design spec with sections (a)-(g), measured four-lane interlock inventory,
both #1465 riders landing in build stage B1 (same change as the carrier ship,
per the ratified record), falsifiers carried verbatim; (3) three DECISION-NEEDED
forks (delivery depth, ancestor case, NOT-COVERED policy) left open.

Prior-art: prior-art-evaluations.md#259 #260 #261 #262 #263 (this commit IS the consult record; docs-only, no capability shipped)

* docs(pre-merge-carrier): T19 round-1 fixes — UI-preset lanes in §b/§a.4/§g, append-only SSOT restored

Cold review round 1 (REVISE) findings applied:
- MAJOR-1: three UI preset lanes (react-next/react-spa/react-native, delivered
  as consumer ci.yml via setup.d/40-configs.sh:399/414/437) added to the §b
  inventory (measured: 0-hit shared-resource grep; new interlocks = fixed TCP
  ports + playwright browsers), §a.4 derivation, §g B2 scope; population
  corrected to seven lanes.
- MAJOR-2: prior-art-evaluations.md restored to origin/staging content +
  clean append of rows #259-#263 and the #176 Last-reviewed touch (the
  whole-file prettier reformat mutated historical row #152 'en/*' -> 'en/_'
  and rewrote ~80 rows it never touched — reverted).
- MINOR-1/2/3: code-span spacing in new SSOT rows; VACUITY included in the
  §a.2 terminal-verdict enumeration (three shas + ledger on every outcome);
  Russian citation removed from §b.2 trap-5 row.
- Reviewer note (a): the part-1 landing-site choice (new probe script vs
  docs-only recipe) now stated explicitly in §d as a resolved design choice.

* docs(pre-merge-carrier): fix the react-next census claim (ls-blind negative)

Cold fidelity audit round 1 (GO) notes-lane MINOR: the spec said
packages/core/templates/react-next/ is EMPTY on the strength of a bare `ls`,
which hides dot-entries — `find … -type f` returns 2 (.storybook config).
The design conclusion is unchanged (the directory carries no CI template, and
the repo-wide census `find . -name 'github-actions-ci*.yml'` returns exactly
the 7 lanes §b inventories); only the measurement claim is corrected, and the
ls-blindness is named so a later reader does not repeat it.

Scope-neutral: no deliverable, constraint, or decomposition row changes.

---------

Co-authored-by: Test <test@example.com>
artyhoo added a commit that referenced this pull request Aug 18, 2026
…s-server lane) + both #1465 riders (#1479)

* feat(audit-self): opt-in pre-merge carrier (ts-server lane) + ci-available-probe

B1 of the pre-merge-carrier-build umbrella (#1466/#1465; spec
2026-08-18-pre-merge-carrier-design.md §a/§d).

pre-merge-local.sh — gates the MERGE RESULT, never the head (#1466 class):
throwaway worktree at $(git rev-parse --git-path getff/), git merge --no-ff
of base into head, npm ci + npm run validate on the result. Three-sha
report (head/base/merge) on every verdict; exit table 0 PASS / 1 FAIL /
2 CONFLICT (distinct outcome + GitHub-runs-nothing warning) / 3 CANNOT-RUN
(named) / 90 VACUITY (a declared gate that never reported — npm's per-gate
header line is the signal, not the command echo); F2: base already
contained -> proceed, merge = head, shas intact. NDJSON run ledger +
retained PASS logs live under --git-path getff/, outside the worktree.
Atomic mkdir lock (exit 75). Honest framing per §e: "LOCAL PRE-MERGE
PASS" (never "CI green"), NOT-COVERED list on every verdict, §e.4
copy-paste PR-body citation block. Bash 3.2-compatible.

ci-available-probe.sh — #1465 part 1: classifies GitHub CI state with the
Actions-quota third state. A CI waiter reading only red/green misreads a
DEAD CI (GitHub Free private repos share 2 000 Actions minutes/month per
ACCOUNT) as red: every first-party (app.id 15368) check fails ~2 s with
zero executed steps while third-party checks stay green. The probe detects
that signature -> "CI UNAVAILABLE" exit 4, distinct from RED, and fetches
the check-run annotation naming the true cause. gh absence degrades to a
named CANNOT-RUN (exit 3), never a hard dependency.

Delivery is file-landing only (W-3): no husky/validate/CI wiring rides
along — promotion to default-on is B3's trigger-gated decision.

Prior-art: prior-art-evaluations.md#263 (ADAPT — artyhoo/timeliner PR 229
reference: worktree+merge --no-ff+same-validate+vacuity control transfer;
the six timeliner interlocks re-derived per lane, not vendored — Turbo/
pnpm/Postgres absent from all seven shipped lanes).
Prior-art: prior-art-evaluations.md#259 (DEFER — git merge-tree lacks the
runnable checkout the lane gates need), #260 (REJECT — merge queue:
Enterprise-only + spends the same metered minutes), #261 (REJECT — act
simulates the merge, does not construct it; Docker dep), #262 (DEFER —
jjq owns the landing and is jj-only) — the S0 consult this build cites.

* test(audit-self): live-fire self-tests — arms 1-10 + probe P1/P2

B1 Task 3 (spec §a.6 + kickoff §3). T-PMC-D contract: every arm RUNS the
real carrier/probe against a seeded fixture repo and asserts OUTPUT + exit
code — nothing greps the scripts' source text.

Carrier arms: three-sha block asserted on EVERY arm (W-1/T-PMC-B); seeded
failing gate -> 1; seeded conflict -> 2 (+ the GitHub-runs-nothing warning
+ conflicted file named); vacuity -> 90 via a shim that skips a declared
gate while the aggregate exits 0 (the #1466 item-1 shape); PASS run
retains its log OUTSIDE the worktree and cleans the worktree up; F2
containment (base ancestor of head) proceeds with merge = head; real-merge
sharp edge — verified sha must differ from head sha when base advanced;
.nvmrc major mismatch -> 3 with the pin named; unresolvable base -> 64
with NO ledger line; held lock -> 75.

Probe arms: gh absent from PATH -> 3 named (invoked via /bin/bash under an
emptied PATH with only a git symlink); a gh shim (emitting post---jq
output) drives the four classifications: quota signature (zero steps,
sub-5s first-party failure + green third-party) -> 4 with the annotation's
cause named; real red with steps -> 1; all green -> 0; no check-runs -> 2
with the merge-conflict-state hint.

Fixtures are throwaway git repos with a zero-dep package-lock so npm ci
works offline; the npm-run-all2 shim loops gates via `npm run` so npm
prints the SAME per-gate report headers the production aggregate produces.

Prior-art: prior-art-evaluations.md#263 (ADAPT — live-fire self-tests for the carrier capability of commit 8d63f23; same SSOT row, arms re-derived per T-PMC-D, not a new capability)

* feat(install): deliver carrier scripts to all profiles + CI wiring + the two #1465 docs lines

B1 Tasks 4-7 (kickoff §2 B1 row + §3 delivery-mechanism constraint).

Delivery (F1 — ALL profiles, core included; the delivery is NOT
profile-gated): setup.d/40-configs.sh copy_safe + chmod_safe +x pairs for
pre-merge-local.sh and ci-available-probe.sh in the unconditional scripts
section; install.sh do_refresh "Scripts -> scripts/" pairs for both
(refresh_safe honours <dst>.override.md — Layer-3 escape preserved). W-3:
file-landing only — nothing wires the carrier into husky/validate/CI.

Enforcement wiring the new test files force (principle 41's population is
every tracked *.test.sh, allowlist empty): a step in the EXISTING
audit-self.yml mechanical job runs
packages/core/audit-self/pre-merge-local.test.sh; a literal
`run: bash tests/install-sh/pre-merge-local-delivery.test.sh` step in the
EXISTING install-sh-c job (meta-all-wired greps the literal); the
install-sh-c shellcheck step now also sweeps the two new shipped scripts,
making the shellcheck-clean constraint CI-enforced; a
run-local-ci-sweep.sh gate_table row (rank 5, trigger
packages/core/audit-self/) keeps the local sweep predicting CI
(sweep-coverage gate: the delivery-test step is battery-covered by the
install-sh-suite row; the shellcheck step is a multi-line run: block,
outside the single-line population).

tests/install-sh/pre-merge-local-delivery.test.sh — installs a fixture
consumer at `--profile core`, asserts BOTH scripts land executable and
byte-identical to the framework source, asserts W-3 negatively (no
package.json/husky wiring), then proves --refresh updates a stale planted
carrier copy (paired-negative control included).

The two #1465 part-2 docs lines: AI-USAGE-GUIDE.md §3 item 5 names
scripts/ci-available-probe.sh (+ the opt-in carrier) for the
quota-dead-CI state; INSTALL-FOR-AI.md gains the Actions-minutes fact
(2 000/month per account on GitHub Free private repos) + both script
pointers — 11 lines, 594/600 against the markdown wall.

Prior-art: skipped — delivery wiring, CI steps, docs lines, and a test for
the capability committed earlier (cited there as #263 ADAPT); no new
capability.

* chore(install): snapshot regen for carrier delivery

Deliberate baseline regen after the B1 shipped-file edits (kickoff §3):
every npm stack gains scripts/pre-merge-local.sh + scripts/
ci-available-probe.sh and the refreshed .ai-factory/AI-USAGE-GUIDE.md
hash; python lanes carry the guide-hash change only (the agent surface,
not 40-configs scripts/); cargo/go are untouched (toolchain artefacts
only). Diff reviewed — no unexpected drift.

Prior-art: skipped — snapshot regen after a delivery edit, no new
capability.

* fix(audit-self): shellcheck disables for SC1003/SC2329 false positives

The B1-widened CI shellcheck step (audit-self.yml, pinned-idiom 0.9.0 on the
runner) reds on pre-merge-local.sh: SC1003 (info) fires on the tr -d literal
set at the NDJSON ledger remote-sanitize line on every shellcheck version;
SC2329 fires on cleanup() from 0.10.0 up (trap-invoked, not dead). Both are
false positives — annotated with rationale, no behaviour change. Reproduced
red at v0.9.0 (exit 1) and green after (exit 0) on both v0.9.0 and v0.11.0.

Prior-art: skipped — two-line lint-annotation fix, no new capability

* chore(install): snapshot regen after shellcheck-annotation fix

Prior-art: skipped — snapshot regen after lint-annotation edit, no capability

* fix(ci): quote the B1 self-test step name — unquoted inner colon broke YAML

actionlint at pre-push (host harvest gate): audit-self.yml:99:70 'mapping
values are not allowed in this context' — the step name contains 'B1: live-fire',
and an unquoted scalar with an inner ': ' is invalid YAML, breaking the whole
workflow. The sibling install-sh step names added in the same change were
already quoted; this one was not. Verified: full-file js-yaml load now passes.

Prior-art: skipped — one-line YAML quoting fix, no new capability

---------

Co-authored-by: Test <test@example.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant