feat(compliance): add devflow-compliance optional plugin (Phases 1+2)#265
Conversation
Adds the compliance rule, skill (+8 framework references), and plugin
registration for GDPR, HIPAA, PCI DSS, SOC 2, ISO 27001, SOX coverage.
Phase 1 scope (this commit):
- shared/rules/compliance.md: global rule (paths: []) with 6 data-control
directives; first global optional plugin-scoped rule in the registry
- shared/skills/compliance/SKILL.md: 137-line skill with Iron Law
("CLASSIFY IT, MINIMIZE IT, ENCRYPT IT, AUDIT IT"), Project Framework
Declaration protocol, scope-boundary anti-double-count guard,
clean-report contract (no manufactured findings), 6 control categories
with VULNERABLE/COMPLIANT snippets, severity table, framework mapping
(SOC 2 / PCI DSS / GDPR / HIPAA / ISO 27001 / SOX), 8-item checklist,
and Extended References table linking all 8 reference files
- shared/skills/compliance/references/: 8 reference files — gdpr.md,
hipaa.md, pci-dss.md, soc2.md, iso-27001.md, sox.md, detection.md,
sources.md; grounded in actual regulations, no fabricated citations
- plugins/devflow-compliance/.claude-plugin/plugin.json: plugin manifest
(skills: [compliance], rules: [compliance], version 1.8.3)
- .claude-plugin/marketplace.json: marketplace entry after devflow-rust
- src/cli/plugins.ts: devflow-compliance entry (optional: true, 23rd
plugin); adds 'compliance' to LEGACY_SKILLS_V2X for future cleanup;
updates partitionSelectablePlugins comment (applies ADR-003)
- src/cli/commands/init.ts: pluginHints entry, Step 2 label → "Language
& ecosystem plugins", advanced rules note documents compliance as global
- tests/plugins.test.ts: extends allowedOptional set for devflow-compliance
npm test: 1807/1807 passed (60 test files)
npm run build: exit 0 (23 plugins, 13 rules, 41 skills distributed)
Co-Authored-By: Claude <noreply@anthropic.com>
…se 2
Integrates the compliance plugin from Phase 1 into the code-review, plan,
and implement command pipelines, plus updates agent instructions and docs.
Key changes:
- commands/_partials/_compliance.mds: new installed-gate partial; scope-aware
manifest check → asset verify → rule-file fallback → CLAUDE.md opt-out;
≤3 file reads, no subprocess, no LLM call, silent (avoids ADR-007)
- commands/code-review.mds: import + {compliance_gate()} in Phase 1;
COMPLIANCE_ENABLED added to REVIEWER_LIST conditional table; compliance
row in reviewer focus table; count bound explicitly ≤20 per worktree
- commands/plan.mds: import + {compliance_gate()} in Phase 5; 4→5 Designer
agents when COMPLIANCE_ENABLED; compliance focus in gap-analysis table
- commands/implement.mds: import + {compliance_gate()} in Phase 1 Setup;
COMPLIANCE field added to ALL Coder prompts (initial + fix loops) for
consistent guidance across a run; absent = no-op (avoids PF-002)
- shared/agents/reviewer.md: compliance focus row + conditional activation
note with clean-report contract
- shared/agents/designer.md: compliance added to gap-analysis focus list
- shared/agents/synthesizer.md: merge-don't-boost note in both design and
review modes for compliance+security co-located findings
- shared/agents/coder.md: COMPLIANCE input documented; Step 2 body-instructs
Skill-tool invocation of devflow:compliance when enabled + regulated surface
detected (never frontmatter — avoids PF-002 re-entrancy guard)
- shared/agents/triager.md: one-line compliance disposition hint (prefer
FIX_SEPARATE/TECH_DEBT unless code-local)
- shared/skills/gap-analysis/SKILL.md: section 7 Compliance with detection
patterns for regulatory gaps security doesn't cover
- tests/build-mds.test.ts: partial count 9→10 (RED→GREEN with new partial)
- tests/build.test.ts: plugin.json↔DEVFLOW_PLUGINS skills+rules sync test
(closes the unguarded manual-sync pair for all 23 plugins)
- docs: CLAUDE.md, README.md, docs/commands.md, file-organization.md,
skill-catalog.md updated to 23 plugins / 41 skills / 13 rules / up to 20
reviewers / 10 partials (applies ADR-003)
Co-Authored-By: Claude <noreply@anthropic.com>
…tical coder.md: "Absent COMPLIANCE field = no-op" was already documented in the Input Context section (line 42); the PF-002 meta-note about frontmatter configuration is a developer concern, not Coder runtime instruction. code-review.mds: "(plugin-gated; resolved once above, reused across all worktrees)" restated context already present on lines 137 and 158. Behavior unchanged: COMPLIANCE absent = no-op semantics preserved in the Input Context; compliance reviewer still added to every worktree when COMPLIANCE_ENABLED.
…-reqs ISO 27001 2013 control numbers (A.8.2/A.8.3/A.12.4.x/A.14.1.2/A.14.2.x) are withdrawn. The 2022 edition renumbers and reorganises them: A.5.12 classification, A.5.10 acceptable use, A.8.15 logging, A.8.16 monitoring, A.8.17 clock sync, A.8.24 cryptography, A.8.25 SDLC, A.8.26 app security requirements, A.8.27 secure engineering principles, A.8.29 security testing. In 2022 A.8.2 and A.8.3 mean privileged-access rights and information-access restriction respectively — leaving the old IDs in place would point reviewers at the wrong controls. references/iso-27001.md: replace A.8 / A.12 / A.14 section structure with proper 2022 A.5 and A.8 sections; update Common Code-Level Gaps citations. SKILL.md framework-mapping table: update ISO 27001 column for all six rows (Data Classification A.8.2→A.5.12, Logs A.12.4→A.8.15, Encryption A.10.1→A.8.24, Audit Trails A.12.4→A.8.15, Retention/Erasure A.8.3→A.8.10, IaC/Env A.14.2→A.8.25/A.8.27). Extended References description updated to match. PCI DSS v4.0: fix "Never Store" table sub-requirements — track data 3.2.1→3.3.1.1, CVV/CAV2 3.2.1→3.3.1.2, PIN/block 3.2.1→3.3.1.3 (Req 3.2.1 is retention minimisation, not SAD prohibition); PAN rendering 3.3→3.5.1.
… in column-0 fences
The 5 Coder prompt templates (SINGLE_CODER, SEQUENTIAL Phase 1, SEQUENTIAL
Phase 2+, PARALLEL Coder 1, PARALLEL Coder 2) were writing
`COMPLIANCE: \{enabled|(none)\}` inside column-0 code fences where MDS
renders backslashes verbatim. Changed to `COMPLIANCE: {enabled|(none)}`
so the compiled implement.md matches the 3 fix-loop templates (validation-fix,
alignment-fix, qa-fix) which already rendered correctly.
tests/ambient.test.ts and tests/build-mds.test.ts run in parallel vitest workers. build-mds.test.ts has multiple beforeAll hooks that call spawnSync to re-run scripts/build-mds.ts against the real plugins/*/commands/ tree. The script's compileHost() previously did: rmSync(dest) // file deleted await compileFile(host.file) // async gap — file absent here writeFileSync(dest, content) // file restored During the async gap, ambient.test.ts's discoverCommandFiles() could readdir() the file into its list, then fail with ENOENT when trying to read it, because the file had been deleted but not yet rewritten. Fix: replace the delete-then-write pattern with an atomic rename — write to a .tmp file first, then renameSync to dest. rename(2) is atomic on POSIX (same filesystem), so readers always observe either the old or new content, never a missing file. Co-Authored-By: Claude <noreply@anthropic.com>
…PCI DSS v4.0.1, need-based Req 3.2.1 retention, HIPAA §164.530(j) framing) - sources.md: PCI DSS v4.0 (March 2022) → v4.0.1 (June 2024) - sources.md: ISO/IEC 27001:2022 → 2022 edition (incl. Amd 1:2024) - pci-dss.md: version header v4.0 → v4.0.1 - pci-dss.md: replace hardcoded "3 years" retention anchor with need-based framing citing Req 3.2.1; PCI DSS sets no fixed period - SKILL.md: framework table Req 3.4 → Req 3.5.1 (Sensitive Data in Logs) - SKILL.md: framework table Req 3.1 → Req 3.2.1 (Retention & Erasure) - SKILL.md: Extended References pci-dss row removes "3-year retention" → "need-based retention (Req 3.2.1)" - SKILL.md: sources row PCI DSS v4.0 → v4.0.1 - hipaa.md: reframe 6-year retention as §164.530(j) documentation retention; clarify HIPAA sets no federal PHI retention period (state law governs); label 6 years as conservative default for required docs Co-Authored-By: Claude <noreply@anthropic.com>
July 2026 currency audit: PCI DSS v4.0.1 (v4.0 retired, numbering unchanged, no fixed retention period); ISO/IEC 27001:2022 + Amd 1:2024 (Annex A unchanged); HIPAA 6-year clarified as §164.530(j) documentation retention (not PHI retention); Security Rule NPRM Jan 2025 still proposed. Watch items added for HIPAA final rule, NIST SSDF v1.2 draft, GDPR Digital Omnibus Art. 30(5), and OWASP ASVS 5.0.1.
| // v3.x agent-teams removal: namespaced name for cleanup of installed devflow:agent-teams skill | ||
| 'devflow:agent-teams', | ||
| // v2.x compliance plugin: bare name for pre-namespace installs | ||
| 'compliance', |
There was a problem hiding this comment.
not sure I understand why this is not prefixed like devflow:compliance, why? as far as I remember this is important for everything to work correctly, for example shadowing functionality and proper name spaced installation etc.
There was a problem hiding this comment.
Bare is deliberate here — this list is a deletion manifest for stale paths, not install names, and the prefix would invert its meaning:
- Init's legacy cleanup rm's
~/.claude/skills/<entry>verbatim, no prefix applied (init.ts:1027). Barecompliance→ the pre-namespace path~/.claude/skills/compliance/(a no-op today, disjoint from the live install). devflow:compliancehere would point that same cleanup at~/.claude/skills/devflow:compliance/— the live install dir — and delete the skill on everydevflow init(cleanup runs after install). Two tests pin this:skill-namespace.test.ts:83requires the bare form, andplugins.test.ts:312("no namespaced legacy entry matches an active install path") fails on the prefixed form for exactly this reason.- Shadowing is unaffected either way: shadow sources live under
~/.devflow/skills/{bare-name}/(bare by convention,installer.ts:365), and legacy cleanup never touches~/.devflow/at all. Namespaced installation is applied by the installer (prefixSkillName→~/.claude/skills/devflow:compliance/), independent of this list.
The old comment ("bare name for pre-namespace installs") was the confusing part — compliance never shipped pre-namespace (namespacing landed 2026-03-30; compliance was born 2026-07-18), so the entry exists only to satisfy the skill-namespace.test.ts:83 invariant. Reworded the comment to state the actual mechanism in 8bc8be8.
One genuine follow-up this surfaced (out of scope here): for skills born after namespacing, these bare entries have zero migration value but make init's unguarded fs.rm willing to delete a same-named foreign skill dir (compliance is a generic name). Fixing that means changing the skill-namespace.test.ts:83 invariant to a frozen pre-namespace list and/or adding a devflow-marker guard to the cleanup — happy to do that as a follow-up PR if you want it.
There was a problem hiding this comment.
Follow-up: we took this one step further in 37f0712. You were right that no pre-namespace compliance install ever existed — the only thing forcing the entry was the test invariant ("every current skill must have a bare legacy entry"), which over-applied to skills born after namespacing. The invariant is now frozen to the 39 skills that actually existed before dcecda3 (2026-03-30), with an inverse guard: a bare legacy entry for any post-namespace skill now fails the test (no migration value, only foreign-dir deletion risk). That pruned 30 vestigial bare entries (including compliance); all devflow:-prefixed entries and all genuine pre-namespace names (including old constituent names like git-safety/architecture-patterns) are untouched. Full suite green: 1,812 tests, tsc clean.
PR Comments SummaryInline Comments Created (≥80% confidence)
Lower-Confidence Suggestions (60-79%)These are worth considering but not blocking:
Items Not in Diff (Cannot Comment Inline)docs/reference/release-process.md:111 — Plugin count left stale by this PR (Confidence: 90%, MEDIUM Should Fix)
Category Breakdown
Review Scores Summary
Status: READY FOR MERGEAll blocking ≥80% confidence findings have been documented via inline comments. The PR is architecturally sound, regression-clean, and backward-compatible. Address the inline comments before merge; lower-confidence suggestions are optional refinements. Comments created by Claude Code review automation |
- SKILL.md frontmatter: add ISO 27001 and SOX to the 4-framework list - reviewer.md: trim compliance row to activation condition only (contract prose lives in the skill) - docs/commands.md: add UI Design to conditionally-active reviewer list (11 total, matching code-review.mds) - release-process.md: 22 → 23 plugin.json files (devflow-compliance is the 23rd plugin) - init.ts plugin hint: add ISO 27001 and SOX to devflow-compliance hint Co-Authored-By: Claude <noreply@anthropic.com>
…late ISSUE-02: In the alignment-fix Coder template, COMPLIANCE appeared before SCOPE, inconsistent with the structurally-parallel validation-fix and qa-fix templates which both order SCOPE → COMPLIANCE → CREATE_PR. Move the COMPLIANCE line to sit after SCOPE in the alignment-fix block. ISSUE-15: The primary Coder templates (5) place COMPLIANCE between DECISIONS_CONTEXT and PR_DESCRIPTION_GUIDANCE — fields absent from fix templates — making a single slot across all 8 templates unachievable as a pure line-move. ISSUE-02 alone satisfies this issue; primary-vs-fix slot difference is inherent to the surrounding field structure. Co-Authored-By: Claude <noreply@anthropic.com>
ISSUE-10 (build-mds.test.ts §14): assert COMPLIANCE_ENABLED appears in compiled code-review, plan, and implement outputs — a forgotten compliance_gate() call site compiles cleanly but silently drops the gate. ISSUE-11 (build.test.ts): guard that no shared/agents/*.md frontmatter skills: block lists devflow:compliance; parse only YAML frontmatter, not body text, to avoid false hits on body instructions (avoids PF-002). ISSUE-13 (build.test.ts): drop redundant (plugin.rules ?? []) registry guard — PluginDefinition.rules is a required string[] field, never nullish. ISSUE-14 (build.test.ts): collapse the two identical skills/rules sync tests to a single it.each — removes ~15 lines of duplicated manifest-read scaffolding; failure messages retain manifest vs registry labeling. Co-Authored-By: Claude <noreply@anthropic.com>
If writeFileSync to the sibling .tmp succeeds but renameSync throws,
the .tmp was previously left on disk. Wrap renameSync in a try/catch
that calls rmSync({ force: true }) on the error path and re-throws,
so no orphan file lingers. The atomic tmp+rename semantics are fully
preserved (avoids PF-011).
Co-Authored-By: Claude <noreply@anthropic.com>
…s parser
`line.length > 0 && !/^\s/.test(line)` → `/^\S/.test(line)`.
The two forms are equivalent: `/^\S/.test('')` is already false for empty
strings, making the explicit length check redundant.
The 'compliance' entry comment said "for pre-namespace installs" but compliance never shipped before namespacing landed. The real reason is mechanical: init's legacy cleanup rm's ~/.claude/skills/<entry> verbatim with no prefix, so a bare entry is a no-op today while a 'devflow:' prefix would target and delete the live install dir on every init. Co-Authored-By: Claude <noreply@anthropic.com>
Skills born after the devflow: namespace was introduced (dcecda3, 2026-03-30) never had bare ~/.claude/skills/<name> installs, so bare entries in LEGACY_SKILL_NAMES have zero migration value and silently risk deleting same-named foreign skill directories on every devflow init. Pruned from LEGACY_SKILLS_V2 (17 entries born 2026-03-31 to 2026-04-05): git, software-design, boundary-validation, testing, architecture, performance, security, ui-design, complexity, consistency, regression, database, dependencies, documentation, qa, patterns, quality-gates Pruned from LEGACY_SKILLS_V2X (13 entries born 2026-04-08 to 2026-07-18): gap-analysis, design-review (2026-04-08), apply-decisions (2026-05-04), feature-knowledge, apply-feature-knowledge (2026-05-06), research-codebase, research-external, research-market, research-competitor, research-technology, dependency-research (2026-05-10), reliability (2026-05-12), compliance (2026-07-18) Frozen the invariant in tests/skill-namespace.test.ts with: PRE_NAMESPACE_SKILLS: frozen historical set (dcecda3^, 39 skills) Assertion A: current pre-namespace skills must have a bare legacy entry Assertion B (new inverse guard): current post-namespace skills must not Added skill-namespace.test.ts to skill-references.test.ts ALLOWLIST_FILES since PRE_NAMESPACE_SKILLS intentionally contains historical old-skill names. Applies ADR-003 (clean end-state — no tombstone comments or guards). Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Adds the
devflow-complianceoptional plugin, delivering code-level regulatory compliance patterns across GDPR, HIPAA, PCI DSS, SOC 2, ISO 27001, and SOX — integrated into the code-review, plan, and implement pipelines. The plugin is entirely opt-in: without installation, zero compliance surface is exposed and no warnings are emitted.Changes
Phase 1 — Plugin Foundation (commit
0f3ce88)shared/rules/compliance.md— Global rule (paths: []): 6 data-control directives enforced on every prompt when the plugin is installedshared/skills/compliance/SKILL.md— 137-line skill with Iron Law, 6 control categories (access, encryption, audit, retention/erasure, boundary, IaC), severity/framework mapping tablesshared/skills/compliance/references/— 8 reference files: GDPR, HIPAA, PCI DSS, SOC 2, ISO 27001, SOX, detection patterns, sources (200+ regulatory citations)plugins/devflow-compliance/.claude-plugin/plugin.json— Plugin manifest v1.8.3;skills: ['compliance'],rules: ['compliance'],optional: truesrc/cli/plugins.ts— DEVFLOW_PLUGINS entry;'compliance'added to LEGACY_SKILLS_V2Xsrc/cli/commands/init.ts— Plugin hint + Step 2 label update + advanced rules note.claude-plugin/marketplace.json— Marketplace entryPhase 2 — Workflow Integration (commit
afb5271)commands/_partials/_compliance.mds— New installed-gate partial: scope-aware manifest check → skill asset verify → rule-file fallback → CLAUDE.md opt-out. ≤3 file reads, no subprocess, no LLM call, silent (applies ADR-007)commands/code-review.mds— Import +{compliance_gate()}in Phase 1; compliance row in REVIEWER_LIST table; reviewer count bounded ≤20 per worktreecommands/plan.mds— Import +{compliance_gate()}in Phase 5 Gap Analysis; 4→5 Designer agents whenCOMPLIANCE_ENABLED; compliance focus row in gap-analysis tablecommands/implement.mds— Import +{compliance_gate()}in Phase 1 Setup;COMPLIANCEfield added to ALL Coder prompt templates (initial + validation-fix + alignment-fix + qa-fix loops) for consistent guidance; absent = no-op (backward-compatible with /resolve and /dynamic-build)shared/agents/reviewer.md—compliancefocus row + conditional activation note with clean-report contractshared/agents/designer.md—complianceadded to gap-analysis focus list in description and Modes tableshared/agents/synthesizer.md— Merge-don't-boost note in both design and review modes: a compliance+security co-located finding is one gap seen by two lenses, not multi-agent corroborationshared/agents/coder.md—COMPLIANCEinput documented; Step 2 body-instructsSkill(skill="devflow:compliance")whenCOMPLIANCE: enabledAND regulated surface detected; never in frontmatter (avoids PF-002 re-entrancy guard)shared/agents/triager.md— One-line compliance disposition hint: default FIX_SEPARATE/TECH_DEBT unless code-localshared/skills/gap-analysis/SKILL.md— §7 Compliance: detection patterns for regulatory gaps security doesn't cover (retention/erasure, audit-trail completeness, segregation of duties, IaC exposure)tests/build-mds.test.ts— Partial count assertion 9→10 (RED→GREEN with new partial)tests/build.test.ts— Generic plugin.json↔DEVFLOW_PLUGINS skills+rules sync test for all 23 plugins (closes the unguarded manual-sync pair)Breaking Changes
None. The plugin is optional. Without installation:
COMPLIANCE_ENABLED=false, no compliance reviewer/designer/prompt field appears, no warnings emitted (AC-3, AC-13).Reviewer Focus Areas
commands/_partials/_compliance.mds— Gate logic correctness: scope-aware manifest → asset verify → fallback → opt-out; verify AC-11, AC-13, AC-15shared/agents/coder.md— PF-002 guard: body-instructedSkill(skill="devflow:compliance")must NOT appear in frontmatterskills:list (verify the two are disjoint)commands/implement.mds—COMPLIANCEfield coverage: all 6 Coder prompt templates (SINGLE, SEQ phase 1, SEQ phase 2+, PARALLEL × 2, plus 3 fix-loop spawns) should carry the fieldtests/build.test.ts— New sync test: verifiesplugin.jsonskills+rules arrays matchDEVFLOW_PLUGINSfor every plugin; confirm it would catch a real mismatch (drift detection)