diff --git a/.agent/memory/active/napkin.md b/.agent/memory/active/napkin.md index 32ad6e2..f21a54e 100644 --- a/.agent/memory/active/napkin.md +++ b/.agent/memory/active/napkin.md @@ -1,5 +1,36 @@ # Napkin +## Session: 2026-06-18 (later still) — Tier 1b F3/F8/F5/F7 landed, F6 deferred + +### What Was Done + +- **F3** (#31): coverage `fail_under` 70→85 + `audit_coverage_contract`. +- **F8** (#33): WCAG 2.2 AA chart — darkened the amber bar, white-haloed the + target marker, alt-text sidecar. Five PRs merged green this session (28/31/32/ + 33/34), each through CI + CodeQL + SonarCloud. +- **F5/F7** (#34): remote 10 MiB streaming size-cap (in a connection-closing + `with`) + `docs/using-this-template.md` rename guide. + +### Surprises & corrections (critically assess) + +- **A failing accessibility check can reveal an *existing* bug, not just the new + requirement.** The dark target marker (`#374151`) already failed 3:1 on most + bars — invisible on blue/teal/red/purple — before F8. Computing the contrasts + honestly (independent WCAG helper in the test) surfaced it. +- **Don't trust a thread-hint's framing of a security change — verify intent.** + F6's "fail-closed on `$(`/backticks" reads as a blanket deny, but that would + break legitimate command substitution *including this agent's own + `git commit -m "$(cat < --squash --delete-branch` once green (CI + - SonarCloud); the bot-opened release PR #25 needs `--auto` (it sits UNSTABLE). +- **Tier 1b F6 — `agent_hooks.py` guardrail hardening (DEFERRED).** Get owner + intent on the "fail-closed on `$(`/backticks" semantics first (blanket-deny vs + recurse-and-check), then implement in a dedicated session. The full analysis, + the two bypasses it closes, the recommended safe design, and the mandatory + pre-verification (run the edited hook against a heredoc commit → must ALLOW) + are in the gate-expansion thread's Remaining Work entry. Then Tier 3 (branch + coverage, Hypothesis, version-policy ADR), Tier 2 (governance checklist). + Finally **merge release PR #25 with `--auto`** (bot PR, sits UNSTABLE) to cut + the accumulated release. Normal feature PRs merge with + `gh pr merge --squash --delete-branch` once green (CI + SonarCloud). Authoritative detail in the gate-expansion thread record. ## Open Side-Tasks diff --git a/.agent/memory/operational/threads/quality-gate-surface-expansion.next-session.md b/.agent/memory/operational/threads/quality-gate-surface-expansion.next-session.md index 52b7aec..53895ca 100644 --- a/.agent/memory/operational/threads/quality-gate-surface-expansion.next-session.md +++ b/.agent/memory/operational/threads/quality-gate-surface-expansion.next-session.md @@ -66,6 +66,9 @@ All merged to `main` unless noted. `main` is green. `audit_coverage_contract` repo_audit check (floor + omit-list guard — guards what the coverage gate structurally cannot). Normal feature PRs merge with `gh pr merge --squash --delete-branch` once green (CI + SonarCloud). +- **Accessible-chart PR #33 — MERGED** (Tier 1b F8, WCAG 2.2 AA). +- **Adoptability PR #34 — MERGED** (Tier 1b F5 remote size cap + F7 rename + guide). **F6 (the agent_hooks guardrail) is DEFERRED** — see Remaining Work. - **Packaging-schema fix folded into PR #28** (committed `f5225cb`), separate from supply-chain: `pyproject` `[tool.hatch.build.targets.wheel].sources` `["src"]` → `{ "src" = "" }` (array tripped the *Even Better TOML* SchemaStore Hatch @@ -96,13 +99,36 @@ All merged to `main` unless noted. `main` is green. `audit_coverage_contract` (floor + omit-list guard). The audit asserts a *floor* (>=85, raising allowed) and that `omit` stays a subset of the justified set — guarding what the coverage gate structurally cannot. - - **F8 accessible chart — NEXT** (org WCAG 2.2 AA mandate, currently unmet): write a - text alternative from `render_summary` (SC 1.1.1); darken `#d08d46` and halo - the target marker for ≥3:1 contrast (SC 1.4.11); test the sidecar + contrasts. - - **F5/F6/F7 adoptability**: remote-fetch size cap + trust-boundary note; - guardrail fail-closed + simplify in `agent_hooks.py` (treat `|` as separator, - fail-closed on `$(`/backticks; allow-path tests for git commit/push/status); - a "rename this template" guide. + - **F8 accessible chart — DONE (PR #33).** Darkened the amber bar + `#d08d46`→`#b07a37` (2.77→3.69:1), added a white halo to the target marker + (it failed 3:1 on most bars), and a `.png.txt` alt-text sidecar from + `render_chart_alt_text`. Tests pin the WCAG contrasts with an independent + contrast helper. (Discovery: the dark target marker was an *existing* a11y + bug — invisible on blue/teal/red/purple bars.) + - **F5 remote size cap — DONE (PR #34).** `default_remote_reader` streams under + a 10 MiB `REMOTE_MAX_BYTES` cap (declared-Content-Length early reject + decoded + streaming cap), inside a `with` so the connection closes on every exit. + - **F7 rename guide — DONE (PR #34).** `docs/using-this-template.md`, linked + from the README. + - **F6 guardrail hardening — DEFERRED (needs owner input + a dedicated + session).** Goal: close two bypasses in the self-imposed safety rail + (`tools/agent_hooks.py`): (a) `_shell_segments` (line ~484) does NOT split on + `|`, so a piped stage isn't analysed as its own segment; (b) the anchored + force-push/etc. regexes are defeated by `$(...)`/backticks — e.g. + `echo $(git push --force)` slips through because the trailing `)` breaks the + `(\s|$)` anchor. **Why deferred:** "fail-closed on `$(`/backticks" is + ambiguous and, taken as a *blanket deny*, would break legitimate command + substitution — including the agent's own `git commit -m "$(cat <<'EOF' …)"` + heredoc pattern — and the hook runs on the working-tree copy, so a bad edit + self-locks the agent out of committing the fix. **Recommended safe design:** + add `|` to the `_shell_segments` separator set (safe; `||` stays distinct), + and *recurse into* `$(...)`/backtick substitutions to check the inner command + for blocked patterns (mirroring the existing `_shell_launcher_command` + recursion) rather than blanket-denying. **Before relying on any edit, run the + modified hook directly against (i) a heredoc `git commit` → must ALLOW, + (ii) `echo $(git push --force)` → must DENY, (iii) `git status` → ALLOW.** + Owner to confirm whether they want strict blanket-deny (and accept simple + `-m` messages for git commit/push) or the recurse-and-check interpretation. - **Tier 3 — Pythonic additions**: - branch coverage (`--cov-branch`) + raise threshold; - Hypothesis property-based tests for the CSV/data boundary; @@ -159,9 +185,13 @@ All merged to `main` unless noted. `main` is green. ## Next Safe Step -1. **#28 (supply-chain) and #31 (F3 coverage) are MERGED; `main` is green.** - Resume at **Tier 1b F8** (WCAG 2.2 AA accessible chart) — its own branch + PR. -2. Then F5/6/7, then Tier 3, then the Tier 2 checklist. +1. **#28, #31, #33, #34 are MERGED; `main` is green. Tier 1b is done except F6.** + Resume at **Tier 1b F6** (the deferred `agent_hooks.py` guardrail hardening — + read its full entry under Remaining Program Work; get owner intent on the + fail-closed semantics first, and pre-verify the modified hook allows a heredoc + commit before relying on it). +2. Then Tier 3 (branch coverage, Hypothesis, version-policy ADR), then the + Tier 2 governance checklist. 3. When the sprint's PRs are all merged, **merge release PR #25 with `--auto`** to cut the accumulated release, then verify the new GitHub Release + the bumped `main` version. diff --git a/.agent/plans/runtime-infrastructure/current/template-fitness-remediation.md b/.agent/plans/runtime-infrastructure/current/template-fitness-remediation.md index d111519..2fdad6d 100644 --- a/.agent/plans/runtime-infrastructure/current/template-fitness-remediation.md +++ b/.agent/plans/runtime-infrastructure/current/template-fitness-remediation.md @@ -9,16 +9,19 @@ todos: content: "F2 — make the CSV boundary robust to pandas NA/dtype sniffing, with negative tests." status: completed - id: honest-gates - content: "F3 — raise coverage threshold toward achieved and audit the omit-list." - status: pending + content: "F3 — raise coverage threshold toward achieved and audit the omit-list. DONE (PR #31)." + status: completed - id: ci-workflow content: "F4 — add a CI workflow that runs check-ci on push and PR." status: completed - id: accessible-output - content: "F8 — emit a text alternative for the chart and lift failing contrasts." - status: pending - - id: adoptability - content: "F5/F6/F7 — trust-boundary note + size cap, guardrail simplify-and-fail-close, rename guide." + content: "F8 — emit a text alternative for the chart and lift failing contrasts. DONE (PR #33)." + status: completed + - id: adoptability-f5-f7 + content: "F5 remote size cap + trust-boundary note and F7 rename guide. DONE (PR #34)." + status: completed + - id: guardrail-f6 + content: "F6 — agent_hooks.py guardrail hardening. DEFERRED: needs owner intent on the fail-closed semantics + a dedicated security-reviewed session (a blanket $( deny would break the agent's own heredoc commits). See the gate-expansion thread." status: pending ---