Skip to content

[#227] feat: assess-security capability + deterministic secret-scanning layer#341

Merged
rucka merged 10 commits into
mainfrom
feat/#227-assess-security-secret-scanning
Jul 18, 2026
Merged

[#227] feat: assess-security capability + deterministic secret-scanning layer#341
rucka merged 10 commits into
mainfrom
feat/#227-assess-security-secret-scanning

Conversation

@rucka

@rucka rucka commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

PR Information

PR Title: [#227] feat: assess-security capability + deterministic secret-scanning CI layer
Story/Epic: #227 (epic #208 — quality/security review)
Type: Feature (skill + KB + CI config — no runtime application code)
Priority: Medium
Assignee: Gianluca Carucci
Reviewers: independent blind review (2-lens: process + adversarial nit)
Labels: feature, security

Summary

What Changed

Delivers story #227's two halves:

  1. pair-capability-assess-security (skill, dataset + installed mirror) — review-mode 1-line verdict + collapsed findings feeding the risk matrix's security dimension (D22); audit-mode OWASP scan writing a report and proposing project rules via record-decision. Rules resolve through a 5-layer cascade (global KB → per-service → per-web-app → adoption → package-scoped). It never scans for secrets itself (D24).
  2. Deterministic secret-scanning CI layersecret-scanning.md guideline + gitleaks-example.toml asset (root + dataset, byte-identical, byte-parity-locked by a conformance test), provisioned by /setup-gates. Dogfooded into this repo's own .github/workflows/ci.yml via the license-free gitleaks binary (pinned 8.30.1) — not gitleaks-action@v2, which requires a GITLEAKS_LICENSE for org-owned repos and fails before scanning. Verified green in live CI (secret-scan job). Root .gitleaks.toml allowlists exactly the documented synthetic strings via precise regexes.

Supporting: D22 recorded as an ADL; quality-model Security pillar backlinks the 5-layer cascade; ADR-015 records "deterministic layer is CI, not a skill"; /pair-process-review Step 2.4 composes assess-security (CHANGES-REQUESTED on introduced vulnerabilities).

Why This Change

Security findings now surface in every review against an objective, resolved rule set, and a committed secret mechanically blocks the build with no LLM involved (R6.5) — closing the two gaps in epic #208.

Story Context

User Story: I want pair-capability-assess-security (review + audit) plus a deterministic secret-scanning layer, so security findings surface in every review with objective rules and secrets mechanically block the build.
Acceptance Criteria:

  • AC1 — review composes assess-security with the 5-layer resolved rule set; 1-line verdict + collapsed findings (D22). ✅
  • AC2 — committed secret → build RED mechanically, no LLM (R6.5). ✅ (dogfooded, CI-verified)
  • AC3$mode: audit → report in .pair/working/reports/security/ + proposes project rules to record. ✅
  • AC4 — introduced vulnerabilities → CHANGES-REQUESTED. ✅

Changes Made

Implementation Details

  • Change 1: assess-security SKILL.md (dataset + .claude/ mirror) — review/audit modes, 5-layer cascade, D22 output, D24 boundary.
  • Change 2: secret-scanning.md guideline + gitleaks-example.toml (root + dataset, byte-identical) — dual CI-template forms (Action + GITLEAKS_LICENSE for orgs; binary for no-license), fail-closed, allowlist mechanism.
  • Change 3: repo ci.yml secret-scan job (gitleaks binary) + root .gitleaks.toml; /setup-gates provisions the layer; /pair-process-review Step 2.4 composes assess-security.
  • Change 4: ADR-015, D22 ADL, quality-model Security-pillar backlink; conformance suites; docs-site pages; skill-count 35→36 refresh; llms.txt regen.

Files Changed (42 files — see the PR Files tab for the authoritative list)

  • Added: .claude/skills/pair-capability-assess-security/SKILL.md (+ dataset mirror); .pair/knowledge/guidelines/quality-assurance/security/secret-scanning.md (+ dataset mirror); .pair/knowledge/assets/gitleaks-example.toml (+ dataset mirror); .gitleaks.toml; .pair/adoption/tech/adr/adr-015-…md; .pair/adoption/decision-log/2026-07-18-d22-…md; packages/knowledge-hub/src/conformance/{assess-security,secret-scanning}.test.ts.
  • Modified: .github/workflows/ci.yml; pair-process-review + pair-capability-setup-gates + pair-next SKILLs (+ mirrors); quality-assurance/quality-model.md (+ mirror); README.md; .pair/knowledge/getting-started.md + way-of-working.md (+ mirrors, 35→36 count); .pair/llms.txt (regenerated); packages/knowledge-hub/eval/trigger-prompts.json; several apps/website/content/docs/** pages.
  • Deleted / Renamed: none.

Database Changes / API Changes

  • N/A — skill/KB/CI content, no runtime code or data.

Testing

Test Coverage

  • Conformance Tests: assess-security.test.ts (20 — modes, D22, D24, review composition, setup-gates provisioning) + secret-scanning.test.ts (16 — dual-form template, org-license documented, fail-closed, byte-parity lock for this story's mirrored files).
  • CI (dogfood): the secret-scan job runs the gitleaks binary on this repo — verified green in live CI.
  • Allowlist verification: full-history scan clean (0 leaks); a 1-char-different secret still trips (allowlist is surgical, not broad).

Test Results

@pair/knowledge-hub vitest: ✅ 182 passing (assess-security 20, secret-scanning 16, + suite)
skills:conformance:        ✅ PASS (36 skills, 26 capability)
docs:staleness:            ✅ PASS
check:links / markdownlint: ✅ Clean
CI: build ✅ · preview ✅ · secret-scan ✅ (binary, no license)

Testing Strategy

  • Happy Path: review composes assess-security → 1-line verdict + collapsed findings.
  • Edge Cases: committed secret → RED; audit mode → report + rule proposals; introduced vuln → CHANGES-REQUESTED.
  • Error Handling: fail-closed CI (set -euo pipefail, --exit-code 1, no continue-on-error).

Quality Assurance

  • assess-security is output-only (audit report is the one exception, D14); adoption writes go through record-decision.
  • Byte-parity lock for this story's mirrored security files; conformance asserts dataset + mirror.
  • No debugging artifacts.

Deployment Information

  • Environment Impact: the secret-scan job becomes a required CI check on this repo; KB/skill content ships with the dataset. Config: the binary form needs no secret; the Action form (for adopters) needs GITLEAKS_LICENSE for orgs. Rollback: revert the PR.

Breaking Changes

  • None for consumers. New required CI job on this repo is additive.

Documentation

  • Technical Documentation: secret-scanning.md guideline, ADR-015, D22 ADL, quality-model backlink.
  • User Documentation: docs-site pages updated; skill catalog 35→36.
  • Knowledge Sharing: .pair/llms.txt was regenerated and swept in ~9 previously-unindexed pre-existing files (azure-devops-, context-map-, canonical-states, ddr-template, subdomain-context-template) — harmless generator output, unrelated to this story, noted here for transparency.

Performance Impact

  • N/A (skill/KB/CI content). The secret-scan binary job adds ~8s to CI.

Security Considerations

Security Review

  • Deterministic, fail-closed secret gate: gitleaks binary, --exit-code 1, no continue-on-error, pinned 8.30.1 — no LLM in the path (R6.5, D24).
  • Allowlist scope: .gitleaks.toml allowlists exactly the documented synthetic strings (AKIAABCDEFGHIJKLMNOP, usr_abc123def456, sess_xyz789uvw012); no un-allowlisted secret-shaped string introduced; a different secret still fails.
  • assess-security covers authn/authz, injection, OWASP surface via the rule cascade — the judgment-call counterpart, deliberately separate from the deterministic gate.

Security Testing

  • Security Scan: the new secret-scan job itself; live-CI green; full-history scan clean.

Accessibility

  • N/A — prose/MDX + CI config; no new interactive UI.

Risk Assessment

Technical Risks

Risk Impact Probability Mitigation
Adopter on an org uses the Action form without a license → job fails before scanning Med Low Template documents the org-license requirement + the license-free binary alternative; this repo uses the binary
gitleaks binary fetched over network without a checksum pin (version-pinned only) Low Low Official GitHub release over HTTPS, version-pinned; a checksum pin is a reasonable future hardening

Reviewer Guide

Review Focus Areas

  1. AC2 dogfood: the secret-scan CI job actually goes green (binary, no license).
  2. D24 boundary: assess-security never scans secrets; the deterministic layer is CI, not a skill.
  3. Mirror parity: security guideline + asset byte-identical root↔dataset.

Testing the Changes

git fetch origin feat/#227-assess-security-secret-scanning
git worktree add ../pair-227 feat/#227-assess-security-secret-scanning && cd ../pair-227
pnpm install && pnpm --filter @pair/content-ops build
pnpm --filter @pair/knowledge-hub test        # vitest 182 + check:links
gitleaks detect --source . --config .gitleaks.toml --no-banner --redact  # 0 leaks

Dependencies & Related Work

Pre-Submission Checklist

  • All ACs implemented and verified (AC2 CI-verified green)
  • Security guideline + asset byte-identical root↔dataset (conformance-locked)
  • All checks green (vitest 182, skills:conformance 36, docs:staleness, check:links, markdownlint; CI incl. secret-scan)
  • No breaking changes
  • Summary + testing + security review + reviewer guide complete
  • CI passing; no merge conflicts with main

@github-actions
github-actions Bot temporarily deployed to Website Preview July 16, 2026 18:17 Inactive
rucka added a commit that referenced this pull request Jul 16, 2026
…nt (PR #341 review)

Critical: this repo's own dogfood .pair/knowledge/ tree was missing
secret-scanning.md + gitleaks-example.toml + the README index entry,
mirroring only existed in packages/knowledge-hub/dataset/ — the live
skills' relative links resolved to nothing in this repo's own adoption
tree. Mirrored all three, byte-identical to dataset.
Minor: way-of-working.md (root + dataset) still said "35 skills", bumped
to 36 in both copies.
@github-actions
github-actions Bot temporarily deployed to Website Preview July 16, 2026 20:03 Inactive
rucka added a commit that referenced this pull request Jul 17, 2026
… lock it in with a conformance test (PR #341 round-3 review)

Root mirror had spurious extra blank lines vs dataset (retyped, not
copied). Re-copied for true byte parity, and added a conformance test
scoped to this story's 3 mirrored files (secret-scanning.md, security
README.md, gitleaks-example.toml) so neither this regression nor the
round-2 missing-mirror one can recur silently.
@github-actions
github-actions Bot temporarily deployed to Website Preview July 17, 2026 11:47 Inactive
rucka added a commit that referenced this pull request Jul 17, 2026
… fixture-test scope in ADR-015 (PR #341 round-4 review)

- Regenerated .pair/llms.txt (via existing apps/pair-cli/src/registry/llms-generation.ts
  logic) to close repo-wide staleness, including the missing secret-scanning.md entry.
- Backfilled quality-model.md into the root .pair/knowledge/ mirror (was dataset-only,
  breaking relative links from secret-scanning.md).
- Clarified in ADR-015 + secret-scanning.md that the gitleaks Verification section is a
  documented, manually-reproduced check by design, not a committed automated fixture test
  (external-binary dependency; would need a smoke test per the gate-tooling-code ADL, not a
  vitest unit test, and this repo doesn't dogfood gitleaks into its own CI yet).
@github-actions
github-actions Bot temporarily deployed to Website Preview July 17, 2026 12:06 Inactive
rucka added a commit that referenced this pull request Jul 18, 2026
…ue-on-error check (PR #341 review round 5)

MIRRORED_FILES was missing quality-model.md, backfilled in round 4 but
left unprotected against future re-divergence. Tightened the
continue-on-error assertion to match only the YAML key form
(continue-on-error:), not prose mentioning the option by name.
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 06:40 Inactive
rucka added a commit that referenced this pull request Jul 18, 2026
…s CI wiring (PR #341 review, nonActionable findings now resolved)

Per corrected policy (nonActionable is not a scope filter — a real
fixable gap gets fixed, not deferred): resolves all 5 previously-accepted
findings from the last review round.

- Records ADL 2026-07-18-d22-classification-verdict-collapsed-details.md:
  D22 (1-line verdict + collapsed findings, never a table inline) was
  cited 5+ times with no decision record anywhere.
- quality-model.md (root + dataset): backlink from the Security pillar to
  assess-security's 5-layer rule-resolution cascade.
- adr-015-security-deterministic-layer-not-a-skill.md: H1 corrected to
  "# ADR-015: ..." per the already-tracked repo-wide fast-follow (numbering
  is now final).
- Real gitleaks CI wiring, the actual point of this story: root
  .gitleaks.toml allowlisting the guideline's own worked example
  (AKIAABCDEFGHIJKLMNOP) plus 2 unrelated pre-existing placeholder tokens
  found during verification (usr_abc123def456, sess_xyz789uvw012 in
  observability/sensitive-data-protection.md) via precise literal
  regexes, not a broad pattern — a different secret in the same files
  still trips the scan (verified). secret-scan job added to ci.yml.
  Full-history scan verified clean (283 commits, 0 leaks) before wiring.
  ADR-015 updated to record this is no longer deferred.
rucka added 6 commits July 18, 2026 10:48
…ng layer

Add pair-capability-assess-security (review verdict + one-shot OWASP
audit, D22) and wire it into pair-process-review Phase 2 (AC1/AC4:
introduced red findings drive CHANGES-REQUESTED). Provision the
deterministic secret-scanning CI layer (gitleaks default, required
+ fail-closed, .gitleaks.toml allowlist) via pair-capability-setup-gates
(R6.5/D24) — never a skill, never an LLM judgment call; assess-security
explicitly never re-implements it. Record the skill/CI-layer boundary
as ADR-015.

Verified the secret-scanning guideline's own reproducibility claim
with gitleaks 8.x and fixed it: a bare `gitleaks detect` scans full
history (a leak keeps failing forever), the CI-equivalent scoped
invocation (`--log-opts`) is what actually demonstrates the
allowlist working.

Updates skill counts (35->36) across docs site + skills-guide.md
(catalog subsection was under-counted) + eval trigger-prompts.json.

Refs: #227
…nt (PR #341 review)

Critical: this repo's own dogfood .pair/knowledge/ tree was missing
secret-scanning.md + gitleaks-example.toml + the README index entry,
mirroring only existed in packages/knowledge-hub/dataset/ — the live
skills' relative links resolved to nothing in this repo's own adoption
tree. Mirrored all three, byte-identical to dataset.
Minor: way-of-working.md (root + dataset) still said "35 skills", bumped
to 36 in both copies.
… lock it in with a conformance test (PR #341 round-3 review)

Root mirror had spurious extra blank lines vs dataset (retyped, not
copied). Re-copied for true byte parity, and added a conformance test
scoped to this story's 3 mirrored files (secret-scanning.md, security
README.md, gitleaks-example.toml) so neither this regression nor the
round-2 missing-mirror one can recur silently.
… fixture-test scope in ADR-015 (PR #341 round-4 review)

- Regenerated .pair/llms.txt (via existing apps/pair-cli/src/registry/llms-generation.ts
  logic) to close repo-wide staleness, including the missing secret-scanning.md entry.
- Backfilled quality-model.md into the root .pair/knowledge/ mirror (was dataset-only,
  breaking relative links from secret-scanning.md).
- Clarified in ADR-015 + secret-scanning.md that the gitleaks Verification section is a
  documented, manually-reproduced check by design, not a committed automated fixture test
  (external-binary dependency; would need a smoke test per the gate-tooling-code ADL, not a
  vitest unit test, and this repo doesn't dogfood gitleaks into its own CI yet).
…ue-on-error check (PR #341 review round 5)

MIRRORED_FILES was missing quality-model.md, backfilled in round 4 but
left unprotected against future re-divergence. Tightened the
continue-on-error assertion to match only the YAML key form
(continue-on-error:), not prose mentioning the option by name.
…s CI wiring (PR #341 review, nonActionable findings now resolved)

Per corrected policy (nonActionable is not a scope filter — a real
fixable gap gets fixed, not deferred): resolves all 5 previously-accepted
findings from the last review round.

- Records ADL 2026-07-18-d22-classification-verdict-collapsed-details.md:
  D22 (1-line verdict + collapsed findings, never a table inline) was
  cited 5+ times with no decision record anywhere.
- quality-model.md (root + dataset): backlink from the Security pillar to
  assess-security's 5-layer rule-resolution cascade.
- adr-015-security-deterministic-layer-not-a-skill.md: H1 corrected to
  "# ADR-015: ..." per the already-tracked repo-wide fast-follow (numbering
  is now final).
- Real gitleaks CI wiring, the actual point of this story: root
  .gitleaks.toml allowlisting the guideline's own worked example
  (AKIAABCDEFGHIJKLMNOP) plus 2 unrelated pre-existing placeholder tokens
  found during verification (usr_abc123def456, sess_xyz789uvw012 in
  observability/sensitive-data-protection.md) via precise literal
  regexes, not a broad pattern — a different secret in the same files
  still trips the scan (verified). secret-scan job added to ci.yml.
  Full-history scan verified clean (283 commits, 0 leaks) before wiring.
  ADR-015 updated to record this is no longer deferred.
@rucka
rucka force-pushed the feat/#227-assess-security-secret-scanning branch from 7ac5836 to 2326030 Compare July 18, 2026 08:49
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 08:50 Inactive
rucka added a commit that referenced this pull request Jul 18, 2026
…e-scope-filter ADL (PR #341 round-7 review)

Per round-7 review of PR #341:

- adr-011..014 H1s corrected to "# ADR-NNN: <Title>" (the fast-follow
  2026-07-12-adr-sequential-naming-convention.md tracked, deferred until
  adr-009/adr-010 landed on main - both now merged). adr-014 (created after
  that ADL, still unprefixed) folded into the same fix. adr-015 (this
  story) already had a numbered H1 from round 7 - now all of adr-001..015
  are consistent, closing the "adr-015 as a lone exception" gap the review
  flagged. ADL addendum records scope + completion.
- Recorded ADL 2026-07-18-nonactionable-findings-still-get-fixed-unless-
  design-disagreement.md: the review flagged an undocumented "corrected
  policy" (nonActionable is not a scope filter) cited in commit 7ac5836's
  message but never recorded anywhere - and the same standard is applied
  again by this very fix round's own instructions, confirming it's a real,
  repeated standard rather than a one-off. Recorded per CLAUDE.md's "record
  decisions" rule so future reviewers don't re-litigate nonActionable calls
  PR-by-PR. Does not touch .claude/agents/reviewer.md's broader existing
  definition - left as a noted follow-up, out of this story's scope.

Refs #227
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 08:53 Inactive
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 09:11 Inactive
…icense), dual-form KB template, stale skill count

Verify review (Major, confirmed in live CI run 29638207943 — secret-scan
fail 5s): gitleaks-action@v2 requires a GITLEAKS_LICENSE for org-owned
repos (foomakers is an org), so the round-8 dogfood job failed before
scanning — a red-but-meaningless gate. My earlier "verified" was the local
binary, not the CI action.

- ci.yml: run the MIT-licensed gitleaks binary directly (pinned 8.30.1),
  no org-license gate; fail-closed via --exit-code 1.
- secret-scanning.md (root + dataset, byte-identical): document BOTH forms
  — Option A action + GITLEAKS_LICENSE (org note, matches
  github-actions-implementation.md), Option B binary (no license).
- secret-scanning.test.ts: assert the template surfaces the org-license
  requirement + the binary option.
- getting-started.md (root + dataset): stale "35 skills (25 capability)"
  -> "36 (26 capability)" — the drift class this PR fixes elsewhere.
- ADR-015: correct the 2026-07-18 update to reflect binary-not-action.
@rucka
rucka force-pushed the feat/#227-assess-security-secret-scanning branch from 0d82c14 to 9885f58 Compare July 18, 2026 09:12
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 09:13 Inactive
rucka added a commit that referenced this pull request Jul 18, 2026
…e-scope-filter ADL (PR #341 round-7 review)

Per round-7 review of PR #341:

- adr-011..014 H1s corrected to "# ADR-NNN: <Title>" (the fast-follow
  2026-07-12-adr-sequential-naming-convention.md tracked, deferred until
  adr-009/adr-010 landed on main - both now merged). adr-014 (created after
  that ADL, still unprefixed) folded into the same fix. adr-015 (this
  story) already had a numbered H1 from round 7 - now all of adr-001..015
  are consistent, closing the "adr-015 as a lone exception" gap the review
  flagged. ADL addendum records scope + completion.
- Recorded ADL 2026-07-18-nonactionable-findings-still-get-fixed-unless-
  design-disagreement.md: the review flagged an undocumented "corrected
  policy" (nonActionable is not a scope filter) cited in commit 7ac5836's
  message but never recorded anywhere - and the same standard is applied
  again by this very fix round's own instructions, confirming it's a real,
  repeated standard rather than a one-off. Recorded per CLAUDE.md's "record
  decisions" rule so future reviewers don't re-litigate nonActionable calls
  PR-by-PR. Does not touch .claude/agents/reviewer.md's broader existing
  definition - left as a noted follow-up, out of this story's scope.

Refs #227
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 09:16 Inactive
@rucka
rucka force-pushed the feat/#227-assess-security-secret-scanning branch from d6d38ee to 9885f58 Compare July 18, 2026 11:39
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 11:39 Inactive
…ify A/B scan-scope in secret-scanning template

- README.md: stale "35 Agent Skills" -> 36 (assess-security is the 26th
  capability skill); getting-started.md was already bumped, this is the
  root repo README that also carries the count.
- secret-scanning.md (root + dataset, byte-identical): the two CI-template
  forms are not "equivalent" in scan scope — reworded to state they share
  the fail-closed guarantee but differ in scope (Action = event commit
  range; binary = full history).
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 12:07 Inactive
@rucka

rucka commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Code Review — PR #341

PR Number: #341
Author: rucka (Gianluca Carucci)
Reviewer: Independent review (/pair-process-review, adversarial nit-hunt)
Review Date: 2026-07-18
Story/Epic: #227 (assess-security + deterministic secret-scanning layer) / Epic #208
Review Type: Feature

Review Summary

Overall Assessment

  • Approved with Comments — Minor issues noted, can merge

The change is solid and the four acceptance criteria are genuinely met (not just claimed):
Step 2.4 wires assess-security as a required Phase-2 composition; setup-gates provisions a
required, fail-closed secret-scan job + .gitleaks.toml; audit mode writes to
.pair/working/reports/security/; and Step 5.2 ties an introduced red finding to
CHANGES-REQUESTED. The deterministic layer is dogfooded and live CI secret-scan passes (7s).
All cross-references resolve in both the root and dataset trees; the 4 byte-parity mirror files are
identical; quality-model.md §3.1/§3.2/§4 citations are accurate; conformance test counts are correct
(assess-security.test.ts = 20). ADR-015 numbering and the D22 ADL naming/structure conform.

This is an adversarial re-review against an author claim of zero outstanding findings. That claim
does not hold: the items below are real (one concrete defect + several nits). None are blocking.

Business Value Validation

Closes the two gaps in Epic #208 as specified: a judgment-call security assessment skill, and a
structural (LLM-free) secret gate. Confirmed.

Detailed Review Comments

Minor Issues

  • packages/knowledge-hub/eval/trigger-prompts.json:166-171 (AD-N3) — Self-contradictory
    eval record. It is type: should-not-trigger with near_miss_for: "assess-*" and
    expected: "assess-security". Since assess-security is a member of the assess-* family, the
    record simultaneously asserts "no assess-* skill may fire" and "assess-security is the correct
    destination" — mutually exclusive under the schema documented in eval/README.md and the file's own
    $comment. Every other negative (AD-N1→setup-pm, AD-N2→record-decision, AD-N4→none) has expected
    pointing outside its near_miss_for. Moreover the prompt "Assess the security posture of our
    login flow" is now a genuine should-trigger for assess-security (near-identical to AS-02), so
    it is a true positive miscategorized as a near-miss. The PR description frames this as a correct fix
    ("now correctly expects assess-security"), but flipping only expected (none→assess-security) while
    leaving type/near_miss_for produced an incoherent entry. Recommendation: delete AD-N3
    (redundant with AS-01/AS-02) or convert it to a should-trigger in the assess-security family and
    drop near_miss_for. (Non-blocking: eval fixture, not asserted by vitest / not on the runtime path.)

Nits

  • .pair/llms.txt — Bundles 11 added index entries unrelated to pair-capability-assess-security + deterministic secret-scanning layer #227 (Azure DevOps
    automation/issues/implementation/tracking, context-map-maintenance, context-map-template,
    canonical-states, ddr-template, subdomain-context-template) — a stale generated-index sync
    swept into a security-feature PR and not mentioned in the description. All targets exist (no dead
    links) and llms.txt is generator-produced (apps/pair-cli/src/registry/llms-generation.ts), so the
    content is correct; the only issue is scope creep + silence in the PR narrative. The one entry this
    story actually needs (secret-scanning.md) is correctly present; adoption/asset files are correctly
    excluded. Recommendation: note the regen in the description, or land it separately. Largely
    by-design (correct generator output).

  • PR [#227] feat: assess-security capability + deterministic secret-scanning layer #341 description → "Changes Made / Files Changed" — Incomplete enumeration: omits
    .pair/llms.txt, .pair/knowledge/getting-started.md (+mirror), .pair/knowledge/way-of-working.md
    (+mirror), README.md, .github/workflows/ci.yml, .gitleaks.toml, and the new
    .pair/adoption/decision-log/2026-07-18-d22-…md ADL (several appear only in prose). Hedged by
    "see the PR Files tab", so low impact. Recommendation: list all changed paths or drop the partial
    list.

  • .claude/skills/pair-next/SKILL.md + dataset mirror (version stays 0.4.1) — Body changed
    (35→36 catalog, 3 spots) with no version bump, whereas setup-gates (0.4.1→0.5.0) and review
    (0.5.0→0.6.0) bumped. By-design / non-actionable: no documented rule mandates a bump, and the
    35→36 count refresh was applied without version bumps everywhere else (skills-guide, 9 .mdx). pair-next
    had no behavioral change (count-only), so not bumping is the consistent choice; bumping would be the
    inconsistency. Reported for transparency.

Positive Feedback

  • Genuinely test-first factual fix to secret-scanning.md's verification (--log-opts="-1" scoping),
    with the reasoning captured in ADR-015 Trade-offs.
  • The secret-scanning.test.ts root↔dataset byte-parity guard (scoped to this story's 4 files) is a
    well-judged, self-documenting regression lock, honest about the ~30 pre-existing unrelated mismatches
    it deliberately does not try to boil-the-ocean fix.
  • ADR-015 + the backfilled D22 ADL close two "cited-but-unrecorded decision" gaps cleanly.

Security Review

Deterministic secret-scan job is required, fail-closed (set -euo pipefail, --exit-code 1, no
continue-on-error), pinned gitleaks 8.30.1 binary (avoids the org-license gate). .gitleaks.toml
allowlists exactly 3 real synthetic strings (AKIAABCDEFGHIJKLMNOP, usr_abc123def456,
sess_xyz789uvw012) — all verified present at the cited locations; no un-allowlisted secret-shaped
string introduced. Live CI green. No security concerns.

Testing Review

assess-security.test.ts = 20 tests (matches the description), secret-scanning.test.ts = 17.
Conformance asserts both dataset and mirror copies. CI build/preview/secret-scan all pass.

Risk Assessment

Low. Findings are Minor/Nit and confined to eval fixture data + PR-hygiene; no runtime or interface risk.


Decision: Approved with Comments. The "zero findings" claim is disproved (AD-N3 is a real defect),
but nothing here blocks merge. Recommend fixing AD-N3 before or shortly after merge.

…anning Verification prose with full-history CI (verify-review)

- eval/trigger-prompts.json AD-N3 was self-contradictory (should-not-trigger
  + expected assess-security). The prompt "Assess the security posture of
  our login flow" is a direct assess-security trigger -> should-trigger.
- secret-scanning.md Verification (root + dataset): the prose claimed
  full-history scanning "is not what the CI job is testing" and that an
  allowlist wouldn't help — both now false since the dogfooded CI uses
  `gitleaks detect --source .` (full history) + the allowlist. Reworded to
  match: reproduction uses --log-opts=-1 for isolation; CI scans full
  history against the allowlist.
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 13:14 Inactive
@rucka

rucka commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation — all requested findings addressed

Fixed (this round):

  • Minoreval/trigger-prompts.json AD-N3 was self-contradictory (should-not-trigger + expected: assess-security); converted to a should-trigger case and dropped near_miss_for (the prompt is a genuine assess-security trigger).
  • Nit.pair/llms.txt regen scope now noted in the description (harmless generator output; pre-existing files indexed).
  • Nit — Files Changed completed via the full PR template.
  • Earlier: root README skill count 35→36; the two CI-template forms are no longer called "equivalent" (scan-scope difference stated); the secret-scanning Verification prose reconciled with the full-history dogfood CI; secret-scan CI job runs the license-free gitleaks binary — verified green in live CI.
  • PR body rewritten to the full PR template (Security Review included).

Remaining — non-closable:

  • pair-next version unbumpedwhy: count-only change; no bump rule, and bumping would be inconsistent with the other count-only refreshes (by-design).
  • ~30 pre-existing root↔dataset mirror mismatches (unrelated files) — why: out of pair-capability-assess-security + deterministic secret-scanning layer #227 scope; this story's own mirrored files are byte-identical; needs a dedicated mirror-parity cleanup + gate.
  • gitleaks binary no SHA256 pinwhy: official GitHub release over HTTPS, version-pinned; checksum pin is an optional future hardening (noted as follow-up).

Gates green (vitest 182, skills:conformance 36, docs:staleness, check:links; CI incl. secret-scan); rebased on main.


Mirror reconciliation (post-merge): the root↔dataset KB mirror drift is intentionally not hand-fixed in-PR (a blind byte-sync would break the intentional dual-naming convention /X/pair-capability-X). It will be reconciled by running pair update after these PRs merge — the CLI's registry sync applies the naming transform correctly and never touches .pair/adoption/ (protected by reserved-paths). This is the intended transform-aware mechanism, not a manual sync.

…ply-chain integrity)

The secret-scan job (and the shipped Option-B template) fetched the gitleaks
binary version-pinned but without an integrity check. Added sha256sum -c against
the release's published checksum (551f6fc… for 8.30.1 linux_x64), fail-closed —
if the release asset were swapped, the job fails instead of running an
unverified binary. Addresses the reviewer's supply-chain hardening note.
@github-actions
github-actions Bot temporarily deployed to Website Preview July 18, 2026 13:58 Inactive
@rucka

rucka commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation follow-up — supply-chain hardening applied

Reconsidered the "by-design" gitleaks-download note as a real weakness and fixed it: the secret-scan job (and the shipped Option-B template, root + dataset) now pins the gitleaks binary by SHA256 (551f6fc… for 8.30.1 linux_x64, from the release checksums), verified with sha256sum -c before extraction — fail-closed if the release asset is ever swapped. Commit d0ab802.

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