# Wave 6 — Final Qualification and Documentation Sync Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans (this wave is > verification-heavy and benefits from one session holding the whole evidence set). > **Read [`2026-08-15-five-adapter-runtime-remediation-index.md`](2026-08-15-five-adapter-runtime-remediation-index.md) > first.** > **Entry criterion:** Wave 5 complete — build logic extracted with a clean baseline diff. **Goal:** Run every blocking gate, the full activation matrix, and every environment smoke; reconcile generated metadata and documentation with the code; and produce the evidence set that lets each Definition-of-Done checkbox in spec §13 be ticked with a command and its output attached. **Architecture:** Wave 6 adds no capability. It executes, records, and reconciles. Every claim is backed by a command and its output stored under `docs/superpowers/plans/evidence/2026-08-15-wave6-final/`. A checkbox without attached evidence stays unticked, and a gate that could not run is reported as not-run with its reason — never as passing. **Spec:** [`2026-08-15-five-adapter-runtime-remediation-review-design.md`](../specs/2026-08-15-five-adapter-runtime-remediation-review-design.md) (§12 in full, §13, §11 Wave 6) --- ## Global Constraints Inherited from the index. Wave 6 adds: - **Use `superpowers:verification-before-completion` before any completion claim.** Evidence precedes assertion, always. - **A not-run gate is reported as not-run.** Spec HARD-STOP 6 (`AGENTS.md:22`) makes claiming completion without the verification, or without naming why it could not run, a stop condition. - **No conclusion broader than its evidence** (HARD-STOP 7). "The matrix passed" requires the matrix, not a representative lane. - **The wave ends with the LLM Wiki capture** required by `AGENTS.md:79-90`, or with an explicit reported reason it was blocked. --- ## Task 1: Build and architecture gates - [ ] Run and capture each: ```bash cd src ./gradlew clean compileJava compileTestJava --warning-mode=fail --no-daemon --console=plain ./gradlew test --warning-mode=fail --no-daemon --console=plain ./gradlew check --warning-mode=fail --no-daemon --console=plain ./gradlew verifyCleanArchitectureDependencies verifyEnvKeys \ verifyRuntimeModuleMembership verifyPublicPathSnapshot \ verifyDocumentedLeafCount --console=plain ``` - [ ] Confirm `./gradlew wave0RedReport --console=plain --no-daemon` reports an **empty** red set, then delete the `wave0Red` lanes and the aggregate — the characterizations they tracked are now ordinary tests, and a permanent lane for an empty set is a lane that stops being read. ## Task 2: Focused module gates Gradle paths are read from `src/config/architecture/modules.json`, never from memory. - [ ] Run and capture: ```bash cd src ./gradlew :adapter:outbound:persistence-jpa:test --console=plain ./gradlew :adapter:outbound:persistence-mongo:test --console=plain ./gradlew :adapter:outbound:messaging:test --console=plain ./gradlew :adapter:outbound:notification:test --console=plain ./gradlew :adapter:inbound:graphql:test --console=plain ./gradlew :adapter:inbound:graphql:graphqlStableTest \ :app-bootstrap:graphqlRuntimeQualification \ conditionalTransportQualification --console=plain ``` - [ ] Run the messaging platform's Stable facade focused tests and its live-broker lane separately. Record explicitly that ordinary `test` does **not** substitute for the Docker-backed qualification. - [ ] Persistence blocking lanes: ```bash cd src ./gradlew :adapter:outbound:persistence-jpa:jpaPlatformReleaseGate -Pjpa.matrix.versions=16 --console=plain ./gradlew :adapter:outbound:persistence-jpa:jpaPlatformReleaseGate -Pjpa.matrix.versions=17 --console=plain ./gradlew :adapter:outbound:persistence-jpa:jpaPlatformReleaseGate -Pjpa.matrix.versions=18 --console=plain ./gradlew :adapter:outbound:persistence-mongo:mongoStableContractTest \ :adapter:outbound:persistence-mongo:mongoReplicaSetTest \ :adapter:outbound:persistence-mongo:mongoFailoverTest \ :adapter:outbound:persistence-mongo:mongoMigrationTest \ :adapter:outbound:persistence-mongo:mongoCompatibilityTest \ :adapter:outbound:persistence-mongo:mongoSecurityIntegrationTest \ :adapter:outbound:persistence-mongo:mongoPerformanceTest --console=plain ``` - [ ] Confirm Wave 2 Task B5's decision is reflected: either the three lanes exist and run, or their Stable blocking claim is gone from `src/config/mongodb/release-contracts.json`, `docs/mongodb/advanced/sharding.md`, and `scripts/verify-mongodb-advanced.sh`. Attach the `ReleaseManifestTaskExistenceTest` result. ## Task 3: The activation matrix Run each row and capture the resolved activation report, health, exit code, WARN/ERROR count, and the bean/thread inventory. | # | Matrix | Expected | | --- | --- | --- | | 1 | five off | boots with no external infrastructure; health OK; adapter beans, resources, threads, endpoints all zero | | 2 | JPA only | PostgreSQL + Flyway + Hibernate `validate` succeed; no Mongo, GraphQL, broker, or provider | | 3 | Mongo only | replica set, client, topology, security succeed; no JPA entity, repository, or pool | | 4 | Messaging only | broker publish/consume succeeds; with relay off, no database needed | | 5 | Notification + JPA, `INGEST_ONLY` | durable accept on a frozen non-empty versioned route; provider credentials, calls, and workers all zero; after a `SERVING` restart, exactly one delivery on the same route | | 6 | Notification + JPA, `SERVING` | reference provider delivery and receipt succeed | | 7 | GraphQL only | schema endpoint plus security/policy pipeline succeed; no persistence resolver | | 8 | relay on, dependency missing | startup rejects, **naming the exact missing switch or provider** | | 9 | JPA + Mongo | distinct ports succeed; two implementations of one port is a startup rejection, not a `@Primary` pick | | 10 | five on | every dependency and endpoint ready; no silent fallback and no duplicate authority | - [ ] Row 8 must be checked for the *name*, not merely for a failure. A generic "misconfiguration" is a fail. - [ ] Row 9's conflict case must fail; a bean-ordering or `@Primary` resolution is a fail. ## Task 4: Environment and runtime gates - [ ] Compose artifacts, statically then dynamically: ```bash ./scripts/verify-compose-profile-contracts.sh ./scripts/run-compose-runtime-smoke.sh --matrix src/config/runtime/compose-profile-contracts.json ``` - [ ] Confirm the matrix owned every lane: `off-local`, `off-dev`, `off-prod`, each local adapter lane, `shared-infra-local`, `shared-infra-dev`, `prod-smoke`, `all-adapters`. - [ ] Confirm `prod-smoke` actually **started** TLS PostgreSQL, the app, Keycloak, and MinIO and ran both one-shots — a `config`-only pass is a fail. - [ ] Confirm each run stored exit code, active profile, resolved activation report, and WARN/ERROR count as artifacts. - [ ] Confirm no dev or prod lane was made to pass with a local override. Spec §12.4 does not accept that as evidence for the profile. - [ ] Confirm teardown left no stray project or volume: `docker ps -a`, `docker volume ls`. ## Task 5: Documentation and metadata reconciliation - [ ] Regenerate Spring configuration metadata and diff against the env registry and the YAMLs; any drift is a fail. - [ ] Confirm every registry env key appears in `src/.env.example` and that no example carries a real secret. - [ ] Confirm `docs/registries/env-keys.yaml` lists the five masters with `false` defaults and the two subordinate selectors with their `required-when` conditions. - [ ] Confirm no demoted key (`APP_MESSAGING_BROKER`, `APP_NOTIFICATION_SLACK_PROVIDER`, `APP_NOTIFICATION_EMAIL_PROVIDER`, `app.jpa-platform.enabled`) is documented anywhere as an activation switch. - [ ] Update `README.md` with the five switches, the Compose minimum version, and the two script entry points. - [ ] Update `src/app-bootstrap/CLAUDE.md`, replacing its "19-leaf dependency list" phrasing with a pointer to the registry — a count in prose is the drift `AGENTS.md:52-55` forbids. - [ ] Confirm the capability docs do not label as Stable anything the index's scope boundaries exclude: Mongo reactive, change streams, sharding, Atlas, KMS; Notification before NTF-INT-007 is closed. ## Task 6: Definition of Done Walk spec §13 and tick each box **only** with attached evidence. Reproduced here as the checklist: - [ ] Five runtime facades on one bootJar runtime classpath. - [ ] Five canonical master switches in registry, YAML, metadata, and docs, all defaulting `false`. - [ ] All-off `local`, `dev`, `prod` smoke succeeds with no external resources. - [ ] Each adapter's off invariant and on fail-closed contract pinned by full-context tests. - [ ] Mongo, GraphQL, and Messaging Stable facades' resolved runtime membership matches the registry. - [ ] The JPA switch controls the whole DataSource/Hikari/entity/repository/Hibernate/Flyway/DB health-and-metrics graph. - [ ] Messaging has a real broker bridge and a consistent relay dependency. - [ ] Notification `SERVING` works through production assemblers; `INGEST_ONLY` starts no worker. - [ ] Notification handoff proves, in one project and DB volume, `INGEST_ONLY` accept → restart → `SERVING` delivery exactly once on the same frozen route, with zero duplicates. - [ ] GraphQL policy and JWT context execute on the real `/graphql` request path. - [ ] GraphQL blocking qualification runs the bootJar JWT composition exactly once and uses neither class-existence nor test-only Basic Auth as release evidence. - [ ] `SPRING_PROFILES_ACTIVE` is exactly one of `local|dev|prod`; profileless, multiple, and unknown deployments are rejected. - [ ] GraphQL on requires one environment-permitted `APP_GRAPHQL_DEPLOYMENT_MODE`; the legacy boolean/enum split-brain is rejected. - [ ] Profiles and env example/secret sources are separated; real secret files are excluded from tracking, rendering, and evidence. - [ ] Compose minimum version, per-profile exact service sets, the whole merged model, and mount-target uniqueness are verified by the canonical script. - [ ] The runtime-smoke wrapper performs create, `up --wait`, required one-shots, sanitized evidence, and unique-project teardown with zero skips across `local`, `dev`, and `prod` blocking lanes. - [ ] PostgreSQL, Mongo, broker, MinIO, and Keycloak/realm smoke evidence exists. - [ ] The Keycloak realm provides a client-credentials-only service account, audience, and role claims, and real JWT-protected REST and GraphQL requests succeed against the same issuer URL per lane. - [ ] Full `test` and `check`, plus architecture, env, public-path, and strict qualification, all pass. - [ ] Zero Gradle, javac, Checkstyle, SpotBugs, and runtime-startup errors and warnings; zero allowlist entries; IDE Problems zero confirmed separately on the same toolchain. - [ ] The real active profile and the structured-log profile field agree; zero late-MeterFilter warnings. - [ ] After convention-plugin extraction, task selection, dependency graph, and evidence semantics are unchanged. - [ ] Every P0 blocker on a runtime path from the detailed module reviews is either closed or its capability is explicitly inactive/experimental. - [ ] Changed files, commands, results, not-run/blocked items, and evidence grades are captured in the LLM Wiki branch-note. ## Task 7: LLM Wiki capture Per `AGENTS.md:79-90`: - [ ] Create or update `/home/donghyeon/workspace/ai-tool/llm-wiki-private/raw/branch-notes/.md` with the implementation, changed files, decisions, verification commands, failures/blocks, and evidence grades. - [ ] Create derived documents where genuine material exists: `raw/errors/`, `raw/interviews/`, `raw/blog-topics/`. Each links upward via `## Parent`; the branch-note's `## Cluster / 묶음` links back. - [ ] Where no derived document is warranted, record that judgement explicitly ("추출할 별도 글감 없음") rather than omitting the section. - [ ] Do not create `wiki/blog/`, `wiki/interview/`, `wiki/portfolio/`, `wiki/concepts/`, or `wiki/projects/` without an explicit canonical extraction request. ## Task 8: Final report Per `AGENTS.md:239-251`, the closing response states: changed files; the core changes; verification commands run; verifications that failed or could not run, with reasons; the Wiki capture result; and remaining risks or follow-ups. - [ ] Explicitly restate what remains **out of scope and not production-ready**, from the index's scope boundaries: Mongo reactive, change streams, sharding, Atlas, KMS; Notification's at-rest decision if the threat-model branch was chosen; object storage's runtime inclusion; Fileserver internals. --- ## Wave 6 Exit Criteria - [ ] Every §13 checkbox above is ticked **with attached evidence**, or is explicitly reported as not-met with its reason. - [ ] `docs/superpowers/plans/evidence/2026-08-15-wave6-final/` holds the output of every command in Tasks 1–4. - [ ] The LLM Wiki branch-note exists and links its derived documents. - [ ] No completion, "all passing", or "production-ready" claim appears anywhere without the command output that supports it.