V13-FE-011: finalize search list layout slice #32

Merged
kjh2064 merged 50 commits from docs/wbs-tracker-current-state into main 2026-08-09 02:58:25 +09:00
Owner

What changed

  • Finalized V13-FE-011 search/list layout and shared UI shell work.
  • Added the KBX design/reference foundation under docs/Design.
  • Preserved Playwright evidence and updated WBS/evidence tracking.

Validation

  • frontend: pnpm test — 33 files, 73 tests passed.
  • frontend: pnpm build — passed (vue-tsc and Vite production build).

Notes

  • Automatic ordering and KIS submission capabilities remain disabled.
## What changed - Finalized V13-FE-011 search/list layout and shared UI shell work. - Added the KBX design/reference foundation under docs/Design. - Preserved Playwright evidence and updated WBS/evidence tracking. ## Validation - frontend: pnpm test — 33 files, 73 tests passed. - frontend: pnpm build — passed (vue-tsc and Vite production build). ## Notes - Automatic ordering and KIS submission capabilities remain disabled.
kjh2064 added 50 commits 2026-08-09 02:58:13 +09:00
Renumbers the four 2026-08-07 slices (ApprovalWorkflow, AuditTrail,
TradeExecution, PortfolioReconciliation) to previously-unused VS-26..29,
leaving WBS_MASTER.csv's original VS-03/04/12/14 definitions (IngestMarketDataPIT,
ApplyCorporateActions, RankBuyCandidates, GenerateDailyRecommendations) untouched,
per docs/DECISIONS/ADR-WBS-001-slice-renumbering.md.

While investigating, found two things not yet resolved by this commit:
- DEBT-017 (duplicate ApprovalWorkflow implementation): the tested backend
  (ApprovalWorkflow/) is [DontRegister]'d dead code; the live one
  (Features/ApprovalWorkflow/, wired in Program.cs) has no dedicated tests.
  AEG-VS-26-01 downgraded from COMPLETED to BLOCKED in the tracker pending an
  architect decision on which implementation is canonical.
- Features/MarketData and Features/Portfolio (VS-03/04/05/08 Market Data
  Ingestion Dashboard, Portfolio Rebalance, Risk Metrics, Dashboard) are a
  third, already-implemented-and-tested body of work entirely absent from
  WBS_PROGRESS_TRACKER.csv. Flagged in CURRENT_ROADMAP.md as a follow-up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- scripts/dba/grant-migration-test-db-ownership.sql: for a DBA to run,
  fixes the kartsell_migration_test ownership regression blocking
  DbUpMigrationTests/DbUpRecoveryTests (12 tests) locally.
- docs/CURRENT/PHASE-1_APPROVAL_CHECKLIST.md +
  scripts/phase1/template-approve-versionset.sql: documents/templates the
  human maker-checker approval steps needed to freeze a VersionSet before
  Phase 1 shadow run can be re-queued. Does not perform any approval —
  every placeholder must be filled by a real, named maker and a different
  named checker. No automation should insert rows into dataset_manifest /
  model_version_registry / evidence_snapshot / release_evidence_bundle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Renumbers the four 2026-08-07 slices (ApprovalWorkflow, AuditTrail,
TradeExecution, PortfolioReconciliation) to previously-unused VS-26..29,
leaving WBS_MASTER.csv's original VS-03/04/12/14 definitions (IngestMarketDataPIT,
ApplyCorporateActions, RankBuyCandidates, GenerateDailyRecommendations) untouched,
per docs/DECISIONS/ADR-WBS-001-slice-renumbering.md.

While investigating, found two things not yet resolved by this commit:
- DEBT-017 (duplicate ApprovalWorkflow implementation): the tested backend
  (ApprovalWorkflow/) is [DontRegister]'d dead code; the live one
  (Features/ApprovalWorkflow/, wired in Program.cs) has no dedicated tests.
  AEG-VS-26-01 downgraded from COMPLETED to BLOCKED in the tracker pending an
  architect decision on which implementation is canonical.
