# Phase 03: Constitutional Context Files

## Entry Gate

```bash
devforgeai-validate phase-check ${SYSARCH_ID} --workflow=system-architecture --from=02 --to=03 --project-root=. 2>&1
```

| Exit Code | Action |
|-----------|--------|
| 0 | Proceed to Phase 03 |
| 127 | CLI not installed — proceed without enforcement |
| Other | HALT — previous phase not complete |

---

## Contract

| Attribute | Value |
|-----------|-------|
| **PURPOSE** | Emit the project **constitution**: the 5 immutable context `.md` files, the generated `source-tree/` folder, their 5 `.ai.md` companions, and `test-plan.ai.yaml`. These files are THE LAW — every downstream DevForgeAI agent enforces them. |
| **REFERENCES** | The 5 context-file templates in `.claude/skills/spec-driven-system-architecture/assets/context-templates/` (source-tree generated by `devforgeai-validate generate-source-tree` — ADR-071); this skill's `references/system-architecture-output.schema.json` |
| **SUBAGENTS** | `ai-rule-extractor` (×5, one per `.ai.md` companion parent); `test-plan-architect` (×1); `tech-stack-detector` (×1, `--extract-test-patterns` mode) |
| **STEP COUNT** | 5 mandatory steps |

## Phase Exit Criteria

Before this phase can complete, ALL of the following MUST be true:

- [ ] All 5 templated context `.md` files exist in `devforgeai/specs/context/`, non-empty, no `TODO`/`TBD`/`[FILL IN]` placeholders
- [ ] The `source-tree/` folder exists at `devforgeai/specs/context/source-tree/` with at minimum `_manifest.json` and `tree.json` (ADR-071)
- [ ] All 5 `.ai.md` companions generated and verified on disk (source-tree excluded — ADR-071)
- [ ] `test-plan.ai.yaml` generated and verified on disk
- [ ] Every technology choice in `tech-stack.md` is grounded in the PM plan or an explicit user decision (Critical Rule 1)

**IF any criterion is unmet: HALT. Do NOT proceed to Phase 04.**

---

## Reference Loading [MANDATORY]

```
Read(file_path=".claude/skills/spec-driven-system-architecture/assets/context-templates/tech-stack.md")
Read(file_path=".claude/skills/spec-driven-system-architecture/assets/context-templates/dependencies.md")
Read(file_path=".claude/skills/spec-driven-system-architecture/assets/context-templates/coding-standards.md")
Read(file_path=".claude/skills/spec-driven-system-architecture/assets/context-templates/architecture-constraints.md")
Read(file_path=".claude/skills/spec-driven-system-architecture/assets/context-templates/anti-patterns.md")
```

These templates are the canonical structure for the 5 templated context files
(source-tree is generated separately by the CLI in Step 3.1b — ADR-071) — reused
rather than duplicated. IF any Read fails: HALT — "Phase 03 context-file
templates not loaded."

Do NOT rely on memory of previous reads. Load fresh every time this phase executes.

---

## Context-File Write Protection — Note

