13 KiB
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.mdfirst. 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
(§12 in full, §13, §11 Wave 6)
Global Constraints
Inherited from the index. Wave 6 adds:
- Use
superpowers:verification-before-completionbefore 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:
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-daemonreports an empty red set, then delete thewave0Redlanes 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:
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
testdoes not substitute for the Docker-backed qualification. -
Persistence blocking lanes:
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, andscripts/verify-mongodb-advanced.sh. Attach theReleaseManifestTaskExistenceTestresult.
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
@Primaryresolution is a fail.
Task 4: Environment and runtime gates
- Compose artifacts, statically then dynamically:
./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-smokeactually started TLS PostgreSQL, the app, Keycloak, and MinIO and ran both one-shots — aconfig-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.exampleand that no example carries a real secret. - Confirm
docs/registries/env-keys.yamllists the five masters withfalsedefaults and the two subordinate selectors with theirrequired-whenconditions. - 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.mdwith 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 driftAGENTS.md:52-55forbids. - 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,prodsmoke 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
SERVINGworks through production assemblers;INGEST_ONLYstarts no worker. - Notification handoff proves, in one project and DB volume,
INGEST_ONLYaccept → restart →SERVINGdelivery exactly once on the same frozen route, with zero duplicates. - GraphQL policy and JWT context execute on the real
/graphqlrequest 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_ACTIVEis exactly one oflocal|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 acrosslocal,dev, andprodblocking 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
testandcheck, 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/<branch-name>.mdwith 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/, orwiki/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.