Files
clean-architecture-backend-…/docs/superpowers/plans/2026-08-02-p2-verification-governance-refactoring.md
DongHyeonkaandClaude Opus 5 5f10b791d3 chore: record pre-existing uncommitted repository state
Snapshot of the in-flight state that already existed, identically, in both
this worktree and the main checkout before this session began: the initial
HTTP Client platform implementation (previously untracked), the redis-lab
removal, and the JPA / object-storage / notification integration work.

Kept separate from this session's HTTP Client review response, which lands
in the following commit, so the two bodies of work stay reviewable apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 16:48:43 +09:00

19 KiB

P2 Verification Governance Refactoring Plan

Batch 1 — strict owner-local qualification

  • Add TestKit RED cases for empty source sets, missing FQCNs, disabled-only tests, and one valid test.
  • Add the shared strict qualification convention.
  • Move conditional transport and Messaging task registration from root to owner projects.
  • Adopt the convention for object-storage, Poster migration, and composition qualifications.
  • Keep root tasks as absolute-path aggregators and verify all evidence XML.
  • Run focused TestKit, every migrated qualification lane, locks, and independent review.

Evidence: eight TestKit cases passed fresh; conditional transport ran 8/15/5/1 tests and Messaging ran 15/6/4/29/28 tests with zero skips. All dependency locks passed. Object-storage and Poster required-class preflights passed; protected AWS and Docker-backed full lanes remain environment- qualified. Independent review closed with no remaining Critical, Important, or Minor findings.

Batch 2 — tracked contract resources hard-fail

  • Add RED tests proving absent tracked files/directories fail instead of aborting.
  • Add RepositoryContractResources and inject the canonical repository root.
  • Replace stale tracked-resource assumptions in the contract corpus.
  • Preserve assumptions only for genuinely optional external infrastructure.
  • Run focused representative contracts, scan for stale skip language, and run app-bootstrap check.

Evidence (2026-08-02): the fail-closed repository resolver is covered by 11 boundary tests; Runbook coverage and lock-classification contracts passed with zero skips. Independent review found and closed both direct-link and directory-enumeration symlink escapes. A fresh ./gradlew :app-bootstrap:check --no-daemon --console=plain passed (77 tasks; 18 executed, 59 up-to-date), and the final Batch 2 review reported zero Critical, Important, or Minor findings.

Batch 3 — real gate-matrix mutation tests

  • Add temporary-fixture tests that execute the shell validator itself.
  • Make the validator accept a repository-root argument without changing default CI behavior.
  • Delete the duplicated Java command parser.
  • Cover deceptive names, suppression flags, missing/duplicate gates, and missing task wiring.
  • Run the focused contract, real repository validator, and wrapper verifier.

Evidence (2026-08-02): the initial focused RED compiled and reported seven failing contracts against the old validator. Independent review found arbitrary project-qualified task matching, shorthand step parsing, generic name: registration, relocated-script guard evidence, unsafe custom refs, missing check wiring evidence, and process-tree cleanup gaps; each was closed with a regression test or bounded cleanup. A final regex-boundary audit also closed custom-task and plugin-ref ERE injection with literal-safe grammars and fixed-string plugin lookup. The final focused contract passed all 16 tests using bounded ProcessBuilder execution of the real shell script. bash .github/scripts/verify-gate-matrix.sh passed with 27 gates (26 verified and one explicitly delegated), bash .github/scripts/verify-gradle-wrapper.sh . passed, bash -n and :app-bootstrap:spotlessJavaCheck passed, and git diff --check reported no whitespace errors.

Batch 4 — Redis manifest JSON Schema conformance

  • Add invalid-manifest RED fixtures for bounds, patterns, required fields, and extra fields.
  • Validate the canonical schema and all manifests with Draft 2020-12 semantics.
  • Retain Java-catalog equality checks for cross-resource invariants.
  • Run the focused schema test, cache-redis check, and dependency-lock verification.

