Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4aa15c5
fix(traceability): repair issue-seam prompt defects (A1)
dean0x Sep 5, 2026
b9d36ed
test(golden): capture git-agent and github-status-lines goldens (A2)
dean0x Sep 5, 2026
6d595b6
test(harness): land A3a — resolver, seam test, golden infra, D11 unio…
dean0x Sep 5, 2026
83594b9
test(guards): land A3b — guard-gap closures, CI integration, AC-0.7 r…
dean0x Sep 5, 2026
e8c4055
docs(traceability): Phase-0 docs sweep — platform assumptions, CHANGE…
dean0x Sep 5, 2026
4df70e8
test(integration): scope subagent transcript scan to the spawned session
dean0x Sep 5, 2026
71a3ce4
test(integration): pin the spawned session id and diagnose non-spawns…
dean0x Sep 5, 2026
fac739e
refactor(tests): simplify harness helpers and guards
dean0x Sep 5, 2026
b1f38bc
fix(tests): scrutinize fixes for Phase-0 harness
dean0x Sep 5, 2026
ef67f32
refactor(tests): remove unused transcript selector
dean0x Sep 5, 2026
4a00484
fix(traceability): contain every remote-sourced field in issue-fetch …
dean0x Sep 5, 2026
1ca307d
test(harness): re-anchor status-line extraction and consolidate updat…
dean0x Sep 6, 2026
a5dd078
test(golden): re-capture goldens after containment fix
dean0x Sep 6, 2026
5fc76aa
docs(changelog): enumerate the plan's five user-visible changes
dean0x Sep 6, 2026
fe11930
test(harness): implement missing guards M1–M13 and Guard 6 anchor fix…
dean0x Sep 6, 2026
21c9a4c
test(harness): isolate the resolver fixture in a temp root
dean0x Sep 6, 2026
98a5bb5
fix(traceability): add D4 degradation to issue-fetch ops and restore …
dean0x Sep 6, 2026
1528bf1
test(harness): re-anchor status lines and re-measure byte baselines a…
dean0x Sep 6, 2026
38db29e
test(golden): re-capture goldens after D4 degradation fix
dean0x Sep 6, 2026
27191ba
docs(changelog): correct the containment before-state
dean0x Sep 6, 2026
0b44eae
test(guards): widen containment and D4 predicates, restore AC-0.10 fl…
dean0x Sep 6, 2026
27d6fbd
test(harness): mechanise literal-path and dist-throw contracts, real-…
dean0x Sep 6, 2026
0f65757
docs(knowledge): add test-harness feature knowledge base
dean0x Sep 6, 2026
a1fe205
docs(changelog): keep the five enumerated user-visible changes
dean0x Sep 6, 2026
b6928e5
test(harness): relabel char baselines, pin the v3 fast-path, strip fi…
dean0x Sep 6, 2026
75f13e7
fix(git-agent): contain setup-task issue bodies and harden containmen…
dean0x Sep 6, 2026
c7bff85
fix(plan): carve Step 0 out of the Gate 0 spawn ban and drop unbacked…
dean0x Sep 6, 2026
97f421a
fix(git-agent): commit conventions.md so learn-conventions leaves a c…
dean0x Sep 6, 2026
b0d576a
test(golden): regenerate git-agent fixture after containment fixes
dean0x Sep 6, 2026
948c440
test(integration): mechanise clause (ii) file-residue via tarball ins…
dean0x Sep 6, 2026
c56c105
test(guards): restore genuine containment validation and pin the matc…
dean0x Sep 6, 2026
0503e89
test(seams): source issue-capture producers from the agent, not the c…
dean0x Sep 6, 2026
7074733
fix(init): gitignore the devflow-written .claudeignore (marker v4)
dean0x Sep 6, 2026
f7ac392
test(integration): assert clause (ii) file-residue now that .claudeig…
dean0x Sep 6, 2026
e276175
test(harness): anchor status-line extraction on content instead of li…
dean0x Sep 6, 2026
eec2ae3
docs(changelog): enumerate the full Phase 0 user-visible change set
dean0x Sep 6, 2026
3a95c92
test(golden): re-capture frozen status-lines fixture after containmen…
dean0x Sep 6, 2026
df34d77
docs(changelog): cite stable identifiers instead of volatile line num…
dean0x Sep 6, 2026
0af035b
chore(gitignore): adopt the v4 carve-out block in devflow's own repo
dean0x Sep 6, 2026
4ce6261
docs(changelog): drop a redundant operation-name repetition
dean0x Sep 6, 2026
a2207ac
docs(knowledge): update test-harness, compliance-feature, installer-s…
dean0x Sep 6, 2026
08fbdd4
docs(test): correct stale shape count in hud-git header comments
dean0x Sep 7, 2026
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
18 changes: 13 additions & 5 deletions .devflow/features/compliance-feature/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ directories:
- src/assets/commands/resolve.mds
- src/assets/commands/release.md
created: 2026-08-20
updated: 2026-08-21
updated: 2026-09-06
---