The 5 context `.md` files, the `source-tree/` folder, and `test-plan.ai.yaml`
(7 constitutional artifacts total) are immutable. In a project carrying the
`pre-context-file-guard.sh` hook, `Write`/`Edit` to these paths is blocked with
`exit 2`. Generating the constitution for the first time is
the sanctioned exception: scope the bypass to **one tool invocation at a time** —
`env DEVFORGEAI_ALLOW_CONTEXT_EDIT=1 <write>` — never `export` it session-wide.
IF a write is blocked and the per-invocation bypass is unavailable: HALT and
AskUserQuestion (CLAUDE.md HALT trigger #11).

---

## Mandatory Steps

### Step 3.1: Generate the 5 Templated Context `.md` Files

**EXECUTE:**

For each context file, populate the loaded template from the PM plan (Phase 01
checkpoint) and the discovery results (Phase 02 checkpoint):

| File | Primary inputs |
|------|----------------|
| `tech-stack.md` | `architecture_style`, `tech_inventory`, PM-plan technical `constraints`, NFR-implied technology |
| `dependencies.md` | `tech_inventory`, framework ecosystems, PM-plan integrations |
| `coding-standards.md` | language conventions, `success_criteria` quality bars |
| `architecture-constraints.md` | `architecture_style`, `reconciled_constraints`, system NFRs |
| `anti-patterns.md` | language/framework anti-patterns, constraints that forbid specific practices |

```
FOR each of the 5 files:
  Write(file_path="devforgeai/specs/context/<file>", content=<populated template>)
```

Every locked technology decision MUST cite its grounding (PM-plan field or a
recorded user decision). A technology not grounded in the PM plan or an explicit
user choice → HALT and AskUserQuestion (Critical Rule 1).

**VERIFY:**
- `Glob(pattern="devforgeai/specs/context/*.md")` returns ≥ 5 files
- Each file is non-empty and contains no `TODO` / `TBD` / `[FILL IN]` placeholder
- `tech-stack.md` lists at least one language and one framework/runtime

**RECORD:**
```bash
devforgeai-validate phase-record ${SYSARCH_ID} --workflow=system-architecture --phase=03 --step=3.1 --project-root=. 2>&1
```
```json
{ "phase": "03", "step": "3.1", "context_files_created": ["<5 paths>"] }
```

---

### Step 3.1b: Generate the `source-tree/` Folder

`source-tree/` is a constitutional context artifact and a *folder* of generated,
schema-validated JSON files (ADR-071, ADR-072). It is **never hand-templated** —
it is produced by the `generate-source-tree` CLI from the live repository walk.

**EXECUTE:**

```
Bash("env DEVFORGEAI_ALLOW_CONTEXT_EDIT=1 devforgeai-validate generate-source-tree --root=.")
```

The CLI walks the project root (auto-detected via the `CLAUDE.md` marker if
`--root` is omitted) and writes `devforgeai/specs/context/source-tree/` with at
minimum `_manifest.json`, `tree.json`, `governance.json`, and a `components/`
subdirectory. The `DEVFORGEAI_ALLOW_CONTEXT_EDIT=1` wrap is required because
`pre-context-file-guard.sh` otherwise blocks any Write under
`devforgeai/specs/context/` (scope the variable to this single invocation —
never `export`).

**VERIFY:**
- `Glob(pattern="devforgeai/specs/context/source-tree/_manifest.json")` returns exactly 1 file
- `Glob(pattern="devforgeai/specs/context/source-tree/tree.json")` returns exactly 1 file
- The CLI exited 0
- IF any Glob misses or the CLI exited non-zero: HALT — "Phase 03 Step 3.1b: source-tree generation incomplete."

**RECORD:**
```bash
devforgeai-validate phase-record ${SYSARCH_ID} --workflow=system-architecture --phase=03 --step=3.1b --project-root=. 2>&1
```
```json
{ "step": "3.1b", "source_tree_generated": true,
  "source_tree_path": "devforgeai/specs/context/source-tree/",
  "cli_exit": 0 }
```

---

### Step 3.2: Generate the 5 `.ai.md` Companions

**EXECUTE:**

Companion generation is the hybrid agent + CLI pipeline (ADR-052 / ADR-053).
Spawn 5 parallel `ai-rule-extractor` calls in a single message — one per parent
context file. Source-tree is excluded: the `source-tree/` folder (ADR-071)
IS the AI-optimized artifact, so it has no separate `.ai.md` companion.

```
Task(subagent_type="ai-rule-extractor",
     prompt="Read devforgeai/specs/context/<parent>.md and emit a structured
       fragment listing CRITICAL, HIGH, and MEDIUM severity rules.")
   # ×5: tech-stack, dependencies, coding-standards,
   #     architecture-constraints, anti-patterns
```

Merge the 5 fragments into `devforgeai/workflows/ai-companion-manifest.json`, then
render deterministically:

```
Bash("devforgeai-validate render-ai-companion --all")
```

The CLI validates each fragment against its parent (HALT on a missing CRITICAL
rule) and atomically writes the 5 `.ai.md` files.

**VERIFY:**
- All 5 `ai-rule-extractor` tasks returned a fragment
- `Glob(pattern="devforgeai/specs/context/*.ai.md")` returns ≥ 5 files
- The CLI exited 0

**RECORD:**
```bash
devforgeai-validate phase-record ${SYSARCH_ID} --workflow=system-architecture --phase=03 --step=3.2 --project-root=. 2>&1
```
```json
{ "step": "3.2", "ai_companions_created": ["<5 .ai.md paths>"],
  "render_cli_exit": 0 }
```

---

### Step 3.3: Generate `test-plan.ai.yaml` (subagent-based per ADR-094)

`test-plan.ai.yaml` is the 7th constitutional artifact (ADR-054). It is generated
by a subagent-based pipeline per ADR-094: `test-plan-generator` produces the
YAML payload, `test-plan-reviewer` verdicts it against the constitutional context
files, and (on reviewer escalation) `/advisor` performs a second-tier review.
The orchestrator writes the accepted YAML directly via `Write()` with the
constitutional bypass — no CLI template substitution.

The legacy `test-plan-architect` + `tech-stack-detector --extract-test-patterns`
+ `render-ai-companion` hybrid pipeline is **deprecated as of ADR-094** and stays
in place for back-compat only during the 30-day retirement window; do NOT invoke
it here.

**EXECUTE:**

Issue the generator `Task()` call:
```
Task(subagent_type="test-plan-generator",
     description="Generate test-plan.ai.yaml payload from 6 context files + framework metadata",
     prompt="Read devforgeai/specs/context/ context files plus the project's
       framework-detection metadata files (package.json / requirements.txt /
       *.csproj / go.mod / Cargo.toml / Gemfile / pom.xml / build.gradle —
       whichever exist). Produce a YAML payload conforming to the
       test-plan.ai.yaml.template shape. Every strategic section MUST carry
       _provenance (inferred / user_confirmed / web_fetched). YAML only.")
```

The generator returns a YAML payload as its result. Write it to a temp file the
reviewer can read:
```
Write(file_path="tmp/_framework/test-plan-generator-output.yaml",
      content="<generator result>")
```

Pre-parse the YAML payload to JSON so the reviewer (content-only — no Bash
tool) can perform structural cross-checks via `Read` on the JSON file
(per ADR-094 Decision 3 + ADR-097 PyYAML permission):
```
Bash("devforgeai-validate yaml-to-json tmp/_framework/test-plan-generator-output.yaml --output=tmp/_framework/test-plan-generator-output.json")
```
If `yaml-to-json` exits non-zero, the generator's payload is malformed
YAML — HALT with "test-plan-generator emitted malformed YAML: <stderr
excerpt>"; do NOT invoke the reviewer.

Issue the reviewer `Task()` call against the generator's payload (both the
raw YAML for aspirational-language scan + the parsed JSON for structural
cross-checks):
```
Task(subagent_type="test-plan-reviewer",
     description="Verdict test-plan-generator payload against 6 invariants + behavioral-equivalence",
     prompt="generator_yaml_path: tmp/_framework/test-plan-generator-output.yaml
       generator_json_path: tmp/_framework/test-plan-generator-output.json
       Read the JSON for field-value extraction (6 T5 invariants +
       behavioral-equivalence). Read the YAML only for the aspirational-language
       scan. Also Read the 6 constitutional context files plus the existing
       devforgeai/specs/context/test-plan.ai.yaml (may not exist on first
       generation). Enforce the 6 T5 cross-check invariants AND the T1
       behavioral-equivalence invariants (when prior artifact exists).
       Return verdict JSON: accept / reject_with_findings / escalate_to_advisor.")
```

