4,523 -> 1,687 (77% of the 2,200 budget). Records the
test_kis_data_collection_v1.py import fix and the golden-stub removal
reasoning, and explicitly notes that further file-count reduction
isn't warranted right now - the gate has real headroom and continuing
to hunt for deletions has more downside (accidentally cutting
something live) than upside at this point.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records the two-pass orphan script cleanup (74 files total across two
commits) and the methodology gap that mattered (check output-path
references, not just script-name references). Also records that
GatherTradingData.json (the project's own designated canonical seed,
per docs/GATHERTRADINGDATA_XLSX_DECISION) is available from the
production server even without the untracked .xlsx, but the release
DAG's convert_xlsx node has no skip-if-output-exists logic, and the
remaining 10 blocked WBS verdicts need a running QuantEngine.Web +
Playwright evidence run against real DB price history, not just the
seed JSON - not attempted this session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Entropy cleanup earlier today deleted all of Temp/, which turned out
to include WBS verification evidence (Temp/evidence/*/verdict.json),
not just build cache. Documents what broke, what got recovered, and
what remains genuinely blocked on missing trading data - so this
doesn't get rediscovered from scratch next time.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds docs/SESSION_HANDOFF_2026-07-30.md with what a future session
needs that isn't derivable from git log: open threads (release DAG
unverified end-to-end, engine_history/quantengine schema collision
left as-is, OpenDART/KRX not yet wired into any workflow) and traps
hit this session worth not repeating (archive-before-grepping
tools/spec/tests, DbUp ordinal sort, runtime/ is tracked history not
scratch space, two Pythons on this machine, entropy audit counting
local build noise). Pointed to it from CLAUDE.md's Known Issues list.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs/ROADMAP_WBS.md and docs/ROADMAP_ENTERPRISE_TEMPLATES_WBS.md were
archived in an earlier commit today as "superseded planning docs," but
that judgment only checked CLAUDE.md/README/other docs for references
- not the actual validator scripts, spec YAMLs, and unit tests that
drive the release gate. Both paths turn out to be load-bearing:
- docs/ROADMAP_WBS.md is read directly by
tools/validate_quant_engine_wbs_v1.py,
tools/validate_platform_transition_wbs_v1.py,
tests/unit/test_validate_quant_engine_wbs_v1.py, and referenced by
spec/60_quant_engine_wbs.yaml and others.
- docs/ROADMAP_ENTERPRISE_TEMPLATES_WBS.md is read by
tools/validate_enterprise_crud_specification_v1.py, which runs as
the "Enterprise Contract Parity Test" step in
.gitea/workflows/ci-frontend.yml.
Moved both back to their original path, replaced the stale "ARCHIVED"
banner with a note explaining why they can't be archived without first
updating the validators, and fixed the 4 doc cross-references that had
been repointed at docs/archive/. Verified all three affected validators
now exit 0 by actually running them locally.
The other 9 docs archived earlier today (5 CI/CD docs + CICD_ROADMAP.md,
EXECUTION_PLAN_PHASE0_CLOSEOUT_AND_PHASE1_KICKOFF.md,
MODERNIZATION_ROADMAP_VISUAL.md,
MODERNIZATION_STRATEGY_ROADMAP_2026-2027.md) were checked against the
same grep sweep (*.py/*.yaml/*.yml/*.js/*.ts/*.cs/*.json, whole repo)
and have zero references outside markdown - those archivals stand.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Commits work that predated this session and was sitting untracked:
qualitative sell strategy module (src/quant_engine), the t20 outcome
ledger cron workflow, the QuantEngine masterpiece roadmap doc, a WBS
execution yaml, and shared Razor Pages partials (page header, delete
confirm modal) with their view models. Verified these build clean
(0 errors, 0 warnings) before committing.
Also includes the "ARCHIVED" header notes on 6 docs archived in the
previous commit - the git-mv landed there, but the note text itself
was missed from that commit's staged file list.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Archives 6 more superseded planning docs to docs/archive/ (ROADMAP_WBS.md,
MODERNIZATION_ROADMAP_VISUAL.md, MODERNIZATION_STRATEGY_ROADMAP_2026-2027.md,
ROADMAP_ENTERPRISE_TEMPLATES_WBS.md, EXECUTION_PLAN_PHASE0_CLOSEOUT_AND_PHASE1_KICKOFF.md,
CICD_ROADMAP.md), each replaced by a current source of truth (CLAUDE.md,
docs/MIGRATION_STATUS.md, or the OMS·WMS·ERP spec/playbook), and repoints
4 files that linked to the pre-archive path.
Fixes README's top-of-file install instructions and package.json's
"ops:dev" script, both of which pointed at core_satellite_collector.js -
a file that has never existed anywhere in this repo's git history. The
real, working entry point (tools/run_kis_data_collection_v1.py /
npm run ops:data-collect) was already correctly documented further
down the same README.
Also finishes retiring pre-existing stale state that predates this
session: removes the superseded deploy-prod.yml.backup, completes the
already-in-progress removal of the old src/client/ Vue+AG-Grid
prototype (superseded by src/frontend/), and untracks
test-results/.last-run.json (Playwright's own run-metadata file,
regenerated every test run - shouldn't be version controlled).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
V004_normalize_snapshots_schema.sql had an unguarded FK to a table V2
creates. Under DbUp's default ordinal filename sort, the zero-padded
"V003_"/"V004_" migrations sorted before "V1__", so on a brand-new
database V004 would hard-fail on that FK and abort every migration
after it - V1 through V8 would never run. Confirmed via production
that neither V003 nor V004 had ever actually applied.
Fix: renamed them to V9__/V10__ and added MigrationScriptNameComparer,
which sorts DbUp scripts by numeric V{n} value instead of raw string
order, so double-digit versions can never again sort ahead of earlier
single-digit ones. Added regression tests for both the fixed case and
the original bug shape.
Also updates docs/db/quantengine.dbml (renamed migrations, and closes
out the engine_history/quantengine table-name-collision question -
both schemas are live, backing different code paths, not duplicates)
and CLAUDE.md (migration ordering fix, KIS/OpenDART/KRX credential
env-var-name reference, including a CI secret/env-var name mismatch
found for OpenDART that still needs a decision).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Consolidates duplicate KIS API client implementations (governance tests
were exercising an unused class instead of the one actually running in
production), closes a SQL injection path in the DB admin page, fixes a
migration that used MySQL-only syntax and had never actually applied
(confirmed against production), resyncs docs/db/quantengine.dbml with
all migrations, and removes a duplicate OMS·WMS·ERP frontend tree in
favor of src/frontend/. Also corrects several unverifiable/inflated
claims in the OMS planning docs and realigns CI/CD and architecture
documentation with what's actually in the repo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Critical re-review of the QuantEngine WBS evidence system found several
regressions of the "no fake gates" discipline established by M0, plus a
still-unwired M1 collection path. This closes 10 more WBS tasks
(QE-M1-01..06, QE-M2-01/02/04/05/06 — see spec/60_quant_engine_wbs.yaml)
with real, gate-verified evidence (18/34 total).
M1 — real KIS data now lands in PostgreSQL end-to-end:
- SchedulerService: load ticker universe from GatherTradingData.json instead
of a hardcoded array; fix a Hangfire scoped-service resolution bug.
- KisDataCollectionOrchestrator: restore logging on the lineage-event write
path (was a bare `catch {}` swallowing all failures silently); persist
daily OHLCV bars into quantengine.price_history_daily per run.
- Verified live: POST /api/collection/run -> Hangfire -> orchestrator ->
KIS mock API -> PostgreSQL, with Playwright DOM/API parity evidence.
M2 — historical price-history pipeline:
- CollectionRepository: SavePriceHistoryDailyAsync (idempotent upsert),
GetPriceHistorySummaryAsync (per-ticker aggregation) + a new
DateOnlyTypeHandler registered globally, since Dapper has no built-in
System.DateOnly support in either direction (write threw
NotSupportedException, read threw a constructor-mismatch
InvalidOperationException — found by exercising both paths live).
- tools/validate_price_history_integrity_v1.py: gap-freeness (vs KIS
trading calendar) + price-sanity gate over collected history.
- Admin Collection page: new "히스토리 현황" summary table +
GET /api/collection/history-summary, with Playwright evidence.
Governance/gate fixes:
- validate_market_time_series_schema_v1.py mislabeled its own output
"runtime_database_query": "DATA_GATED" despite never opening a DB
connection (pure file/regex check) — relabeled "check_scope":
"STATIC_STRUCTURAL_ONLY" and wired the node into the release DAG so it
isn't only reachable from ci.yml, matching every other validator.
Live-data authority for the same claim stays with QE-M2-01's pg_query
gate (spec/60), documented in spec/64.
- Fixed a WBS log_pattern check (QE-M1-06) that couldn't match its own
multi-line target; loosened two depends_on edges (QE-M1-05/06,
QE-M2-04/05) that encoded "needs X verified" when the real requirement
was only "needs X's code merged."
- Discovered and fixed admin-pages.spec.ts logging in with the wrong
seeded password (admin/admin instead of admin/quant123!, per CLAUDE.md)
— every test in that suite had been silently failing at the login step.
Deferred: QE-M2-03 (2-year backfill) — the KIS mock/VTS token endpoint
started returning 403 after the first successful call this session; looks
like a token-issuance rate limit or credential issue on KIS's side, not a
code defect. Backfilling at scale right now would just generate more 403s,
so left QE-M2-03 PENDING pending KIS account/console verification.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Document the two-stage debugging pattern discovered while fixing
prepare-release.yml (Run #1996-2000):
1. PowerShell harness for workflow_dispatch trigger + poll-to-completion
- Working pattern for POST .../dispatches (204 = success)
- Known PowerShell/HttpClient limitation: cannot read error response
body via GetResponseStream() in PS7
2. SSH log-reading harness for when the Gitea API has no working
/logs endpoint (404 on job logs):
- Match runner container logs (task ID) to the triggered run
- Locate actions_log/{owner}/{repo}/{shard}/{taskId}.log.zst
- Stream-decompress with 'zstd -dc' and grep for 'Failure'/'exitcode'
3. Network debugging commands for dispatch 500s / stuck runners
(docker network inspect, restart timing, exec connectivity test)
4. Table of real failure patterns hit and their fixes (YAML multiline
notes, unset git identity, missing gh CLI in runner image)