Files
summercms/.planning/phases/14-domain-jobs-and-external-integrations/14-06-SUMMARY.md

20 KiB

phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, app_repo_head_before, app_repo_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
phase plan subsystem tags requires provides affects actuals plan_head_before plan_head_after app_repo_head_before app_repo_head_after tech-stack key-files key-decisions patterns-established requirements-completed coverage duration completed status
14-domain-jobs-and-external-integrations 06 testing
gate
coverage
mutation-testing
removal-harness
truth-tables
fuzz
security-review
discogs
sm-golem-plugin
sm-feedback-plugin
validation
phase provides
14-domain-jobs-and-external-integrations 14-01 framework helpers (fetchguard.Client, tide sidecars, sunscreen, DropIndex), 14-02 Discogs core and workers, 14-03 Discogs routes, 14-04 sm-golem-plugin and recognition, 14-05 sm-feedback-plugin
phase provides
13-p-ytarium-api-wishlist-notifications-csv-credentials-public check-phase13.sh structure, FuzzWriteEndpoints, TestPhase13Threats and the removal-harness precedent
scripts/check-phase14.sh: --self-test --go --parity --named --removal --coverage --evidence --all, fail closed; 175 recorded, 172 ported and passing, 3 pending
TestPHPTruthDiscogs over PHP-generated php_mapper.json, php_input_parser.json, php_scorer.json, php_price_suggestion.json
TestPhase14Threats (T-14-08 to T-14-29), TestPhase14Edges, TestPhase14Jobs, TestPhase14HandlersFailClosed, TestPhase14Classes, TestPhase14ControllerHelpers; TestRouteTablePhase14 with the in-handler buckets; FuzzWriteEndpoints over the 11 Phase 14 routes
sm-golem-plugin TestGolemAdminSchemas, TestGolemImportCommand; sm-feedback-plugin TestFeedbackEdges (pushed)
43 removal checks, one or more per mitigated threat, all failing as required; 14-SECURITY-REVIEW.md
Validated 14-VALIDATION.md, REQUIREMENTS INTG-02 and API-08 Complete, COVERAGE.md confirmed, two folded todos closed
14 verify-work
14.1 oauth-identities and me routes
15 cutover
tokens tasks commits app_repo_commits plugin_repo_commits
79300 4 6 9 3
c12641605c 17b2ef1961 9fc38d9d7fefd9671312e4a148b2f3042acde6eb cd393e4
added patterns
Fault injection without a broken database: a second gorm handle on the same pool with Before callbacks that fail statements on one table after N successes (faultDB in classes and the plugin root)
Phase function floor: the functions a phase's diff touched are listed in the gate by file and must each reach 80% by go tool cover -func; an exemption carries its reason
Removal rows reach into the shared plugins' submodule checkouts; the dirty-file refusal runs against the file's own repository
A fuzz route that calls a vendor runs behind a scripted vendor transport (fetchguard.WithTransport), never the network
created modified
scripts/check-phase14.sh
modules/tide/upstream_coverage_test.go
.planning/phases/14-domain-jobs-and-external-integrations/14-SECURITY-REVIEW.md
../fonoteka.go/plugins/golem15/fonoteka/classes/discogs/php_truth_test.go
../fonoteka.go/plugins/golem15/fonoteka/classes/discogs/testdata/php_mapper.json
../fonoteka.go/plugins/golem15/fonoteka/phase14_security_test.go
../fonoteka.go/plugins/golem15/fonoteka/phase14_edges_test.go
../fonoteka.go/plugins/golem15/fonoteka/phase14_jobs_test.go
../fonoteka.go/plugins/golem15/fonoteka/phase14_handlers_test.go
../fonoteka.go/plugins/golem15/fonoteka/classes/phase14_classes_test.go
../fonoteka.go/plugins/golem15/fonoteka/controllers/api/phase14_controllers_test.go
../fonoteka.go/plugins/golem15/fonoteka/testdata/fuzz/FuzzWriteEndpoints/ (11 seeds)
../fonoteka.go/plugins/golem15/golem/golem_admin_test.go
../fonoteka.go/plugins/golem15/feedback/feedback_edges_test.go
../fonoteka.go/parity/discogs_truth_tables.php
../fonoteka.go/parity/README.md
../fonoteka.go/plugins/golem15/fonoteka/classes/discogs/discogs_test.go
../fonoteka.go/plugins/golem15/fonoteka/classes/discogs/testdata/php_input_parser.json
../fonoteka.go/plugins/golem15/fonoteka/classes/discogs/testdata/php_price_suggestion.json
../fonoteka.go/plugins/golem15/fonoteka/routes_table_phase14_test.go
../fonoteka.go/plugins/golem15/fonoteka/write_endpoints_fuzz_test.go
.planning/phases/14-domain-jobs-and-external-integrations/14-VALIDATION.md
.planning/phases/14-domain-jobs-and-external-integrations/COVERAGE.md
.planning/phases/14-domain-jobs-and-external-integrations/deferred-items.md
.planning/REQUIREMENTS.md
.planning/todos/done/fetchguard-guarded-http-client.md
.planning/todos/done/redacting-slog-handler.md
The sm-feedback-plugin routes are pinned and fuzzed by the plugin's own tests (TestFeedbackConfig, TestFeedbackSubmit, TestFeedbackEdges), not from TestRouteTablePhase14 or FuzzWriteEndpoints: the fonoteka plugin would otherwise have to require the shared plugin module just for tests
Every mitigated threat gets a removal row (43 rows), not only the high ones; the evidence stage requires one per mitigated threat
Two Phase 14 functions are exempt from the 80% function floor with recorded reasons: cover_importer.go fetch (its 2xx path needs the live image host, deferred from 14-03) and validateDiscogsInput (its error branch needs a malformed rule table)
internal/pgtest of both plugins is exempt from the package floor: a test-only helper whose uncovered lines are container start failures
The Discogs truth tables were restructured into php_mapper.json (mapRelease plus the candidate mappers) and widened; TestPHPTruthDiscogs replaces the replay subtests of TestDiscogsDomainVectors and TestMapReleaseFixture
PHP's behaviour kept against the plan's wording stays pinned: a dry run writes what PHP's writes (T-14-19 pins 'never writes a staged field'), a second identical apply re-imports covers, apply runs without a transaction (14-03 deviations 5-7)
Phase gate with a phase-function coverage list and per-mitigated-threat removal rows
Shared-plugin tests committed and pushed in the plugin checkout, then one gitlink-only bump commit per plugin in the application
JOBS-02
JOBS-03
SRCH-02
INTG-01
INTG-02
API-08
CLI-05
id description requirement verification human_judgment
D1 One command proves the phase green or red over both repositories, the corpus and the named flows, failing closed INTG-01
kind ref status
other bash scripts/check-phase14.sh --all → 'phase14 all passed' (2026-10-04); --self-test plants every detector pass
false
id description requirement verification human_judgment
D2 The Discogs mapper, parser, scorer and price resolver reproduce PHP's truth tables row for row INTG-01
kind ref status
unit plugins/golem15/fonoteka/classes/discogs/php_truth_test.go#TestPHPTruthDiscogs pass
false
id description requirement verification human_judgment
D3 Every numeric edge one step either side, the CSV job lifecycles, the route buckets and the fuzz over the Phase 14 write routes JOBS-02
kind ref status
unit plugins/golem15/fonoteka#TestPhase14Edges, TestPhase14Jobs, TestRouteTablePhase14, FuzzWriteEndpoints, TestPhase14HandlersFailClosed pass
kind ref status
unit plugins/golem15/feedback#TestFeedbackEdges pass
false
id description requirement verification human_judgment
D4 Every mitigated threat has a test that fails without its protection INTG-02
kind ref status
unit plugins/golem15/fonoteka/phase14_security_test.go#TestPhase14Threats pass
kind ref status
other bash scripts/check-phase14.sh --removal → 43 of 43 fail as required, 'phase14 removal passed' pass
false
id description requirement verification human_judgment
D5 The framework, the Phase 14 application functions and both shared plugins at the 80% floor API-08
kind ref status
other bash scripts/check-phase14.sh --coverage → 'phase14 coverage passed' pass
false
id description requirement verification human_judgment
D6 Validation signed off, requirements complete, API coverage checked, security review complete, folded todos closed CLI-05
kind ref status
other bash scripts/check-phase14.sh --evidence → 'phase14 evidence passed'; REQUIREMENTS grep prints 7 pass
false
132min 2026-10-04 complete

