Files
clean-architecture-backend-…/docs/superpowers/plans/2026-08-15-wave6-final-qualification.md

13 KiB
Raw Permalink Blame History

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 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 (§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:
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:
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:

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:
./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/<branch-name>.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 14.
  • 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.