Branch on the reviewer's verdict:

- **`accept`**: write the generator's payload to the constitutional artifact via
  the ADR-054 bypass. `pre-context-file-guard.sh` is `PreToolUse[Edit|Write]`
  only — it does NOT fire on `PreToolUse[Bash]` — so a Bash heredoc redirect
  with the audit-trail env-var signal is the sanctioned mechanism (matches
  how `render-ai-companion` and `generate-source-tree` legacy CLIs write
  context files):
  ```
  Bash("env DEVFORGEAI_ALLOW_CONTEXT_EDIT=1 cat > devforgeai/specs/context/test-plan.ai.yaml <<'EOF'
  <generator payload>
  EOF
  ")
  ```
  The `env DEVFORGEAI_ALLOW_CONTEXT_EDIT=1` prefix is audit-trail signaling
  (the Bash hook chain does not actually consult it for `pre-context-file-guard.sh`;
  the prefix records intent in `devforgeai/logs/post-edit-write.log`-adjacent
  audit trails). Do NOT use `Write(file_path="devforgeai/specs/context/test-plan.ai.yaml", ...)`
  via the native Write tool — that path triggers `pre-context-file-guard.sh`
  exit 2 and the env-var prefix syntax does not propagate to native Edit/Write
  tool calls (per `[[feedback_hook_settings_session_load]]` and the ADR-081 arc).

- **`reject_with_findings`**: HALT — "test-plan generation rejected by reviewer:
  `<finding count>` violations." Display the Rule-16-compliant findings to the
  maintainer for remediation; do NOT silently retry the generator.

