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
9 changes: 2 additions & 7 deletions plugins/wff-chat/skills/git/workflows/pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ Identify:
- **Purpose**: Why these changes were made
- **Impact**: Benefits, risks, breaking changes
- **Testing**: What validation was done or needed
- **CHANGELOG**: If any commit uses type `feat`, `fix`, `perf`, or includes `!` (breaking
change), verify that `CHANGELOG.md` has been updated. If not, note it as a required
action before PR creation.
- **Size**: Count total lines changed (`git diff $(git merge-base HEAD main)..HEAD --stat |
tail -1`). If > 500 lines, consider whether the PR can be split. Recommend a split when
changes span unrelated concerns (for example, a feature addition combined with a
Expand Down Expand Up @@ -129,7 +126,6 @@ Omit this section for pure code changes with no deployment side-effects.]
- [ ] Format passes (`uv run ruff format --check`)
- [ ] Linting passes (`uv run ruff check`)
- [ ] Type checking passes (`uv run basedpyright`)
- [ ] CHANGELOG.md updated (required for feat, fix, perf, or breaking changes)

## Notes

Expand Down Expand Up @@ -200,7 +196,7 @@ time:

1. **Re-sync immediately before merge.** `gh pr merge --auto` plus update-branch is the
efficient loop, but the PR must be up-to-date against the latest base at merge time.
2. **Apply skip/changelog labels BEFORE the synchronize push.** A label only takes effect if
2. **Apply skip labels BEFORE the synchronize push.** A label only takes effect if
present before the push that triggers the workflows. Applying it after requires an empty
commit to re-trigger; a bare label event does not re-run `pull_request` workflows.
3. **Dismiss stale bot reviews.** A `coderabbit`/Copilot review left in CHANGES_REQUESTED
Expand All @@ -213,7 +209,7 @@ time:
6. **Diff the merged file vs base to verify semantic correctness.** A textual auto-merge can
be semantically wrong. Conflict-resolution heuristic: for files already changed by merged
PRs take the base branch's version (never revert merged work); keep the PR's version only
for files unique to it; union additive doc sections (e.g., CHANGELOG).
for files unique to it; union additive doc sections (e.g., a reference index or catalog).

Verify the actual gate state (`gh pr view <n> --json mergeStateStatus,statusCheckRollup`)
rather than waiting on a never-reported required context.
Expand Down Expand Up @@ -267,7 +263,6 @@ unblocks the enterprise customer pilot that requires SSO. Tracks #142.
- [x] Format passes (`uv run ruff format --check`)
- [x] Linting passes (`uv run ruff check`)
- [x] Type checking passes (`uv run basedpyright`)
- [x] CHANGELOG.md updated

## Notes

Expand Down
21 changes: 21 additions & 0 deletions plugins/wff-chat/skills/observability-and-instrumentation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,27 @@ Rules for every alert you create:
4. Use two severities only: **page** (user-facing, act now) and **ticket** (degradation,
act this week). A third tier becomes noise that trains people to ignore everything.

**Security alerting is a distinct axis from symptom alerting.** The symptom rules
above optimize for "users are hurt", which is the right default for reliability
and the wrong one for an attack in progress: credential stuffing, enumeration, and
scripted abuse degrade nothing a user feels until they succeed. Add rules for
authentication-failure and authorization-denial spikes alongside the symptom set.
Standards manifest `OPS-006` covers this and requires three things a reliability
alert usually leaves implicit: the rule is **committed** (not configured only in a
vendor console), it **names its destination channel**, and it carries a recorded
**test-fire timestamp**. An alert that pages nobody is not alerting.