Evidence (2026-08-02): the initial focused RED compile failed on the deliberately missing RedisProgramManifestSchemaValidator (six cannot find symbol errors). NetworkNT 3.0.2 now validates the canonical schema against its bundled Draft 2020-12 meta-schema and validates the exact six closed manifests under strict parsing/configuration. Mutation coverage exercises additional properties, type, required, enum, minimum/maximum, pattern, duplicate JSON keys, and an independent cross-resource duplicate-program-id Java invariant. The first GREEN attempt exposed that the canonical ACL pattern rejected the existing SCRIPT|LOAD command form; the pattern was narrowly relaxed before independent review identified that it also admitted dangerous commands. A second RED run failed exactly two tests because the schema had no exact allowlist and accepted FLUSHALL, CONFIG|SET, and MODULE|LOAD. The six canonical manifests contain 265 ACL command occurrences and exactly 37 unique commands; aclCommands.items now uses that exact enum so adding a command requires an explicit schema change. Review coverage also rejects a trailing manifest JSON token and a duplicate schema key on the compile path, and pins invalid meta-schema diagnostics to /type:type. Final verification passed: ./gradlew :adapter:outbound:cache-redis:test --tests '*RedisProgramManifestContractTest' --console=plain (12 tests), ./gradlew :adapter:outbound:cache-redis:test :adapter:outbound:cache-redis:spotlessJavaCheck --console=plain, ./gradlew :adapter:outbound:cache-redis:verifyDependencyLocks :adapter:outbound:cache-redis:spotlessCheck --console=plain, and ./gradlew :adapter:outbound:cache-redis:check --console=plain. The owner lock gained only com.networknt:json-schema-validator:3.0.2 and com.ethlo.time:itu:1.14.0; no tools.jackson.dataformat:jackson-dataformat-yaml entry is present. git diff --check passed. The configured owner check remained successful while its SpotBugs test report retained one pre-existing DMI_RANDOM_USED_ONLY_ONCE finding in RedisPrimitiveRuntimeServiceTest; the new schema validator and contract test introduced no SpotBugs finding.

Batch 5 — registry and runbook governance

  • Enforce an exact catalog for every tracked registry, including object-storage readiness.
  • Resolve every stable required_test ID exactly once and reject dangling mappings.
  • Replace the Java runbook stub allowlist with owned, issue-linked, expiring debt data.
  • Clarify tracked registry ownership and private-wiki provenance.
  • Run schema, object-storage readiness, runbook, app-bootstrap, and root checks. The checks exercise the mechanically enforceable catalog/containment rules; the three semantic migrations above remain explicitly blocked on project-owner evidence.

Batch 5-A evidence — exact tracked registry catalog (2026-08-02)

The owner catalog now enumerates exactly eight regular, non-symlink direct children: seven universal contract registries plus the specialized object-storage readiness registry. The initial focused RED failed compilation on the deliberately absent RegistryGovernanceCatalog (13 symbol errors). A second exact-version mutation RED proved that numeric coercion admitted schema_version: 1.5; the implementation now requires the integer value 1. Strict SnakeYAML safe construction disables duplicate keys and aliases, enforces exact root keys, a non-empty list of map rows, non-blank unique identities, the existing universal row policy, and the specialized owner delegation/provenance policy. Missing, unknown, non-regular, symlinked, malformed, duplicate, false-provenance, block-scalar spoofing, reordered-header, and fabricated-branch-header fixtures fail closed.

Gradle declares docs/registries as a relative-path-sensitive :app-bootstrap:test directory input. The object-storage owner declares its canonical readiness YAML as a relative-path-sensitive file input and passes its absolute path through objectstorage.readiness.registry; its leaf test no longer searches parent directories. The tracked specialized registry header is exactly four ordered leading comment lines containing only the factual repository and semantic owner Gradle paths and test FQCNs.