Phase 14 Plan 06: Unit tests and the Phase 14 gate Summary

Phase 14 is proven by one fail-closed gate: PHP's own Discogs truth tables replayed row for row, every Phase 14 function and both shared plugins at the 80% floor, every numeric edge pinned one step either side, and 43 anchor-exact mutations, one or more per mitigated threat, each caught by a named test.

Performance

  • Duration: 132 min
  • Started: 2026-10-03T22:35:35Z
  • Completed: 2026-10-04T00:48Z
  • Tasks: 4
  • Commits: 6 in summercms.go, 9 in fonoteka.go, 2 in sm-golem-plugin and 1 in sm-feedback-plugin (both pushed), plus this summary
  • Files: 13 created and 13 modified across the four repositories (plus 11 fuzz seeds)

Accomplishments

  • The gate (scripts/check-phase14.sh).
    • --go runs vet and tests in summercms.go, and with -race in fonoteka.go including sm-user-plugin, sm-golem-plugin and sm-feedback-plugin. It refuses a vendor AI SDK in either module graph (D-02, T-14-SC).
    • --parity reads 175 recorded, 172 ported and passing and 3 pending from the replay's own coverage line and from the manifest. It requires every TestFonotekaNuxtFlows subtest (read from the source, so a new flow cannot be skipped), the broadcast goldens, the sidecar replay, the feedback job sidecar, check_corpus --require-recorded --check-secrets, the fuzz corpus scan and the docs checks.
    • --named runs about 110 tests by exact name, across 21 packages.
    • --coverage enforces the floors (below).
    • --removal runs 43 mutations.
    • --evidence checks the security review, the validation map, COVERAGE.md, the REQUIREMENTS wording and the ROADMAP Phase 14 section.
    • --self-test plants a failing, skipped, zero-test, racy and non-JSON run, a fourth pending route, a vendor SDK, each secret shape, each coverage and function-floor refusal, each removal-harness refusal and each evidence gap.
  • PHP truth tables. parity/discogs_truth_tables.php was rerun against the isolated PHP instance:
    • php_mapper.json gained releases without images, with secondary images only, with several formats, with cassette and CD, with unicode artists and a master's main release.
    • The barcode table gained check-digit cases.
    • The price table gained every market currency, rounding ties and empty or odd suggestions.
    • TestPHPTruthDiscogs replays all rows and fails if a table shrinks. The price results are compared byte for byte.
  • Application tests (fonoteka).
    • TestPhase14Edges pins the limiter (50/51), the wait budget (15/16 s), Retry-After, the candidate cap (10/11), the 90-day prune cutoff, the 60/20/10 inbound buckets and the 12/13 cover-price throttle.
    • TestPhase14Jobs covers a cancel while a match is paused, a resumed match writing the same rows as an uninterrupted one, already-written rows being skipped, and every worker error branch.
    • TestPhase14HandlersFailClosed covers gate lookups that fail with a 500 before any vendor call, PHP's no_match, token-rejected and Winter 500 answers, and failures after the fetch.
    • TestPhase14Classes uses a fault-injecting gorm handle. TestPhase14ControllerHelpers covers the controller helpers.
    • TestRouteTablePhase14 now asserts which in-handler bucket each route answers 429 from.
    • FuzzWriteEndpoints covers the 11 Phase 14 routes through a scripted vendor, with 11 committed seeds (81 routes in all).
  • Threats. TestPhase14Threats has one subtest per application threat from T-14-08 to T-14-29. The framework threats map to their module tests, and the feedback threats to the plugin's own tests. 14-SECURITY-REVIEW.md maps all 39 ids, and the removal run passed 43 of 43.
  • Shared plugins. TestGolemAdminSchemas and TestGolemImportCommand were added to sm-golem-plugin, and TestFeedbackEdges to sm-feedback-plugin. Both were pushed, and each pointer was bumped in its own commit.
  • Record. 14-VALIDATION.md is validated. INTG-02 and API-08 are marked Complete. COVERAGE.md is confirmed, and both folded todos are closed.