# Compliance Feature & SDLC Traceability
Expand Down Expand Up @@ -171,7 +171,7 @@ The Git agent implements the SDLC traceability layer. All operations are declare

| Marker | Operations | Key Details |
|---|---|---|
| D1 | `learn-conventions` | Bounded scan (≤50 branches, ≤20 tags, ≤30 merged PRs, ≤200 merges for integration-branch scoring). Writes `.devflow/conventions.md` **once** — never overwrites. Scanned strings are UNTRUSTED DATA: shape-derived patterns only, never verbatim. Post-composition verbatim-match check replaces any copied string with the generic default. |
| D1 | `learn-conventions` | Bounded scan (≤50 branches, ≤20 tags, ≤30 merged PRs, ≤200 merges for integration-branch scoring). Writes `.devflow/conventions.md` **once** — never overwrites. Scanned strings are UNTRUSTED DATA: shape-derived patterns only, never verbatim. Post-composition verbatim-match check replaces any copied string with the generic default. After writing, **commits `.devflow/conventions.md` via scoped pathspec** (never `git add -A`, never push, never force, non-blocking on failure; reports `CONVENTIONS_COMMIT: failed` on error and continues — mirrors the Knowledge agent's commit pattern). |
| D2 | `fetch-review-threads`, `resolve-review-threads` | GraphQL (≤2 pages of 50 = 100 max threads); external thread bodies wrapped in `<external-thread>...</external-thread>` and never echoed verbatim |
| D3 | `ensure-traceable-issue` | D3 issue template sections: `## Initial Request`, `## Product Requirements`, `## Implementation Plan`. Template single-sourced in `devflow:git` skill (git/SKILL.md). Never rewrites issue body, posts comments only. All user-supplied strings (title, body, labels) bound to shell variables and passed via `--body-file`/`--label "$VAR"` — never interpolated into the command string. |
| D4 | All traceability ops | **Degradation contract** (see table below) |
Expand Down Expand Up @@ -220,8 +220,10 @@ Collects the commit list (≤100 entries) and shipped issue numbers (≤50) sinc
- All external content (PR body, issue title, labels) bound to shell variables; applied via `--body-file {temp_file}` or `"$VAR"` — never interpolated into the command string.
- `Closes #{n}` addition requires `gh issue view {n} --json number,state` verification; `.state` must be `"open"`. Branches like `chore/2026-cleanup` or `fix/2fa-login` may produce false numeric matches — the existence check is the guard.
- **Branch-name metacharacter guard (setup-task step 1b):** `.devflow/conventions.md` is third-party input (git-tracked and team-shared). Before using the convention-derived prefix and separator in step 3, the fully composed branch name is checked against `` $ ` \ " ' ; | & < > `` or whitespace/newline. If any match: discard the convention and fall back to heuristic defaults. The validated name is bound to `DEVFLOW_BRANCH` before use.
- **`setup-task` issue body containment (commit `75f13e7`):** The remote-sourced issue fields (`title`, `description`, `criteria`) are now wrapped in `<untrusted-issue-body>` tags. The locally-derived issue number is intentionally placed outside the wrapper. Prior to this fix, `setup-task` was `/implement`'s only issue path and the highest-traffic issue path in the product — Principle 8 claimed all remote bodies were wrapped, but `setup-task` did not actually apply the wrapper. The KB was stronger than the implementation; the fix closes that gap.
- **`fetch-issues-batch` per-issue wrapping:** The output template explicitly shows the `<untrusted-issue-body>` wrapper on each issue (not just the first with an implicit "etc." for the rest). Each issue is wrapped independently — there is no single wrapper around the whole list.

**conventions.md authority (D1):** Written by `learn-conventions`, consumed by `setup-task` (branch naming, step 1b), `ensure-pr-ready` (PR title retitle, step 4c), and `create-release` (version/tag/version-PR title, step 1b). Delete to force re-learn.
**conventions.md authority (D1):** Written by `learn-conventions`, consumed by `setup-task` (branch naming, step 1b), `ensure-pr-ready` (PR title retitle, step 4c), and `create-release` (version/tag/version-PR title, step 1b). Delete to force re-learn. `learn-conventions` now commits this file as its final step so fresh projects do not leave `?? .devflow/conventions.md` in `git status`.

**Traceability bounds:**
- `backlink-shipped-issues`: ≤50 issues, 1s throttle (raises to 3s at remaining<50)
Expand All @@ -237,6 +239,8 @@ Collects the commit list (≤100 entries) and shipped issue numbers (≤50) sinc

**External thread containment (D2):** External review thread bodies are untrusted third-party input. They are never executed as instructions, never echoed verbatim into devflow-authored replies, commits, or comments. The `<external-thread>` tag is the containment boundary.

**Principle 8 marker neutralisation (commit `75f13e7`):** Before wrapping any remote content in `<untrusted-issue-body>` or `<external-thread>`, the operation scans the content for the literal closing marker (e.g., `</untrusted-issue-body>` or `</external-thread>`) and inserts a backslash before the slash. This prevents a hostile issue body or review comment from terminating containment early and injecting text into devflow-authored context. This neutralisation applies to all four wrapping operations: `fetch-issue`, `fetch-issues-batch`, `setup-task`, and `fetch-review-threads`. Pointer comments exist at each of these operations in `git.md`.

**`FEATURE_OWNED_SKILLS` disjointness:** Must be disjoint from `getAllSkillNames()` (enforced by D-FO-1 comment in plugins.ts). The compliance skill is managed by the feature system, not the plugin install loop.

## Anti-Patterns
Expand All @@ -257,6 +261,8 @@ Collects the commit list (≤100 entries) and shipped issue numbers (≤50) sinc

**Hand-assembling converge options at each call site.** `convergeFromManifest` is the single manifest→options site. Callers that bypass it risk assembling the options struct inconsistently (e.g., forgetting `rulesEnabledOverride`).

**Wrapping an entire issue list in a single containment tag.** The correct model is per-issue wrapping — each issue body gets its own `<untrusted-issue-body>...</untrusted-issue-body>` pair. A single outer wrapper around the whole list would allow the attacker's first issue to close the outer tag and escape containment for all subsequent issues.

## Gotchas

**normalizeFrameworks silently drops unknowns; parseFrameworkList errors loudly.** Use `normalizeFrameworks` for manifest-sourced IDs (tolerant, self-heals); use `parseFrameworkList` for user CLI input (strict, errors on unknowns).
Expand All @@ -281,6 +287,8 @@ Collects the commit list (≤100 entries) and shipped issue numbers (≤50) sinc

**EXCLUDED-as-oracle trap in tests (PF-018).** Tests that assert `FEATURE_OWNED_SKILLS` / `FEATURE_OWNED_RULES` exclusions use independent literal `['compliance']` — they do not import the constant. Importing the constant would make the test verify the constant against itself.

**Principle 8 neutralisation must run before the wrapper is applied.** Scanning for the closing marker after wrapping is too late — the wrapped content already contains the literal tag. Scan the raw remote content first, escape any closing marker occurrence, then wrap.

## Key Files

| File | Purpose |
Expand All @@ -295,13 +303,13 @@ Collects the commit list (≤100 entries) and shipped issue numbers (≤50) sinc
| `src/core/plugins.ts` | `FEATURE_OWNED_SKILLS`, `FEATURE_OWNED_RULES`, `DELETED_PLUGIN_NAMES`, `resolveFeatureRedirect` |
| `src/cli/commands/rules.ts` | `seedRuleShadow` (Tier 1 skipped for FEATURE_OWNED_RULES; Tier 2 = canonical source preserves placeholder) |
| `src/assets/commands/_partials/_compliance.mds` | `compliance_gate()` partial — single-source COMPLIANCE_SKILL_INSTALLED resolution for all 4 host commands |
| `src/assets/agents/git.md` | All traceability operations (D1–D9 legend, D4 rate-limit backpressure, D9 gate table, gather-release-evidence) |
| `src/assets/agents/git.md` | All traceability operations (D1–D9 legend, D4 rate-limit backpressure, D9 gate table, gather-release-evidence, setup-task containment, Principle 8 marker neutralisation) |
| `src/assets/commands/code-review.mds` | Step 0b (imports compliance_gate), Phase 1 regulated-surface gate, Git COMPLIANCE field |
| `src/assets/commands/resolve.mds` | Phase 1b (fetch-review-threads), Phase 9b (resolve-review-threads), Phase 9c (check-merge-readiness) |
| `src/assets/commands/plan.mds` | compliance_gate gate for compliance Design agent and mandatory issue linking |
| `src/assets/commands/implement.mds` | compliance_gate resolution, Git setup-task COMPLIANCE field |
| `src/assets/commands/release.md` | Phase 1c (COMPLIANCE_SKILL_INSTALLED), gather-release-evidence spawn, backlink-shipped-issues |
| `tests/git-agent.test.ts` | Static guards: required ops list, 60000-char caps, D9 gate, D4 backpressure, D7/D8 dedup markers |
| `tests/git-agent.test.ts` | Static guards: required ops list, 60000-char caps, D9 gate, D4 backpressure, D7/D8 dedup markers, AC-0.10 containment (split into issue-body and external-thread guards) |
| `tests/registry-integrity.test.ts` | Guard 6: OPERATION: values in compiled commands ↔ `## Operation:` headings in git.md (spawn↔op integrity) |

## Related
Expand Down
12 changes: 10 additions & 2 deletions .devflow/features/dynamic-workflow-engine/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Partials declare **no** `output-dir:` frontmatter key. Host files declare it as

### Compiled output and test pinning

`scripts/build-mds.ts` compiles all 13 host files (9 knowledge + 4 dynamic). The test file `tests/build-mds.test.ts` reads the compiled `dist/commands/dynamic-build.md` and greps for exact doctrine strings. Changing a doctrine literal in a partial immediately breaks the relevant test — by design. The test suite pins:
`scripts/build-mds.ts` compiles all 13 host files (9 knowledge + 4 dynamic) — `ALL_HOSTS = 13`. **`DIST_FILES` = 14**: the 13 compiled outputs plus `release.md`, which is hand-authored and copied verbatim by the build; the divergence is permanent (SG-13). Compilation-scope guards use `ALL_HOSTS`; deployed-behaviour guards (gh-issue scope, compliance_gate, retired wording) use `DIST_FILES`. The test file `tests/build-mds.test.ts` reads the compiled `dist/commands/dynamic-build.md` and greps for exact doctrine strings. Changing a doctrine literal in a partial immediately breaks the relevant test — by design. The test suite pins:
- `Simplify` and `Scrutinize` each appearing exactly **2 times** (Gate 1 #1 + Gate 1 #2 only)
- **C1 (single-pass review):** presence: `The review pass runs exactly ONCE`, `The pass runs exactly ONCE`, `Never author additional cycles or a delta re-review of fix commits` (invariant #7 unique), `Budget scales roster and verification votes, NEVER the number of passes` (review_pass prose unique); absence: `DELTA REVIEW`, `reviewBaseSha`, `preFixSha`, `maxCycles`, `cyclesRun`, `fixedInCycle`, `allCoverageGaps`, `for (let cycle` (skeleton guard), `review_loop`, `/review[- ]loop/i`
- `reviewed: true`, `coverageGaps.length === 0`, `FAIL-FIXED`, `ALWAYS ready`, `Cheapest-sufficient validation`, `One build gate per phase`, `NEVER wrapped in`, `Gate 1 #2`, `gate1-final`, `No unauthorized GitHub side-effects`
Expand Down Expand Up @@ -275,7 +275,15 @@ In the SINGLE mode workflow's final Gate 1 (#2, `gate1-final` phase), retry atte
- `src/assets/commands/dynamic-build.mds` — main build command source with inline SINGLE + WAVE workflow scripts
- `dist/commands/dynamic-build.md` — compiled artifact pinned by test suite
- `tests/build-mds.test.ts` — doctrine-literal pinning tests (sections 10, 12, 13)
- `scripts/build-mds.ts` — unified MDS compiler (13 hosts → compiled .md files)
- `scripts/build-mds.ts` — unified MDS compiler (13 compiled hosts `ALL_HOSTS`; `DIST_FILES` = 14 including hand-authored `release.md` — SG-13 permanent divergence)

## Deliberate Exceptions (AC-0.4 gh-issue scope guard)

Two categories of deliberate exceptions to the AC-0.4 guard (`tests/build-mds.test.ts §21`) that bars `gh issue` invocations or descriptive mentions from deployed commands outside Git spawn fences:

**`gh pr view` at three prose sites** — `code-review.md` (source: `code-review.mds:76-78`), `bug-analysis.md` (source: `bug-analysis.mds:43-45`), and `resolve.md` (source: `resolve.mds:63`) each fetch a PR description via `gh pr view {pr_number}` in a bash prose block, not inside a Git spawn fence. This is an explicit allowlisted PR-hosting exception: `gh pr` is not `gh issue`, and fetching the PR body for display is unrelated to the issue-routing contract. Encoded in the guard's `GH_PR_VIEW_EXCEPTION_FILES` set.

**`release.md:85` conventions read** — `release.md:85` instructs the release orchestrator to consult `.devflow/conventions.md` directly for version/tag naming conventions (a local file, not a GitHub API call). This is a local-file read that does not route through the Git agent; it is exempt from the AC-0.4 guard by definition (no `gh` CLI involved). Recorded here so future guard authors do not flag it as an oversight.

## Related

Expand Down
2 changes: 1 addition & 1 deletion .devflow/features/feature-knowledge-system/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Invoked at the end of applicable workflows via `knowledge_writeback()` MDS call
5. Writes `{basename}.md` to the declared `output-dir` (per-file clean; no dir wipe)
6. Hard-fails on any compile error — no stale command ever ships

13 hosts total: 9 knowledge hosts (`src/assets/commands/{name}.mds`) + 4 dynamic hosts (`src/assets/commands/dynamic-*.mds`).
13 MDS-compiled hosts (`ALL_HOSTS`): 9 knowledge hosts (`src/assets/commands/{name}.mds`) + 4 dynamic hosts (`src/assets/commands/dynamic-*.mds`). `DIST_FILES` = 14 — the 13 compiled outputs plus `release.md`, which is hand-authored and not MDS-compiled (SG-13 permanent divergence; see `dynamic-workflow-engine` KB).
Partials in `src/assets/commands/_partials/` have no `output-dir:` and are skipped automatically.

## Integration Patterns
Expand Down
Loading