Fresh verification passed:

  • ./gradlew :app-bootstrap:test --tests dev.caskeleton.bootstrap.contract.ContractRegistrySchemaGovernanceTest --console=plain
  • ./gradlew :adapter:outbound:objectstorage:test --tests dev.caskeleton.adapter.outbound.objectstorage.readiness.ObjectStorageReadinessRegistryTest --console=plain
  • ./gradlew :app-bootstrap:test --console=plain (38 tasks; 2 executed)
  • ./gradlew :app-bootstrap:check --console=plain (77 tasks; 21 executed)
  • ./gradlew :app-bootstrap:spotlessJavaCheck :adapter:outbound:objectstorage:spotlessJavaCheck --console=plain
  • git diff --check, an exact direct-child regular-file audit, the owner-path jq audit, and yq eval 'true' docs/registries/*.yaml (eight parsed documents)

Batch 5-C partial containment evidence — legacy runbook stub debt (2026-08-02)

This is bounded containment, not completion of the owned, issue-linked, expiring debt-ledger item above. The Java set is now named LEGACY_STUB_DEBT, contains exactly the 43 current status: stub runbooks, and is checked bidirectionally against canonical tracked runbook files. The stale migration-failed.md entry was removed because that runbook is already active. Active, missing, template, and newly introduced stub drift now fail the same exact-set contract. Messages and the runbook template forbid adding new legacy allowlist entries and direct maintainers to complete the runbook or adopt the future governed ledger.

The focused RED failed only because migration-failed.md was an unexpected legacy-debt element. After the containment change, the focused Runbook contract passed with 6 tests, zero failures, and zero skips. Fresh verification also passed :app-bootstrap:spotlessJavaCheck and :app-bootstrap:check (77 tasks; 18 executed, 59 up-to-date). Owner, issue, start/sunset, expiry enforcement, and the private-wiki provenance migration remain deliberately incomplete and the corresponding Batch 5 checkboxes remain open.

Batch 5-B/C unresolved semantic migrations audit (2026-08-02)

These items are intentionally not marked complete. The seven universal registries contain 324 non-reference required_test occurrences and 216 unique IDs. There is no tracked selector catalog, no Gradle declaration containing those IDs, and no ID that can currently be proven to resolve to one exact module/task/class/method selector. Exact Java test-source literals cover only 17 IDs (45 occurrences, 40 in comments/Javadocs); 199 IDs have no exact source literal. Creating 216 selectors from namespaces or historical branch labels would manufacture execution evidence, so the exact-linkage gate requires semantic owner confirmation or new tests before it can be enabled.

The runbook corpus contains 43 stub documents, all with response owner oncall but no accountable debt owner, real issue, approved expiry, or bounded debt window. The seven legacy registries contain 30 distinct owner_branch labels, none resolving to a current local/remote Git ref, while their private-wiki paths are absent from a fresh clone. The repository files are now protected as the tracked artifacts, but current owner IDs, historical-label migration, CODEOWNERS identities, runbook expiry dates, the INTERNAL_ERROR reverse-link decision, and the four umbrella-runbook retention decisions require real project-owner input. Placeholder owners, issues, selectors, and sunsets were not added to make the checks pass.

Batch 6 — bounded P2 cleanup

  • Extend link-check triggers and scan scope to module README/CLAUDE documents.
  • Make Poster migration gate labels version-neutral while preserving externally stable job IDs.
  • Replace fixed HTTP timeout sleeps with deterministic latch-controlled handlers.
  • Separate sample-off compile evidence from its minimal runtime proof if exact required tests can be established without weakening coverage.
  • Run focused docs, CI, HTTP client, sample-off, and wrapper checks.

Batch 6 link/Poster evidence: test-first changes made the two focused app-bootstrap contracts fail only for the absent module documentation scope and the legacy Poster V7 internal gate ID. The same contracts then passed with exact pull/push/lychee scope, all 27 gate IDs, and the stable external poster-image-v7-migration workflow job plus posterImageMigrationTest task mapping. The full DeveloperExperienceContractTest and ConditionalTransportQualificationContractTest classes passed, posterImageMigrationTest produced 4 tests with zero skips, and both the 27-entry gate validator and Gradle wrapper verifier passed. The complete sorted six-workflow SHA-256 lock was refreshed after review; app-bootstrap Java and sample-portfolio Spotless checks also passed. An independent Batch 6 link/Poster read-only review found no Critical, Important, or Minor issues.

Batch 6 HTTP evidence: the focused synchronization contract first failed on exactly five fixed sleeps across OutboundHttpClientTest (one), OutboundHttpClientDeadlineTest (one), and OutboundCallExecutorTest (three). The HTTP handlers now signal requestStarted, await a bounded releaseResponse latch, and are released in the caller's finally after the timeout result and classification assertions. Executor workers now block on a bounded latch interruption point, with the existing started/interrupted evidence and caller cleanup preserved. The four focused classes passed 25 tests with zero failures, errors, or skips. A 3-second read-timeout mutation failed when the handler's 1-second HTTP 204 fallback completed successfully, proving that the test cannot pass via the separate 5-second logical deadline. The full owner test passed, and :adapter:outbound:httpclient:check passed 29 tasks (16 executed, 13 up-to-date), including Spotless, Checkstyle, SpotBugs, architecture dependencies, and environment-key verification. No production source changed. Independent re-review found no remaining Critical, Important, or Minor issues and found no cleanup leak or deadlock race.

Batch 6 sample-off evidence: the focused build contract first failed because the dedicated source directory, compile lifecycle task, strict registration, and required FQCN did not exist. The sampleOffTest source set now compiles all 204 ordinary test sources plus the dedicated contract without sample-portfolio, while sampleOffCompile exposes that complete compile proof separately. The externally stable sampleOffTest task is registered through the shared strict qualification convention and executes only SampleOffClasspathContractTest; fresh XML reported exactly 1 test, 0 skipped, 0 failures, and 0 errors. The existing eight strict-convention functional contracts passed, including missing-class, no-discovery, skip, and stale-evidence fail-closed cases. The focused build contract, sampleOffCompile, gate-matrix validator, wrapper verifier, dependency-lock verification, Spotless, and the full :app-bootstrap:check also passed; the full check completed 78 tasks (23 executed, 55 up-to-date). This is focused/owner evidence; the repository-wide Batch 6 aggregate is recorded below.

Batch 6 repository evidence (2026-08-02): the real gate-matrix validator passed all 27 entries (26 locally verified and the protected AWS lane explicitly delegated-pending), the Gradle-wrapper contract passed, bash -n .github/scripts/verify-gate-matrix.sh passed, all eight tracked registry YAML documents parsed, the Redis Draft 2020-12 schema parsed as JSON, and git diff --check reported no whitespace errors. The first repository check exposed a 503 in the first JwtJwksSecurityFilterIntegrationTest request while static-analysis workers were running. The single test passed in isolation, identifying a test-fixture scheduling race rather than a JWT classification mismatch. The embedded OIDC server now owns a dedicated single daemon executor and shuts it down in close(); the full eight-test security-boundary lane plus Checkstyle and Spotless passed, and a fresh repository check subsequently passed with the same boundary lane included.

Final verification and capture

  • Run full Gradle tests/checks and all repository validators.
  • Request an independent P2 code review, resolve actionable findings, and record semantic blockers separately.
  • Update the LLM Wiki branch note and any honest derived raw documents.

Fresh aggregate evidence (2026-08-02):

  • ./gradlew test --no-daemon --console=plain — successful in 4m 24s (86 tasks).
  • ./gradlew check --no-daemon --console=plain — first run failed only on the OIDC test-fixture race above; after the bounded fixture correction, successful in 4m 35s (260 tasks).
  • Final post-review ./gradlew check --no-daemon --console=plain — successful in 10m 33s (260 tasks; 76 executed, 184 up-to-date). It regenerated the SampleRemoval result after the source edit: 5 tests, zero skipped/failures/errors.
  • ./gradlew verifyCleanArchitectureDependencies verifyRuntimeModuleMembership verifyDependencyLocks verifyPublicPathSnapshot verifyEnvKeys --no-daemon --console=plain — successful (23 tasks); all 19 leaf locks passed and two runtime compositions matched the registry.
  • Real gate-matrix, wrapper, shell syntax, Redis JSON, registry YAML, and diff validators — all successful; the protected AWS qualification remains explicitly delegated to its environment.
  • Final verifyDependencyLocks rerun — successful in 24s with all 19 leaf tasks executed. The tracked-file assumption audit now reports only four Docker/Testcontainers integration assumptions; no registry or repository-contract assumption remains.

LLM Wiki capture evidence (2026-08-02): raw/branch-notes/main.md records the integrated P1/P2 implementation, decisions, validation commands, failures, evidence grades, and unresolved semantic migrations. It links bidirectionally to one resolved error note, one interview-prep note, and one blog-topic note. The vault's targeted structure lint passed all three derived documents. The branch note passed its content, frontmatter, required-section, and wikilink checks but retained one explicit NAMING_VIOLATION: repository policy requires <branch-name>.md (main.md) while the vault naming rule permits only feature|fix|chore|experiment- branch-note prefixes. Neither policy was silently weakened; the exact conflict is the recorded capture-validation blocker.

Independent aggregate review evidence (2026-08-02): the first pass reported zero critical, three important, and two minor findings. Wiki capture closed the capture-pending finding; the two remaining important items were reclassified as the three project-semantic blockers already kept open in Batch 5. The two minor code findings were corrected with an exact test-fixture-only GraphQL SpotBugs exclusion and registry-derived scanning of all 18 production leaves in SampleRemovalSmokeContractTest. A follow-up audit also found and removed the last tracked-file assumption/upward-directory search in PortfolioErrorCodeRegistryMappingTest, replacing it with a canonical repository-root property, relative Gradle input, and missing-root/symlink-escape fail-closed checks. The re-review found no new code defect; its only completion-evidence concern was a stale SampleRemoval XML, addressed by the final repository check after these corrections. The reviewer retained only the Wiki naming-policy disclosure and this Batch 5 checkbox wording as minor documentation findings; both are now explicit here and in the branch note.