- Features/MarketData and Features/Portfolio (VS-03/04/05/08 Market Data
  Ingestion Dashboard, Portfolio Rebalance, Risk Metrics, Dashboard) are a
  third, already-implemented-and-tested body of work entirely absent from
  WBS_PROGRESS_TRACKER.csv. Flagged in CURRENT_ROADMAP.md as a follow-up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- scripts/dba/grant-migration-test-db-ownership.sql: for a DBA to run,
  fixes the kartsell_migration_test ownership regression blocking
  DbUpMigrationTests/DbUpRecoveryTests (12 tests) locally.
- docs/CURRENT/PHASE-1_APPROVAL_CHECKLIST.md +
  scripts/phase1/template-approve-versionset.sql: documents/templates the
  human maker-checker approval steps needed to freeze a VersionSet before
  Phase 1 shadow run can be re-queued. Does not perform any approval —
  every placeholder must be filled by a real, named maker and a different
  named checker. No automation should insert rows into dataset_manifest /
  model_version_registry / evidence_snapshot / release_evidence_bundle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Centralize label, error, help, required, and ARIA relationships across core field wrappers. Preserve WBS evidence and keep the item IN_PROGRESS pending predecessor acceptance evidence.

Evidence: frontend pnpm typecheck; pnpm test (42/42); pnpm build.
Root cause (CURRENT_ROADMAP.md item #3): wwwroot/assets/* and
wwwroot/index.html under KArtSell.Host are 100% Vite build output (no
hand-authored files in there) but were committed to git. Every local
dotnet build re-triggers pnpm build via the BuildFrontend MSBuild
target, which produces new content-hashed filenames even when no
frontend source changed, and the old hashed files were never cleaned
up (4 of the 6 committed asset files were already orphaned/unreferenced
before this fix, confirmed by diffing wwwroot/index.html's script/link
tags against what was actually on disk).

Investigated whether the committed output was load-bearing for
deployment before picking a fix:
- .gitea/workflows/deploy.yml (the real production deploy path) already
  wipes wwwroot and rebuilds it fresh from pnpm build on every deploy,
  so the committed files were never actually used there.
- .gitea/workflows/ci.yml's `publish` job (Gitea Release zip) was the
  only place actually depending on the committed wwwroot contents,
  since it runs `dotnet publish` without ever building the frontend.

Given that, committing the hashed output was pure architectural
mistake with no deployment benefit, and the smaller/more correct fix
is to stop tracking it rather than bolt MSBuild Inputs/Outputs
incrementality onto the BuildFrontend target (which would also be
fragile: git checkouts/worktrees can normalize file mtimes in ways
that defeat timestamp-based up-to-date checks).

Fix:
- .gitignore: ignore src/KArtSell.Host/wwwroot/assets/ and
  wwwroot/index.html (generated by BuildFrontend target locally and by
  deploy.yml in production).
- git rm --cached the 7 previously-tracked generated files.
- ci.yml publish job: add the same pnpm install/build + wipe-and-copy
  step deploy.yml already uses, so the release zip still ships a real
  frontend build instead of losing it now that git no longer carries it.
- Left the BuildFrontend MSBuild target itself unchanged (still runs
  pnpm build on every local `dotnet build`) since re-running it is no
  longer a problem now that its output isn't tracked.

Verified (not just asserted):
- `dotnet build KArtSell.sln -c Release` run twice in a row: `git
  status`/`git diff --stat` identical after both runs (only the 9
  intentional lines in .gitignore/ci.yml), even though wwwroot/assets
  on disk got fresh hashed filenames both times.
- Reverted to pre-fix state and ran a single `dotnet build` with zero
  source changes: reproduced the bug exactly as described -
  wwwroot/index.html showed a 13-line diff and 2 new untracked hash
  files appeared, with the old stale ones left behind. Then restored
  the fix and re-verified the two-consecutive-build check above.
- `cd frontend && pnpm install --frozen-lockfile && pnpm typecheck &&
  pnpm build` all pass cleanly on their own.
- `dotnet test tests/KArtSell.ModelOperations.UnitTests` still 54/54
  passing after the build changes.

Separate, out-of-scope finding recorded in CURRENT_ROADMAP.md: ~130
frontend/src/**/*.js files compiled from .ts/.vue siblings (plus
tsconfig.tsbuildinfo, vite.config.js) are also committed and also
regenerate on every `pnpm build` via `vue-tsc -b`, because
tsconfig.json has no `noEmit: true`. Same class of problem, not fixed
here to keep this PR to one goal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Validate extensible WBS identity integrity instead of an obsolete fixed row count. Preserve actual vendor-boundary and adapter-contract evidence; status remains IN_PROGRESS pending predecessor acceptance evidence.
Document startup-only provider switching, immutable-artifact rollback, and mandatory visual/accessibility/performance evidence. Status remains IN_PROGRESS until rehearsal and predecessor evidence exist.
Make projection and watermark visible requirements, expose stale state accessibly, and add component regression coverage. Status remains IN_PROGRESS pending predecessor and UX evidence.
Adopt Features/ApprovalWorkflow/ (wired into Program.cs, reachable over
HTTP) as the sole VS-26 (formerly VS-03) maker-checker approval slice.
Delete the dead, [DontRegister]'d duplicate under
ApprovalWorkflow/ (Workstream H) and its dedicated test file, which had
been misleadingly credited with "20/20 tests PASS" while being
unreachable at runtime.

- Sql.cs: fix the same Dapper DateOnly-parameter-binding bug that was
  already found and fixed in the now-deleted implementation
  (commit 2ccf74c) but had not been ported to this one; InsertProposalAsync
  would have failed 100% of the time against a real database.
- tests/.../ApprovalWorkflow/ApprovalWorkflowTests.cs: new Handler+Sql+
  real-Postgres integration coverage (create/approve/activate role
  gating, maker!=checker separation of duties, evidence attachment,
  DateOnly round-trip, list filtering) replacing the deleted dead-code
  suite at the same path.
- ApprovalWorkflowPolicyTests.cs: extended (5->10 cases) rather than
  replaced, since it already tested the kept implementation's Policy.
- Program.cs: drop the reference comment to the deleted namespace.
- TECH_DEBT_REGISTER.md: DEBT-017 marked Completed (DB verification
  pending); corrected stale DEBT-023 to point at this resolution;
  registered two residual gaps discovered (not introduced) by this
  cleanup as DEBT-025 (no GET /approvals/{id}, evidence unreachable via
  HTTP) and DEBT-026 (no wired Draft->Proposed transition, so the
  approve/activate path is currently unreachable end-to-end via HTTP).
- WBS_PROGRESS_TRACKER.csv / CURRENT_ROADMAP.md: AEG-VS-26-01 kept
  BLOCKED, not COMPLETED — no PostgreSQL was reachable in this session
  (127.0.0.1:5432 connection refused), so the 8 new integration tests
  are unverified; only the 10 pure-Policy tests were confirmed passing.

Cherry-picked cedc8d7/8c777df from docs/wbs-tracker-current-state onto
this worktree branch first, to bring in the VS-26 renumbering and
ADR-WBS-001 that this task's brief assumed already existed.

dotnet build -c Release: 0 errors/0 warnings.
dotnet test --filter "FullyQualifiedName~ApprovalWorkflow" -c Release:
10 passed (Policy, no DB), 15 failed (DB connection refused - includes
6 unrelated pre-existing tests matched by the filter substring).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Keep action order while preventing disabled or busy actions from emitting a command. Preserve test evidence; status remains IN_PROGRESS pending predecessor acceptance.
Reject incomplete permission, version, concurrency, idempotency, and sensitive-column contracts. Preserve runtime regression evidence; status remains IN_PROGRESS pending predecessor acceptance.
Create one immutable request per user intent so retries forward the same key; preserve concurrency conflict handling and execution evidence.
Type mandatory states and prevent READY or FORBIDDEN from drifting out of the shared screen matrix.
Verify required field error relationships and busy command suppression; preserve actual test evidence while awaiting UX/QA artifacts.
Constrain sensitive fields to row keys and preserve generic resource-definition contracts.
Merges the isolated-worktree agent's resolution of TECH_DEBT_REGISTER.md
DEBT-017 (duplicate ApprovalWorkflow implementation) into this branch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

# Conflicts:
#	CURRENT_ROADMAP.md
#	docs/CURRENT/CATALOGS/WBS_PROGRESS_TRACKER.csv
#	src/KArtSell.Modules.ModelOperations/ApprovalWorkflow/README.md
Merges the isolated-worktree agent's fix: stop committing Vite-generated
wwwroot/assets output, add frontend build step to the ci.yml publish job
so release zips still ship a real build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

# Conflicts:
#	CURRENT_ROADMAP.md
DEBT-026 (high impact): ProposeForReviewHandler + POST /approvals/{id}/propose
wires ApprovalWorkflowPolicy.CanProposeForReview, which previously had no
Handler/Endpoint calling it. Before this, a proposal created via POST
/approvals could never reach Approved/Active through the running application
- the maker-checker gate was not completable end-to-end via HTTP.

DEBT-025 (medium impact): GetApprovalByIdEndpoint (GET /approvals/{id}) +
ApprovalWorkflowSql.GetEvidenceForProposalAsync make evidence attached during
approval (PBO/DSR/OOS artifact links) readable via HTTP instead of only by
querying model_operations.approval_evidence directly.

Both discovered while resolving DEBT-017 earlier the same session. 4 new
tests added. dotnet build -c Release clean. Not verified against a live
database (no SSH tunnel open in this environment) - see
TECH_DEBT_REGISTER.md and WBS_PROGRESS_TRACKER.csv AEG-VS-26-01 for the
honest verification status; do not mark COMPLETED until a real Postgres
run passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TradeExecution: TradeOutboxPublisher.PublishAsync replaced with
UpdateAndPublishAsync, which opens one connection/transaction, updates
trade status and writes the outbox message on it, then commits once.
Used by the 3 call sites that publish an event after a status update
(SubmitTradeHandler, PollTradeStatusHandler's FullyFilled branch,
ConfirmSettlementHandler).

PortfolioReconciliation: ReconcileTradeHandler now injects the
request-scoped IDbConnection (the same instance ReconciliationSql
already uses) instead of opening a second separate connection via
IDbConnectionFactory, begins one transaction shared by
ReconciliationEngine.ReconcileTradeAsync and the outbox writes, and
commits once. Required adding IDbTransaction-aware overloads of
GetHoldingAsync/UpsertHoldingAsync/InsertReconciliationLogAsync - the
read needed one too, since Npgsql throws if a command on a connection
with a pending transaction doesn't have it attached.

dotnet build KArtSell.sln -c Release: clean. Integration tests: 17
pure-logic tests pass, 13 DB-backed tests fail with the pre-existing
connection-refused error (no SSH tunnel in this environment) - the
transactional changes themselves are not yet verified against a live
database. Also corrected two WBS_PROGRESS_TRACKER.csv rows that
inaccurately said frontend UI work was "in progress" when the
background agents building VS-28/VS-29 UI had actually failed
(hit the session's spend limit) before committing anything.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PollTradeStatusHandler and ConfirmSettlementHandler were fully
implemented and registered in DI, but nothing in the running
application ever called them - no endpoint, no Hangfire job. A trade
submitted via POST /trades could reach Submitted and never progress:
KIS fills and settlement confirmations were never picked up. Same
class of gap as DEBT-026 (a complete handler with no caller).

Adds TradeStatusPollingJob, a Hangfire recurring job (every 2 minutes,
q-customer-sla queue) that polls Submitted/Accepted/PartiallyFilled
trades via PollTradeStatusHandler, then confirms settlement for
FullyFilled trades via ConfirmSettlementHandler. Registered in
Program.cs alongside the other recurring jobs.

dotnet build KArtSell.sln -c Release: clean. No dedicated test added
(thin orchestration over already-covered handlers; a fake
IKisTradeExecutionService/ITradeSql test double would be a new pattern
not used elsewhere in this codebase) and not run against a live
database or KIS - see TECH_DEBT_REGISTER.md DEBT-027.

Also corrected WBS_PROGRESS_TRACKER.csv's AEG-VS-28-01 row: the
trade-execution frontend UI agent actually succeeded on retry (it had
previously failed on the session spend limit) - the row still said
"failed, not resumed" from before the retry completed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DEBT-022 previously only checked AuditSql/TradeSql/SellDecisionSql
(where the bug was first found) and left PortfolioReconciliation/
ApprovalWorkflow explicitly "not yet checked". This pass enumerates
every jsonb/inet column across db/migrations/*.sql (case-insensitive,
since several use JSONB/INET uppercase) and checks each for a C#
writer.

PortfolioReconciliation has no jsonb/inet columns at all.
ApprovalWorkflow's one jsonb column was already cast correctly.
Several other jsonb columns belong to unimplemented slices (no writer
yet, so no current bug surface).

Found one new, real instance of the bug: OpenDartService.CacheResultAsync
inserted a JSON string into opendata.opendart_cache.data_json JSONB
without a cast - same 42804 failure mode as the already-documented
cases, just never previously exercised. Fixed with @dataJson::jsonb.

dotnet build KArtSell.sln -c Release: clean. Not run against a live
database this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Systematic sweep of every *Handler registered in Program.cs (same
method that found DEBT-026/027) found ActivateModelHandler was the
last orphan in Features/ApprovalWorkflow/: no POST /approvals/{id}/activate
endpoint existed, so an Approved proposal could never reach Active -
the entire point of this maker-checker slice.

While wiring it up, found the handler's original call would have
overwritten the checker's approved_by/approval_notes with the
activating SRE's identity (it passed userEmail through
UpdateProposalStatusAsync's approvedBy parameter), and never set
activated_by/activated_at at all despite those columns existing since
migration 0036. Added a dedicated ApprovalWorkflowSql.ActivateProposalAsync
that only touches activation-specific columns, and a regression test
asserting the checker's approval record survives activation unchanged.

Also documents DEBT-029 (discovered, not fixed - genuine cross-cutting
scope): LogAuditEventCommandHandler is never called by any other
slice, so VS-27's audit trail is empty in production regardless of
activity even though its own tests pass. Downgraded AEG-VS-27-01 from
COMPLETED to BLOCKED in the tracker to reflect that honestly.

dotnet build KArtSell.sln -c Release: clean. Not run against a live
database this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Evidence: Release targeted ScheduleOccurrencePlannerTests 2/2 passed; TRX SHA256 4CDD5098C0D49B642A869E35A77F31CB4BF4A9CB76F0B340F1C69EF58C7ED864. No scheduler was enabled.
Implements LATEST_ONLY, SKIP_MISSED, and ALL_WITH_LIMIT dispatch plans anchored to scheduledFor. Evidence: targeted Release tests 4/4 passed; TRX SHA256 DC28BE4F2FCF511D5859B9FC3A0ADDF8CE3A566262C9848F05B06D825EA944AD. Schedules remain disabled; DEC-083 is not resolved.
Carries scheduledFor, catch-up policy, and maxCatchUp from the scheduler through the request model and transactional outbox. Evidence: targeted Release tests 5/5 passed; TRX SHA256 C1BF3EF274702305A29673D5B6A1C3A98D08B1716DA3CD8CB0EE710B5E6C12E6. Schedules remain disabled.
Adds dispatch revision CAS to dispatched, skip, and release schedule mutations. Targeted Release evidence: 8/8 passed. PostgreSQL concurrency rehearsal remains required; WBS stays IN_PROGRESS.
Adds a lease-loss/reacquire integration rehearsal and fixes Dapper due-schedule materialization with an explicit row DTO. Evidence: PostgreSQL test 1/1 passed; TRX SHA256 49627FF0180034D2A7A1E4393448C73D337D918E7CE47EA9FC2BDB144FBBA833.
Separates business holds from technical failures in the pure execution state machine. Evidence: targeted Release tests 3/3 passed; TRX SHA256 2F2CD06B1DFD3F76F336A0636598553599CD05CF7FA82E477DB160425975085F.
Adds a pure, monotonic execution heartbeat and caller-supplied staleness cutoff without inventing alert thresholds. Evidence: targeted Release tests 5/5 passed; TRX SHA256 2ADBB526FAF6E5D924EB3F53C7E582E736199A59E0DA4E4FD25DCAA82A661BBC. WBS remains IN_PROGRESS pending approved alert contract.
Blocks submit, status, cancel, and settlement before HTTP or database writes and removes the KIS polling recurring job. Evidence: concrete adapter test 1/1 passed with zero HTTP calls. WBS remains IN_PROGRESS pending endpoint/startup override evidence.
kjh2064 merged commit a8ccf23d50 into main 2026-08-09 02:58:25 +09:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kjh2064/KArtSell.Aegis#32