- **`escalate_to_advisor`**: invoke `/advisor` with the reviewer's findings +
  the generator's payload. If advisor returns `accept_with_notes`, proceed with
  the artifact write as in the `accept` branch above (and surface the notes in
  the RECORD). If advisor returns `reject_with_critique`, HALT — "test-plan
  generation rejected by advisor: `<critique>`."

**VERIFY:**
- `test-plan-generator` task returned a non-empty YAML payload
- `Glob(pattern="tmp/_framework/test-plan-generator-output.yaml")` returns 1 file (raw payload)
- `Glob(pattern="tmp/_framework/test-plan-generator-output.json")` returns 1 file (yaml-to-json output)
- `test-plan-reviewer` task returned a verdict JSON with one of the three valid
  values (`accept` / `reject_with_findings` / `escalate_to_advisor`)
- On `accept` or `accept_with_notes` advisor verdict:
  `Glob(pattern="devforgeai/specs/context/test-plan.ai.yaml")` returns exactly 1
  file
- The written artifact contains all 12 top-level sections (5 baseline + 7
  strategic) — verify by re-parsing via `Bash("devforgeai-validate yaml-to-json devforgeai/specs/context/test-plan.ai.yaml --output=tmp/_framework/test-plan-verify.json")` then `Read("tmp/_framework/test-plan-verify.json")` and asserting all 12 top-level keys present
- Every strategic section carries a `_provenance` block
- Aspirational-language scan (`grep -nE "TBD|TODO|varies by|configure as needed|could eventually|should eventually|ideally|nice to have|in the future|FIXME|XXX"` on the written YAML file) returns 0 hits — the reviewer should have caught this, but verify post-write
- IF any of the above fails: HALT — "test-plan artifact incomplete or non-compliant."

**RECORD:**
```bash
devforgeai-validate phase-record ${SYSARCH_ID} --workflow=system-architecture --phase=03 --step=3.3 --project-root=. 2>&1
```
```json
{ "step": "3.3", "test_plan_generated": true,
  "test_plan_path": "devforgeai/specs/context/test-plan.ai.yaml",
  "agents_invoked": ["test-plan-generator", "test-plan-reviewer"],
  "advisor_invoked": false,
  "reviewer_verdict": "accept",
  "first_generation_mode": <true|false>,
  "advisor_notes": null }
```

(If `/advisor` was invoked, set `advisor_invoked: true` and `advisor_notes:
"<notes string>"`.)

---

### Step 3.4: Verify the Constitution Is Complete

**EXECUTE:**
```
Glob(pattern="devforgeai/specs/context/*.md")                         # expect >= 5
Glob(pattern="devforgeai/specs/context/source-tree/_manifest.json")   # expect 1 (ADR-071)
Glob(pattern="devforgeai/specs/context/*.ai.md")                      # expect >= 5
Glob(pattern="devforgeai/specs/context/test-plan.ai.yaml")            # expect 1
```
Assemble the `context_files_generated[]` list (relative paths of all 12
artifacts) for the Phase 07 output contract.

**VERIFY:**
- 5 `.md` + 1 `source-tree/` folder + 5 `.ai.md` + 1 `test-plan.ai.yaml` = 12 artifacts confirmed on disk
- IF any is missing: HALT — "Constitution incomplete; cannot proceed to ADRs."

**RECORD:**
```bash
devforgeai-validate phase-record ${SYSARCH_ID} --workflow=system-architecture --phase=03 --step=3.4 --project-root=. 2>&1
```
```json
checkpoint.phases["03"] = {
  "status": "completed",
  "context_files_generated": ["<all 12 relative paths>"]
}
```

---

## Exit Gate

```bash
devforgeai-validate phase-complete ${SYSARCH_ID} --workflow=system-architecture --phase=03 --checkpoint-passed --project-root=. 2>&1
```

| Exit Code | Action |
|-----------|--------|
| 0 | Phase 03 complete — proceed to Phase 04 |
| 127 | CLI not installed — proceed without enforcement |
| Other | HALT — checkpoint/step validation failed |

---

## Phase Transition Display

```
Display:
  "Phase 03 Complete: Constitutional Context Files"
  "Context files: 5 .md + source-tree/ + 5 .ai.md + test-plan.ai.yaml = 12 artifacts"
  "Proceeding to Phase 04: ADR Creation"
```