Related manifest checks in the `operations` domain
(`docs/standards-manifest.yaml`): `OPS-005` (security events emitted against a
documented taxonomy, and greppable in source, so a taxonomy cannot document
events the code never emits) and `OPS-004` (log secret redaction, proven by a
test rather than by the redaction helper's presence).

This skill is the human-facing narrative for instrumenting one service. The
`OPS-*` checks are the durable half: they land in the compliance master log, get
delta caching, fleet escalation at the 3-repo threshold, and staleness detection,
none of which a skill provides. Use both.

### 7. Verify the telemetry itself

Instrumentation is code; it can be wrong. Before calling the work done, trigger the
Expand Down
27 changes: 24 additions & 3 deletions plugins/wff-chat/skills/shipping-and-launch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ looks like. Every launch should be reversible, observable, and incremental.
- [ ] Input validation on all user-facing endpoints
- [ ] Authentication and authorization checks in place
- [ ] Security headers configured (CSP, HSTS, etc.)
- [ ] Rate limiting on authentication endpoints
- [ ] Rate limiting on authentication endpoints, with the configured limit recorded (`OPS-011`)
- [ ] CORS configured to specific origins (not wildcard)
- [ ] Application data-store role is not the table owner and does not hold BYPASSRLS (`OPS-002`)
- [ ] Row-level security, if claimed, passes a two-direction test (`OPS-003`)
- [ ] Logs redact secrets, proven by a test rather than by the filter's presence (`OPS-004`)
- [ ] Public write paths (signup, password reset, contact forms) carry an anti-automation control (`OPS-009`)
- [ ] Runtime secrets come from a secret manager, not a baked-in `.env` (`OPS-010`)

### Performance

Expand All @@ -64,6 +69,8 @@ looks like. Every launch should be reversible, observable, and incremental.
- [ ] On-call questions for this feature are answerable from telemetry
- [ ] Logging and error reporting configured
- [ ] Symptom-based alerts created and test-fired
- [ ] Security events emitted against a documented taxonomy: authn failure, authz denial, rate-limit trip, input-validation reject (`OPS-005`)
- [ ] Security alerts are committed as rules, name their destination channel, and carry a recorded test-fire timestamp (`OPS-006`)

### Accessibility

Expand All @@ -76,18 +83,32 @@ looks like. Every launch should be reversible, observable, and incremental.

### Infrastructure

- [ ] Environment variables set in production
- [ ] Environment variables set in production, and attested in a dated runtime-config document (`OPS-001`)
- [ ] Database migrations applied (or ready to apply)
- [ ] DNS and SSL configured
- [ ] CDN configured for static assets
- [ ] Health check endpoint exists and responds
- [ ] Backups inventoried with schedule, retention, and destination (`OPS-007`)
- [ ] A restore drill has actually been performed and logged; a configured backup is not a tested one (`OPS-008`)
- [ ] Managed-service console settings are committed AND pushed by a workflow, not just committed (`OPS-012`)

> **`OPS-*` references above point to the `operations` domain in
> `docs/standards-manifest.yaml`.** This checklist is the human-facing narrative
> for a single deploy; the manifest checks are the durable half that lands in the
> master log, gets delta caching, fleet escalation at the 3-repo threshold, and
> staleness detection. Use both. A checkbox ticked here leaves no record; an
> `OPS-*` finding does.
>
> The manifest checks are deliberately harder to satisfy than a checkbox: each
> names a durable artifact rather than a state of the world. "Backups are
> configured" ticks a box; `OPS-008` wants a dated restore-drill log entry.

### Documentation

- [ ] README updated with any new setup requirements
- [ ] API documentation current
- [ ] ADRs written for any architectural decisions
- [ ] CHANGELOG updated (OpenSSF release gate)
- [ ] Release commits are Conventional so semantic-release generates the CHANGELOG at release (OpenSSF release gate; do not hand-edit CHANGELOG.md)
- [ ] User-facing documentation updated (if applicable)

## Feature Flag Strategy
Expand Down
1 change: 0 additions & 1 deletion plugins/wff-code/agents/code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ forward from this repo's prior review checklist:
- [ ] Public APIs are documented
- [ ] Complex logic has comments
- [ ] README updated if needed
- [ ] CHANGELOG entry added

### Security

Expand Down
132 changes: 123 additions & 9 deletions plugins/wff-code/agents/compliance-synthesis.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,76 @@ fleet-wide insights, writes a weekly synthesis report.
distinct repos. Promote groups appearing in three or more distinct
sessions across two or more distinct repos.

**Exclude degenerate patterns before grouping.** A `pattern` that is
empty, whitespace-only, or a bare YAML block-scalar marker (`>-`, `>`,
`|`, `|-`, `|+`, `>+`) is a parse artifact, not a description.
Grouping them would make a parse bug the headline insight of the
report. Exclude them from trending, and report the count once under
Data Quality with the affected `session_date` and `repo` values so the
pollution stays visible instead of being silently dropped.

**The parser fallback is a parse artifact too.** When a description
is unusable, `scripts/compliance_rollup_reconcile.py` writes
`"(no description parsed) <proposed_manifest_id>"` so the candidate
stays traceable to its origin. That string is neither empty nor a
block-scalar marker, so the filter above does not catch it, and every
fallback row for the same ID normalizes to the same text: exactly the
shape that ranks first under the promotion rule.

Classify a row as a fallback only when its `pattern` equals
`"(no description parsed) "` followed by that same candidate's own
`proposed_manifest_id`, and use that one predicate for exclusion, for
the Data Quality count, and for the `#VERIFY` step below. A prefix
test is the wrong shape here: the producer accepts arbitrary strings,
so a real description that happens to open with those words would be
discarded as an artifact, and a report that silently drops real
candidates is a worse failure than the pollution this rule prevents.
Matching the ID as well as the prefix is what makes the row
self-identifying rather than merely prefix-shaped.

Exclude fallback rows from trending, count them separately from the
marker rows, and list their affected `session_date` and `repo` values
under Data Quality. A rising fallback count is a producer-side parse
problem, which is a different finding from a recurring real pattern
and must not be reported as one.

The two artifact classes need separate assumptions and separate
verification steps, because they are found by different predicates. A
single `#VERIFY` keyed on the marker set cannot see a fallback row at
all: lines above establish that the marker filter does not catch
`"(no description parsed) ..."`. Pointing the fallback claim at the
marker predicate would return zero every time and read as evidence
that there is no fallback problem, which is a verification step that
cannot fail, the exact defect this whole rule set exists to remove.

`#ASSUME` (markers): the committed master log carries 20 block-scalar
marker rows from an earlier parser version, spread across four
sessions and four repos, the shape that ranks first under the
promotion rule above. Measured once, at authoring time.
`#VERIFY` (markers): recount before citing. Filter
`master-log.jsonl` for `unclassified_candidates[*].pattern` values in
the block-scalar marker set (`>-`, `>`, `|`, `|-`, `|+`, `>+`), plus
empty and whitespace-only values, and report the observed count and
the distinct `(session_date, repo)` pairs you actually found, not the
number above. If they disagree, report what you measured and note the
drift.

`#ASSUME` (fallback): the fallback-row count is unmeasured. No number
is asserted here, because none was taken.
`#VERIFY` (fallback): count them with the exact-equality predicate
defined above, `pattern` equal to `"(no description parsed) "` plus
that same candidate's own `proposed_manifest_id`, never the marker
set and never a bare prefix test. Report the count and the distinct
`(session_date, repo)` pairs separately from the marker figures.

`#ASSUME`: the producer-side guard is `is_degenerate_pattern` in
`scripts/compliance_rollup_reconcile.py`, and these rows predate it,
so no new ones should appear.
`#VERIFY`: confirm that function still exists and still covers the
marker set above; if any degenerate row carries a `session_date`
later than the guard's introduction, the guard has a hole and that
is itself a Data Quality finding, not a historical artifact.

**Stuck manifest candidates.** For each unique
`proposed_manifest_id` seen anywhere in the window: check whether
that ID exists in the standards manifest at
Expand All @@ -51,11 +121,34 @@ fleet-wide insights, writes a weekly synthesis report.
with `remediation_status: open` more than 14 days after the original
proposal, surface as a follow-through gap.

**Coverage and override hotspots.** Coverage: for every catalog repo
**Coverage and override volume.** Coverage: for every catalog repo
not archived, find the newest `session_date`. Flag any older than
60 days. Overrides: count `totals.overrides_applied` per check ID
across the window. Flag check IDs overridden in four or more
distinct repos.
60 days.

Overrides: `totals.overrides_applied` is a scalar integer per session
entry, not a per-check map, and `findings_by_check` items carry only
`{id, severity, remediation_status}` with no override field.

`#ASSUME`: no producer writes a check-ID-to-override association
anywhere, so the per-check grouping this insight originally specified
cannot be computed from the current schema. That was read off the
producers once, at authoring time; if one later emits the
association, the scalar-only rule below turns from honest into
suppressive and hides attribution that is now observable.
`#VERIFY`: before applying the rule, grep the master-log producers
(`scripts/compliance_rollup_reconcile.py` and the
`compliance-retrospective` agent's output schema) for an override
field on `findings_by_check` items. If one exists, report the real
per-check attribution and raise the stale rule as a Data Quality
finding against this file.

Until a producer emits it, report
the scalar total per session and repo and label it explicitly as
"not attributable to specific check IDs (schema gap)". Do NOT invent
an attribution by inference. Raise the schema gap once under
Data Quality rather than silently emitting an empty insight, because
an insight that always returns nothing is indistinguishable from one
that found nothing to report.

4. For each insight with actionable items, spot-check 1-2 supporting
per-repo files via `Read` to confirm the master log is not stale.
Expand Down Expand Up @@ -119,11 +212,32 @@ status table (Resolved / Still open / Not re-audited), recommendation.>

<Table: repo, last audit date, days stale. Sorted descending.>

## Override hotspots

<Per check ID exceeding threshold: check description, repos overriding,
count, recommendation (narrow check scope / accept as standard
exception / other).>
## Override volume

<Table: repo, session date, `totals.overrides_applied`. Sorted
descending by count. Append this line verbatim so a reader cannot
mistake the scalar for per-check attribution: "Not attributable to
specific check IDs (schema gap; see Data quality)." Do NOT write a
per-check-ID breakdown here: no producer emits the check-ID-to-override
association it would require, so any such table would be inferred
rather than observed.>

## Data quality

<Schema gaps and staleness noticed while computing the insights above,
one line each. The override attribution gap belongs here whenever the
Override volume section is non-empty.

Two parse-artifact counts are mandatory whenever either is non-zero,
reported separately because they have different causes: the number of
excluded block-scalar-marker patterns with their affected
`(session_date, repo)` pairs, and the number of fallback patterns with
theirs, counted with the exact predicate above (`pattern` equals
`"(no description parsed) "` plus that candidate's own
`proposed_manifest_id`), never a bare prefix test. A fallback
count that is rising, or that carries a `session_date` later than the
producer guard's introduction, is an open producer-side parse bug and
must be recommended for a fix rather than logged as history.>

## Recommended actions for next sprint

Expand Down
4 changes: 2 additions & 2 deletions plugins/wff-code/agents/ossf-compliance-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -808,8 +808,8 @@ Five criteria currently GAP. For each: the exact badge questionnaire text, what
### change_control_release_notes_vulns (MUST)

**Criterion text:** "The project MUST identify each vulnerability in its change log."
**What satisfies it:** CHANGELOG entries for security fixes explicitly cite the CVE ID (e.g., `CVE-2024-12345`).
**Remediation:** Add to CLAUDE.md release standard: "CHANGELOG entries that fix a security vulnerability MUST include the CVE ID if one has been assigned. Format: `- fix(security): resolve CVE-2024-XXXXX -- [brief description]`." Apply retroactively to any existing vulnerability fix entries in CHANGELOG.md.
**What satisfies it:** The generated CHANGELOG entry for a security fix cites the CVE ID (e.g., `CVE-2024-12345`). Because python-semantic-release renders the changelog from Conventional Commits at release, the CVE ID must originate in the fixing commit message.
**Remediation:** Do NOT hand-edit `CHANGELOG.md`; the org retired per-PR changelog edits (see `ByronWilliamsCPA/.github` PR #288) because they conflicted under the merge queue. Instead, ensure the fixing commit names the CVE so PSR surfaces it at release, e.g. `fix(security): resolve CVE-2024-XXXXX -- [brief description]`. Add to the CLAUDE.md release standard: "Commits that fix a security vulnerability MUST include the CVE ID in the commit message if one has been assigned." Existing pre-PSR entries already in `CHANGELOG.md` may be left as-is.

### reporting_vulnerability_report_private (MUST)

Expand Down
Loading