Coverage (check-phase14.sh --coverage)

Package Coverage
fetchguard 84.5%
tide 82.1%
sunscreen 98.5%
beachcomber 84.8%
beachcomber/typesense 95.6%
fonoteka classes/discogs 86.1%
fonoteka console 82.6%
  • The 132 Phase 14 functions of the fonoteka root, classes and controllers/api packages are each at 80% or more. The lowest is 80.0%. Two are exempt.
  • sm-golem-plugin packages are between 80.0% (updates) and 100%.
  • sm-feedback-plugin packages are between 82.9% (classes) and 100%.
  • internal/pgtest is exempt in both plugins.

Task Commits

summercms.go:

  1. Task 1 (tracer): the gate's self-test, go and parity stages: 88f7683 (test)
  2. Task 3: tide sidecar refusals: fc90ae2 (test). Gate named, coverage and removal stages: 4c042f7 (test). Security review: 8154352 (docs)
  3. Task 4: evidence stage: a1fccd3 (test). Validation, requirements, coverage, todos: 17b2ef1 (docs)

fonoteka.go (not pushed):

  1. Task 2: PHP truth tables: 45052ad. Edges and job lifecycles: b30698f. Route buckets and fuzz: bf177e3. Class, controller and worker coverage: 0244392 (all test)
  2. Task 3: sm-golem-plugin bump: 49dfef5. sm-feedback-plugin bump: 02a4d05 (chore). TestPhase14Threats: 21b3eb8 (test). sm-golem-plugin bump: 976b446 (chore). T-14-19 strengthened: cd393e4 (test)

