Subchapter 25.45
references/phases/generate/generate.mdMarkdown13 KBView on GitHub
Emit the Terraform, the scripts, the docs, and the report. This phase runs under
_exec: { _agent: rw } with _interactive: false — the work is bulky, file-only,
and self-contained, so it runs in an isolated sub-agent while the gates, the state
transition, and the HANDOFF_OK stay in the main window.
The Terraform validation, the tf-best-practices policy gate, and the
validation-report.json write also stay in the main window — the dispatched rw
worker emits terraform/ only; it cannot invoke skills or run terraform/python.
This mirrors gcp-to-aws’s generate.md, which owns validation inline in its own main
window and passes only the terraform DIR to the skill (the caller owns the report). See
§ “Step: Run the phase” step 4.
The run_mode precondition above is an _assert. CI binds _assert bodies but
never evaluates them — the string is checked for being a non-empty value in the
right list, and nothing more. So the consent rule depends entirely on the interpreter
honoring the prose. A future reader should not assume this is enforced.
The DSL has no vocabulary for an opt-in phase, and inventing one for a single case
would be worse than this: the alternative is a mechanical check that the state file
carries a specific value, which the grammar does not have a check kind for.
estimate-assemble.md owns writing run_mode, and it writes
decide_and_execute before this phase loads, so a session that dies mid-Generate
resumes as an Execute run.
The _check_phase_completed: workshop precondition is the other half of the ordering:
the workshop sidebar declares _gates: generate, and a declined sidebar counts as
resolved.
Emit in tier order — network, identity, and secrets first, then data, then compute, then edge. That is the same tiering the clusters carry, which is why the tiering replaced topological depth: Generate’s sequencing is what the ordering is for.
The three artifact fragments and the assembler are wired AND their emitters are
implemented: generate-artifacts-infra.md emits Terraform, generate-artifacts-docs.md
the docs, generate-artifacts-report.md the stakeholder report (rendered from
references/shared/report-decision-core.md, full mode, validated by
scripts/validate-migration-report.py), and generate-artifacts-ai.md the AI-migration
pack when an AI design exists. The phase runs infra, AI-only (app-code-only), or both —
_produces and the pre/postconditions are conditional on which track exists. Read each
fragment’s own ## Status, not this line, for its emitter detail.
| Lands in | What |
|---|---|
| step 6 | The Terraform, script, doc, and report emitters |
| step 6 | The report shape — cluster-level rationale first, rows to an appendix |
| step 6 | The AI handoff summary, when the handoff offer is accepted |
Steps 2–3 are the phase’s WORK and are dispatched to the file-only rw worker. Step 4
and step 5 run in the MAIN window — the worker cannot invoke skills or run
terraform/python.
run_mode._trigger holds. (worker)generate-assemble.md. (worker — emits terraform/, the docs, the report, and
generation-warnings.json; it does NOT validate or write validation-report.json.)_postconditions. This MUST run in the main
window because the rw worker cannot invoke skills or run terraform/python. This
phase is the caller of the tf-best-practices validation protocol, exactly as
gcp-to-aws’s generate.md owns validation inline in its main window:
tf-best-practices skill for the post-writing validation context, passing
$MIGRATION_DIR/terraform — the DIR only (the caller owns the report, just as gcp
passes only the terraform DIR to the skill). Treat it as a black box: run the
fmt/init/validate stages where available, and the zero-dependency policy checker,
which runs regardless of the offline path (a provider-registry outage skips
terraform validate but never the policy gate).violations[] sites (budget 3), then run the
retry/skip/abort prompt.$MIGRATION_DIR/validation-report.json — the two
segments joined by a single / (slash-joined). Merge the skill’s policy verdict into
THAT file as policy_status (+ policy_violations on failure), recorded independently
of the fmt/init/validate outcome so a policy failure is never masked by
passed_degraded_offline. Never write a separate policy-verdict.json, and never
pin the skill’s raw verdict path as the report.POLICY_FAIL the user does not skip/abort sets status: policy_failed
and blocks completion (the _postconditions _assert)._postconditions. On all-pass emit HANDOFF_OK and advance to
complete; on any failure emit GATE_FAIL and stop.