sm-golem-plugin (pushed, master): 70314b5, 6646d10. sm-feedback-plugin (pushed, master): 3057719.

Tracer gate: after Task 1, <verify> (bash -n, --self-test, --go, --parity) was re-run end to end and passed, so the expansion tasks went ahead.

Deviations from Plan

Auto-fixed issues

1. [Rule 1 - Weak tests found by the removal harness] Two tests did not catch the removal of their protection

  • Found during: Task 3, first --removal run (5 survivors)
  • Issue: T-14-19's subtest checked only fields that a dry run stages, so removing the fill-empty skip survived. TestGolemAdminSchemas checked only that the key text was absent, which lagoon.Encrypted's redaction already guarantees.
  • Fix: T-14-19 now also pins a filled barcode and an empty discogs_id. The golem test refuses any api_key key.
  • Commits: cd393e4 (fonoteka.go), 6646d10 (sm-golem-plugin), bumped in 976b446
  • The other three survivors were mutations that were redundant or did not build (the Origin empty-list check, DropIndex's escaping, an import left unused). Their rows now remove a protection that is load-bearing. The details are in the review.

2. [Rule 3 - Blocking] The gate keeps the failed go test log

  • Found during: Task 1. TestCoverFetcherHostLock failed once under the full -race run, and the log had been deleted.
  • Fix: phase14_go moves a failed run's JSON log to $TMPDIR/phase14-failed-<pid>.json and prints the detector's verdict last. The failure did not recur (see deferred-items.md).

Plan details refined

3. The feedback routes are pinned and fuzzed in sm-feedback-plugin, not in TestRouteTablePhase14/FuzzWriteEndpoints. Activating the feedback plugin from the fonoteka plugin's tests would make the application plugin require the shared plugin module. TestFeedbackConfig, TestFeedbackSubmit and TestFeedbackEdges pin the four routes' throttles, buckets and limits instead. The fonoteka route table pins the eleven Phase 14 routes plus their in-handler buckets.

4. The truth-table files are php_mapper.json (the old php_map_release.json plus php_candidates.json), php_input_parser.json, php_scorer.json and php_price_suggestion.json. php_scorer.json regenerated byte-identical.

5. The removal table covers every mitigated threat (43 rows), not only the high ones. The evidence stage enforces a row for every mitigated threat.

6. Coverage files the plan named but did not need were not created. Their packages already met the floor: fetchguard, sunscreen, typesense, golem services and providers, and feedback classes. The new coverage tests were placed where coverage was low: TestPhase14Classes, TestPhase14ControllerHelpers, TestPhase14HandlersFailClosed (new file phase14_handlers_test.go), TestGolemImportCommand and TestFeedbackEdges.

7. Two function exemptions and one package exemption, each with its reason, are recorded in the gate (see key-decisions).

8. The prune cutoff edge in TestPhase14Edges runs the real command on the wall clock: one row a minute inside the window and one a second past it. The exact-boundary row stays pinned by the console package's TestPruneNotifications, which injects the clock.


Total deviations: 8. Two are auto-fixes and six are refinements. Impact: the only production-adjacent change is test strength. No production code changed.

Issues Encountered

  • One --all run refused at the coverage stage. A testcontainers Postgres for the updates package did not become ready within 60 s under the gate's parallel load. The rerun passed unchanged. This is recorded in deferred-items.md.
  • The shell aliases rm to its interactive form, and one cleanup blocked on its prompt. Later cleanups use command rm -f.
  • /tmp is at quota, so the parity root was ~/.cache/summercms-parity/p1406 and the Go temp dirs were ~/.cache/gotest-tmp. The truth-table run wrote nothing into the PHP checkout apart from php artisan cache:clear's cache directory, which earlier recordings also touched. git status there shows only the user's own files.

Verification

  • bash scripts/check-phase14.sh --all: phase14 all passed. The stages were self-test, go, parity (175/175 recorded, 172 ported and passing, 0 failing, 3 pending), named, coverage and evidence, and the run took 13 min 55 s.
  • bash scripts/check-phase14.sh --removal: all 43 rows fails as required, then phase14 removal passed. Every file was restored byte for byte.
  • Per-task verifies:
    • Task 2's -race run of TestPHPTruthDiscogs, TestPhase14Edges, TestPhase14Jobs, TestRouteTablePhase14 and FuzzWriteEndpoints passed with no SKIP or DATA RACE.
    • Task 3's -race -cover runs of both plugins passed.
  • Acceptance greps:
    • EXPECTED_PORTED=172 and EXPECTED_PENDING=3 each appear once.
    • The golem and feedback plugin paths are present.
    • --bogus exits 2 with the usage text.
    • php_mapper.json and php_price_suggestion.json exist, and the generator names PriceSuggestionResolver.
    • The fuzz corpus went from 70 to 81 files.
    • T-14- appears 96 times in the review.
    • There are three run_(named|removal|coverage)() functions and one run_evidence(), which --all calls.
    • The REQUIREMENTS grep prints 7.
    • The validation file has no row with the pending status, and neither todo is left under pending.
    • Both plugins are ## master...origin/master.

Known Stubs

None.

Threat Flags

None. This plan adds tests and a gate script only. Its own threats, T-14-37 (gate counts) and T-14-38 (removal harness), are in the review with removal rows RC-40 to RC-42.

Next Phase Readiness

  • /gsd-verify-work 14 can run bash scripts/check-phase14.sh --all, and separately --removal.
  • The open items from deferred-items.md carry over: the Phase 12 cover-import replay, the one-off TestCoverFetcherHostLock failure and the testcontainers start wait.
  • Phase 14.1 (oauth-identities and the token me route) will move EXPECTED_PENDING from 3 toward 0.

Phase: 14-domain-jobs-and-external-integrations Completed: 2026-10-04

Self-Check: PASSED

Every created file exists; commits 88f7683, fc90ae2, 4c042f7, 8154352, a1fccd3 and 17b2ef1 (summercms.go), 45052ad, b30698f, bf177e3, 0244392, 49dfef5, 02a4d05, 21b3eb8, 976b446 and cd393e4 (fonoteka.go), 70314b5 and 6646d10 (sm-golem-plugin, on origin/master) and 3057719 (sm-feedback-plugin, on origin/master) are present.