@massu/core 1.12.0 → 1.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/dist/cli.js +64 -51
- package/dist/hooks/post-tool-use.js +1 -1
- package/dist/hooks/pre-compact.js +1 -1
- package/dist/hooks/pre-delete-check.js +5 -5
- package/dist/hooks/pre-tool-use-gate.js +5 -5
- package/dist/hooks/session-end.js +7 -6
- package/dist/hooks/session-start.js +2 -2
- package/dist/hooks/user-prompt.js +1 -1
- package/package.json +1 -1
- package/dist/detect/adapters/aspnet.js +0 -577
- package/dist/detect/adapters/go-chi.js +0 -561
- package/dist/detect/adapters/phoenix.js +0 -556
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,68 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.12.2] - 2026-05-18
|
|
8
|
+
|
|
9
|
+
**Security MEDIUM sweep (`plan-2026-05-18-security-medium-sweep`)**. Closes the 5 MEDIUM findings from the post-1.12.0 `massu-security-reviewer` audit-loop with structural drift-guards for each. M-1 IP_HASH_PEPPER consistency (silent-fallback vs throw class), M-2 webhook POST schema symmetry, M-3 Lemon Squeezy webhook idempotency parity with Stripe, M-4 v1 audit UUID echo redaction, M-5 SSO IdP host allowlist (precondition for SSO re-enable). New CR-51 + VR-PEPPER-GUARD + pattern-scanner Check 27.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **M-1 / CR-51 / VR-PEPPER-GUARD** — `website/src/lib/ip/pepper-guard.ts` exporting `requireIpHashPepper()` + `hashIpWithPepper(ip, { length: 16 | 32 })` as the SOLE allowed reader of the IP hash pepper env var. Production fail-closed via `MissingPepperError`; documented test override via `MASSU_TEST_ALLOW_EMPTY_PEPPER=1`. Closes the structural drift class where `evidence/[id]/download/route.ts:21` silent-fallback diverged from `license/activate/route.ts:34-40` throw.
|
|
14
|
+
- **M-2 / VR-SCHEMA-SYMMETRY** — `webhookCreateSchema` in `src/lib/validations.ts`, symmetric to `webhookUpdateSchema`. `description` capped at 500 chars on BOTH schemas (CR-9 bypass-prevention). `route-schema-symmetry.test.ts` drift-guard scans every `app/api/v1/**/route.ts` POST/PATCH/PUT handler for `*Schema.safeParse` invocation.
|
|
15
|
+
- **M-3 / VR-LS-IDEMPOTENCY** — migration `042_lemon_squeezy_webhook_events.sql` + `lemon_squeezy_event_apply(p_event_id, p_event_type, p_payload, ...)` RPC returning TEXT `processing_status` (`processed_ok` | `duplicate_ignored` | `permanent_failure` | `transient_failure`). Route handler maps each status to HTTP 200/200/422/500 — 422 stops LS retries on permanent failures (Stripe's BOOLEAN return can't carry this contract). Down migration shipped alongside (`.down.sql`) per §6.5 Rollback Plan.
|
|
16
|
+
- **M-4 / VR-V1-NO-UUID-LEAK** — `v1-error-response-no-uuid-leak.test.ts` drift-guard scanning every `app/api/v1/**/route.ts` source for caller-controlled UUID interpolation in error/note response surfaces (`apiError`, `note =`, etc.). `${auth.orgId}` self-echo explicitly permitted (caller's auth context already binds them).
|
|
17
|
+
- **M-5 / VR-SSO-IDP-ALLOWLIST** — `website/src/lib/sso/idp-allowlist.ts` with `SSO_IDP_HOSTS_BY_PROVIDER` constant + `validateSsoUrlAgainstProvider(provider, ssoUrl)` + `inferSsoProviderFromUrl(ssoUrl)`. TLD-aware wildcard host match (`*.okta.com` does NOT match `evil-okta.com`); HTTPS-only scheme enforcement. Covers Okta, Auth0, Azure AD (microsoftonline.com + .us), Google Workspace. Generic OIDC deferred to `plan-B.3-followup` SSO re-enable.
|
|
18
|
+
- **`MASSU_SSO_ALLOWLIST_LOG_ONLY` env-flag** for the M-5 staged rollout — `isSsoAllowlistLogOnly()` in `sso-flag.ts`. Operator runs 24h log-only post-deploy to monitor false-positives before flipping to enforcing.
|
|
19
|
+
- **`scripts/massu-pattern-scanner.sh` Check 27** — bash drift-guard for security-sensitive env-var patterns. 27a flags raw `process.env.<NAME>_PEPPER` outside `lib/<purpose>/<purpose>-guard.ts`; 27b flags any `process.env.<NAME>_(PEPPER|SECRET|KEY) ?? <literal>` silent-fallback adjacent to such reads (framework-platform keys exempt).
|
|
20
|
+
- **CR-51** canonical rule in `.claude/CLAUDE.md`: security-sensitive env vars must use a dedicated guard helper. Three-layer enforcement: pattern-scanner Check 27 + vitest drift-guard + the guard helper is the ONLY allowed reader.
|
|
21
|
+
- 5 new vitest drift-guards: `ip-pepper-guard-usage.test.ts`, `route-schema-symmetry.test.ts`, `lemon-squeezy-event-atomic.test.ts`, `v1-error-response-no-uuid-leak.test.ts`, `sso-idp-allowlist.test.ts` (+23 happy/negative/integration cases for M-5 alone).
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **Lemon Squeezy webhook route (`src/app/api/lemon-squeezy/webhook/route.ts`)** — 4 handlers (`handleOrderCreated`, `handleLicenseKeyCreated`, `handleOrderRefunded`, `handleSubscriptionCancelled`) refactored to dispatch through `lemon_squeezy_event_apply` RPC. Direct `from('book_purchases').insert` / `from('organizations').update` calls REMOVED from the route. Pre-RPC test-mode mismatch rejection now returns `permanent_failure` (HTTP 422) instead of throwing.
|
|
26
|
+
- **`src/app/api/v1/audit/route.ts:66`** — `${actor}` UUID echo dropped from non-empty-org-no-rows note. New message: "No audit entries for the actor filter in this org. Verify the user is a member of org ${auth.orgId}." Eliminates the UUID-existence-probe side-channel for authenticated API-key holders.
|
|
27
|
+
- **`src/app/api/sso/route.ts`** — invokes `inferSsoProviderFromUrl(ssoConfig.sso_url)` before constructing `redirect_url`. Non-allowlisted host returns 502 with `X-SSO-Validation-Failure: idp-host-not-allowlisted` (or logs-only under `MASSU_SSO_ALLOWLIST_LOG_ONLY=1`).
|
|
28
|
+
- **`src/app/api/sso/callback/route.ts:exchangeOidcCode`** — same allowlist guard applied BEFORE any outbound `fetch()` to the IdP token endpoint. Closes the SSRF-to-IdP vector at the callback layer (P5-007).
|
|
29
|
+
- **`scripts/massu-security-scanner.sh` Check 6** — RLS coverage scanner now excludes `*.down.sql` rollback scripts (CR-46 structural fix; the literal "CREATE TABLE" only appears in their explanatory comments).
|
|
30
|
+
- **`website/src/data/stats.ts`** — Database Tables 44 → 45 (new `lemon_squeezy_webhook_events`), Canonical Rules 16 → 17 (new CR-51). Marketing count drift-guard covers both.
|
|
31
|
+
- **`website/src/__tests__/changelog-parse.test.ts:EXPECTED_COUNT`** bumped 40 → 41.
|
|
32
|
+
- **`website/src/__tests__/migration-grant-discipline.test.ts:SERVICE_ROLE_ONLY_TABLES`** adds `lemon_squeezy_webhook_events: '042_lemon_squeezy_webhook_events.sql'`.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Pre-existing `plan-token-changelog-coverage.test.ts` PTCC-03 failure surfaced during the loop — 3 post-tag chore-commit plan-tokens (`plan-stage-d-medium-sweep`, `plan-stage-e-low-info-sweep`, `plan-2026-05-16-prelaunch-audit`) added to the documented-divergence allowlist with the same rationale pattern as the existing `plan-stage-c-high-batch` entry.
|
|
37
|
+
|
|
38
|
+
## [1.12.1] - 2026-05-18
|
|
39
|
+
|
|
40
|
+
**Pre-push ↔ CI parity (`plan-2026-05-18-pre-push-ci-parity`)**. Closes the structural drift class surfaced 2026-05-18 when SHA `b26fbb1` passed `pre-push-light` locally but failed CI on 4 distinct gates spread across 3 separate workflow YAMLs (`@massu/types/dist` missing → `ci.yml`, `eslint-rules/` missing from `PUBLIC_DIRS` → `sync-check.yml`, `diff-commands-vs-docs.sh` hardcoded path → `sync-check.yml`, Tarball E2E adapter list stale → `ci.yml`). The two operator-pushed fix attempts `8c6b843` + `d3164f7` fixed the specific instances but left the bug class wide open. This release closes the CLASS via three-layer enforcement.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **CR-50 / VR-CI-PARITY** — structural pre-push ↔ CI parity drift-guard. Every multi-line shell block (>5 lines) in ANY `.github/workflows/*.yml` (excluding `*.public.yml` mirrors + 6 INFRASTRUCTURE/SECURITY workflows in `WORKFLOW_FILE_EXCLUSIONS`) lives in `scripts/ci-<name>.sh`; every such script is called from `scripts/pre-push-light.sh` OR carries `# CI-ONLY:` opt-out + entry in `CI_ONLY_SCRIPTS` allowlist. Three-layer enforcement: vitest drift-guard `packages/core/src/__tests__/ci-prepush-parity.test.ts` (7 cases, including byte-equivalence mirror-enforcement between TS test sets and bash scanner arrays) + pattern-scanner Check 26 + workspace-build-freshness step `[12/15]`.
|
|
45
|
+
- **`scripts/ci-tarball-e2e.sh`** — extracted Tarball E2E adapter-pack verification. Adapter list filesystem-derived (`find packages/adapter-*`); supports `--quick` mode for pre-push-light.
|
|
46
|
+
- **`scripts/ci-sync-check.sh`** — extracted public-mirror sync verification with `mktemp -d` + `trap cleanup EXIT INT TERM` safety contract; called from both `sync-check.yml` and pre-push-light step `[13/15]`. Secrets scan extended to cover ALL file types (not just `.ts`+`.md`) AND added `rk_test_/rk_live_` restricted-key + `whsec_` webhook-secret regex variants.
|
|
47
|
+
- **`scripts/ci-fresh-install.sh`** (CI-ONLY) — `init --ci` fixture runner with `local` + `published` modes via `$2`. Fixture-name validated against `^[a-z][a-z0-9_-]*$` regex to prevent path traversal.
|
|
48
|
+
- **`scripts/ci-config-drift.sh`** (CI-ONLY) — workspace-shadow-avoiding scratch-dir setup for `massu config check-drift`.
|
|
49
|
+
- **`scripts/lib/mtime-helper.sh`** — cross-platform BSD/GNU `stat` shim with python3 fallback. Sourced by `pre-push-light.sh` step `[12/15]` Workspace Build Freshness.
|
|
50
|
+
- **`scripts/test-ci-parity-regression.sh`** — AC-PARITY-REGRESSION automated test (ephemeral `git clone --no-local` + `git revert 8c6b843 d3164f7` + `npm ci` + pre-push-light exit-code assertion). Cited markers: `PARITY-REGRESSION-TEST: PASS|FAIL|ABORT`.
|
|
51
|
+
- 5 new `pre-push-light.sh` steps: `[0/15]` Clean-state simulation (opt-in via `MASSU_PREPUSH_CLEAN=1`), `[12/15]` Workspace Build Freshness, `[13/15]` Sync Check (auto-gated on `packages/`+`scripts/`+`CHANGELOG.md`+...), `[14/15]` Tarball E2E quick, `[15/15]` Config Drift.
|
|
52
|
+
- 4 bypass env-vars threaded with audit-trail stderr markers mirroring CR-48 precedent: `MASSU_PREPUSH_CLEAN`, `MASSU_SKIP_NEW_STEPS`, `MASSU_PREPUSH_SYNC_CHECK`, `MASSU_SYNC_PUBLIC_CHECK_ONLY`.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- **`scripts/pre-push-light.sh`** renumbered from `N/11` to `N/15` label scheme (16 total labels — Plan-Token Changelog Currency REMOVED per P2-006 iter-5 resolution; absorbed by `changelog-parse.test.ts` EXPECTED_COUNT drift-guard running via `[6/15] Tests`). `[9/15] Deploy Staleness` parser fixed to scan for first `PASS:|SKIP:|WARN:` line rather than first log line (pre-existing minor bug masked by stderr/stdout merging — pre-push-light now correctly shows SKIP under `MASSU_SKIP_DEPLOY_STALENESS_CHECK=1`).
|
|
57
|
+
- **`scripts/sync-public.sh`** adds `check_public_dirs_completeness()` drift-guard catching future `PUBLIC_DIRS` omissions structurally (greps cross-package test imports). New `MASSU_SYNC_PUBLIC_CHECK_ONLY=1` env-var runs drift-guard then exits 0 with no filesystem side-effects (AC-12 contract).
|
|
58
|
+
- **`.github/workflows/{ci,sync-check,fresh-install-matrix,massu-config-drift}.yml`** — 4 in-scope workflows now delegate to `scripts/ci-*.sh` (thin orchestration); 7 excluded workflows remain inline with per-entry justification comments in `WORKFLOW_FILE_EXCLUSIONS`.
|
|
59
|
+
- **`scripts/massu-pattern-scanner.sh`** adds Check 26 (Pre-push ↔ CI parity). Awk regex covers all YAML block-scalar variants (`|`, `|-`, `|+`, `>`, `>-`, `>+`) — prior `|` only would silently bypass.
|
|
60
|
+
- **`.claude/CLAUDE.md`** adds CR-50 row + VR-CI-PARITY row + inline `### CR-50: Pre-Push Must Mirror CI` block.
|
|
61
|
+
- **`website/CHANGELOG.md`** synced to root CHANGELOG.md byte-equal (drift-guard `website-changelog-matches-root.test.ts`).
|
|
62
|
+
- **`website/src/__tests__/changelog-parse.test.ts:EXPECTED_COUNT`** bumped 39 → 40.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- Closes the 2026-05-18 incident class (4 CI-only failure modes on SHAs `b26fbb1`, `8c6b843`, `d3164f7`).
|
|
67
|
+
- `scripts/pre-push-light.sh` step `[9/15]` deploy-staleness status parser pre-existing bug — first log line was the stderr audit-trail marker, not the stdout PASS/SKIP line (CR-9 fix surfaced during multi-perspective review).
|
|
68
|
+
|
|
7
69
|
## [1.12.0] - 2026-05-17
|
|
8
70
|
|
|
9
71
|
**Stage E — LOW + INFO sweep (parent plan `plan-2026-05-16-prelaunch-audit`, sub-plan `plan-stage-e-low-info-sweep`)**. Closes the 14-agent pre-launch audit by addressing the residual 71 LOW + INFO items not handled in Stages A–D. Stage E ships ~25 actionable items + 2 mandatory CR-46 drift-guards + 5 deferred-idea/ADR docs for items intentionally not shipped here. Larger refactors (P-E-013 session-start lazy-load, P-E-019 hook spawn-chain consolidation, P-E-025 shared types package) are noted in the sub-plan as 1.12.x follow-up. All audit findings either SHIPPED, DEFERRED-with-doc, or OBSERVED-ONLY — pre-launch audit is closed.
|
package/dist/cli.js
CHANGED
|
@@ -1173,7 +1173,7 @@ function enqueueSyncPayload(db, payload) {
|
|
|
1173
1173
|
}
|
|
1174
1174
|
function dequeuePendingSync(db, limit = 10) {
|
|
1175
1175
|
const stale = db.prepare(
|
|
1176
|
-
"SELECT id, retry_count, last_error FROM pending_sync WHERE retry_count >= 10"
|
|
1176
|
+
"SELECT id, retry_count, last_error FROM pending_sync WHERE retry_count >= 10 LIMIT 10000"
|
|
1177
1177
|
).all();
|
|
1178
1178
|
if (stale.length > 0) {
|
|
1179
1179
|
const ids = stale.map((s) => s.id);
|
|
@@ -1412,16 +1412,17 @@ function getSessionsByTask(db, taskId) {
|
|
|
1412
1412
|
SELECT session_id, status, started_at, ended_at, plan_phase
|
|
1413
1413
|
FROM sessions WHERE task_id = ?
|
|
1414
1414
|
ORDER BY started_at_epoch DESC
|
|
1415
|
+
LIMIT 10000
|
|
1415
1416
|
`).all(taskId);
|
|
1416
1417
|
}
|
|
1417
1418
|
function getCrossTaskProgress(db, taskId) {
|
|
1418
1419
|
const sessions = db.prepare(`
|
|
1419
|
-
SELECT session_id FROM sessions WHERE task_id = ?
|
|
1420
|
+
SELECT session_id FROM sessions WHERE task_id = ? LIMIT 10000
|
|
1420
1421
|
`).all(taskId);
|
|
1421
1422
|
const merged = {};
|
|
1422
1423
|
for (const session of sessions) {
|
|
1423
1424
|
const summaries = db.prepare(`
|
|
1424
|
-
SELECT plan_progress FROM session_summaries WHERE session_id = ?
|
|
1425
|
+
SELECT plan_progress FROM session_summaries WHERE session_id = ? LIMIT 10000
|
|
1425
1426
|
`).all(session.session_id);
|
|
1426
1427
|
for (const summary of summaries) {
|
|
1427
1428
|
try {
|
|
@@ -19667,7 +19668,7 @@ function traceImports(startFile, dataDb, visited, components, hooks, maxDepth =
|
|
|
19667
19668
|
if (maxDepth <= 0 || visited.has(startFile)) return;
|
|
19668
19669
|
visited.add(startFile);
|
|
19669
19670
|
const imports = dataDb.prepare(
|
|
19670
|
-
`SELECT target_file, imported_names FROM ${t("imports")} WHERE source_file =
|
|
19671
|
+
`SELECT target_file, imported_names FROM ${t("imports")} WHERE source_file = ? LIMIT 10000`
|
|
19671
19672
|
).all(startFile);
|
|
19672
19673
|
for (const imp of imports) {
|
|
19673
19674
|
const target = imp.target_file;
|
|
@@ -19704,7 +19705,7 @@ function findTablesFromRouters(routerNames, dataDb) {
|
|
|
19704
19705
|
const tables = /* @__PURE__ */ new Set();
|
|
19705
19706
|
for (const routerName of routerNames) {
|
|
19706
19707
|
const procs = dataDb.prepare(
|
|
19707
|
-
`SELECT DISTINCT router_file FROM ${t("trpc_procedures")} WHERE router_name =
|
|
19708
|
+
`SELECT DISTINCT router_file FROM ${t("trpc_procedures")} WHERE router_name = ? LIMIT 10000`
|
|
19708
19709
|
).all(routerName);
|
|
19709
19710
|
for (const proc of procs) {
|
|
19710
19711
|
const absPath = ensureWithinRoot(resolve27(getProjectRoot(), proc.router_file), getProjectRoot());
|
|
@@ -19727,7 +19728,7 @@ function findTablesFromRouters(routerNames, dataDb) {
|
|
|
19727
19728
|
function buildPageDeps(dataDb, codegraphDb) {
|
|
19728
19729
|
dataDb.exec(`DELETE FROM ${t("page_deps")}`);
|
|
19729
19730
|
const pages = codegraphDb.prepare(
|
|
19730
|
-
"SELECT path FROM files WHERE path LIKE 'src/app/%/page.tsx' OR path = 'src/app/page.tsx'"
|
|
19731
|
+
"SELECT path FROM files WHERE path LIKE 'src/app/%/page.tsx' OR path = 'src/app/page.tsx' LIMIT 10000"
|
|
19731
19732
|
).all();
|
|
19732
19733
|
const insertStmt = dataDb.prepare(
|
|
19733
19734
|
`INSERT INTO ${t("page_deps")} (page_file, route, portal, components, hooks, routers, tables_touched) VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
@@ -19776,7 +19777,7 @@ function findAffectedPages(dataDb, file) {
|
|
|
19776
19777
|
const directPage = getPageChain(dataDb, file);
|
|
19777
19778
|
if (directPage) return [directPage];
|
|
19778
19779
|
const importers = dataDb.prepare(
|
|
19779
|
-
`SELECT source_file FROM ${t("imports")} WHERE target_file =
|
|
19780
|
+
`SELECT source_file FROM ${t("imports")} WHERE target_file = ? LIMIT 5000`
|
|
19780
19781
|
).all(file);
|
|
19781
19782
|
const affectedFiles = /* @__PURE__ */ new Set([file, ...importers.map((i) => i.source_file)]);
|
|
19782
19783
|
let frontier = [...importers.map((i) => i.source_file)];
|
|
@@ -19787,7 +19788,7 @@ function findAffectedPages(dataDb, file) {
|
|
|
19787
19788
|
const next = [];
|
|
19788
19789
|
for (const f2 of frontier) {
|
|
19789
19790
|
const upstreamImporters = dataDb.prepare(
|
|
19790
|
-
`SELECT source_file FROM ${t("imports")} WHERE target_file =
|
|
19791
|
+
`SELECT source_file FROM ${t("imports")} WHERE target_file = ? LIMIT 5000`
|
|
19791
19792
|
).all(f2);
|
|
19792
19793
|
for (const imp of upstreamImporters) {
|
|
19793
19794
|
if (!visited.has(imp.source_file)) {
|
|
@@ -19838,7 +19839,7 @@ function buildMiddlewareTree(dataDb) {
|
|
|
19838
19839
|
while (queue.length > 0) {
|
|
19839
19840
|
const current = queue.shift();
|
|
19840
19841
|
const imports = dataDb.prepare(
|
|
19841
|
-
`SELECT target_file FROM ${t("imports")} WHERE source_file =
|
|
19842
|
+
`SELECT target_file FROM ${t("imports")} WHERE source_file = ? LIMIT 10000`
|
|
19842
19843
|
).all(current);
|
|
19843
19844
|
for (const imp of imports) {
|
|
19844
19845
|
if (!visited.has(imp.target_file) && imp.target_file.startsWith("src/")) {
|
|
@@ -19926,7 +19927,7 @@ function findCrossDomainImports(dataDb) {
|
|
|
19926
19927
|
const srcPrefix = config.paths.source;
|
|
19927
19928
|
const srcPattern = srcPrefix + "/%";
|
|
19928
19929
|
const imports = dataDb.prepare(
|
|
19929
|
-
`SELECT source_file, target_file FROM ${t("imports")} WHERE source_file LIKE ? AND target_file LIKE
|
|
19930
|
+
`SELECT source_file, target_file FROM ${t("imports")} WHERE source_file LIKE ? AND target_file LIKE ? LIMIT 10000`
|
|
19930
19931
|
).all(srcPattern, srcPattern);
|
|
19931
19932
|
const crossings = [];
|
|
19932
19933
|
for (const imp of imports) {
|
|
@@ -21491,7 +21492,7 @@ function handleDetail(args2, db) {
|
|
|
21491
21492
|
if (!ids || ids.length === 0) return text("Error: ids array is required");
|
|
21492
21493
|
const placeholders = ids.map(() => "?").join(",");
|
|
21493
21494
|
const observations = db.prepare(
|
|
21494
|
-
`SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch ASC`
|
|
21495
|
+
`SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch ASC LIMIT 10000`
|
|
21495
21496
|
).all(...ids);
|
|
21496
21497
|
if (observations.length === 0) {
|
|
21497
21498
|
return text("No observations found for the given IDs.");
|
|
@@ -22399,7 +22400,7 @@ function getFeatureImpact(db, filePaths) {
|
|
|
22399
22400
|
const affectedFeatureIds = /* @__PURE__ */ new Set();
|
|
22400
22401
|
for (const filePath of filePaths) {
|
|
22401
22402
|
const links = db.prepare(
|
|
22402
|
-
`SELECT feature_id FROM ${t("sentinel_components")} WHERE component_file =
|
|
22403
|
+
`SELECT feature_id FROM ${t("sentinel_components")} WHERE component_file = ? LIMIT 10000`
|
|
22403
22404
|
).all(filePath);
|
|
22404
22405
|
for (const link of links) {
|
|
22405
22406
|
affectedFeatureIds.add(link.feature_id);
|
|
@@ -22412,7 +22413,7 @@ function getFeatureImpact(db, filePaths) {
|
|
|
22412
22413
|
const feature = getFeatureById(db, featureId);
|
|
22413
22414
|
if (!feature || feature.status !== "active") continue;
|
|
22414
22415
|
const allComponents = db.prepare(
|
|
22415
|
-
`SELECT component_file, is_primary FROM ${t("sentinel_components")} WHERE feature_id =
|
|
22416
|
+
`SELECT component_file, is_primary FROM ${t("sentinel_components")} WHERE feature_id = ? LIMIT 10000`
|
|
22416
22417
|
).all(featureId);
|
|
22417
22418
|
const affected = allComponents.filter((c2) => fileSet.has(c2.component_file));
|
|
22418
22419
|
const remaining = allComponents.filter((c2) => !fileSet.has(c2.component_file));
|
|
@@ -23086,6 +23087,7 @@ function scanTrpcProcedures(dataDb) {
|
|
|
23086
23087
|
SELECT router_name, procedure_name, procedure_type, router_file
|
|
23087
23088
|
FROM ${t("trpc_procedures")}
|
|
23088
23089
|
ORDER BY router_name, procedure_name
|
|
23090
|
+
LIMIT 100000
|
|
23089
23091
|
`).all();
|
|
23090
23092
|
for (const proc of procedures) {
|
|
23091
23093
|
const subdomain = inferSubdomain(proc.router_name, proc.procedure_name);
|
|
@@ -23128,6 +23130,7 @@ function scanPageRoutes(dataDb) {
|
|
|
23128
23130
|
SELECT page_file, route, portal, components, hooks, routers
|
|
23129
23131
|
FROM ${t("page_deps")}
|
|
23130
23132
|
ORDER BY route
|
|
23133
|
+
LIMIT 100000
|
|
23131
23134
|
`).all();
|
|
23132
23135
|
for (const page of pages) {
|
|
23133
23136
|
const domain = inferDomain(page.route);
|
|
@@ -23315,7 +23318,7 @@ function calculateQualityScore(db, sessionId) {
|
|
|
23315
23318
|
const weights = getWeights();
|
|
23316
23319
|
const categories = getCategories();
|
|
23317
23320
|
const observations = db.prepare(
|
|
23318
|
-
"SELECT type, detail FROM observations WHERE session_id = ?"
|
|
23321
|
+
"SELECT type, detail FROM observations WHERE session_id = ? LIMIT 10000"
|
|
23319
23322
|
).all(sessionId);
|
|
23320
23323
|
let score = 50;
|
|
23321
23324
|
const breakdown = Object.fromEntries(
|
|
@@ -23357,6 +23360,7 @@ function backfillQualityScores(db) {
|
|
|
23357
23360
|
FROM sessions s
|
|
23358
23361
|
LEFT JOIN session_quality_scores q ON s.session_id = q.session_id
|
|
23359
23362
|
WHERE q.session_id IS NULL
|
|
23363
|
+
LIMIT 100000
|
|
23360
23364
|
`).all();
|
|
23361
23365
|
let backfilled = 0;
|
|
23362
23366
|
for (const session of sessions) {
|
|
@@ -23455,6 +23459,7 @@ function handleQualityTrend(args2, db, retried = false) {
|
|
|
23455
23459
|
FROM session_quality_scores
|
|
23456
23460
|
WHERE created_at >= datetime('now', ?)
|
|
23457
23461
|
ORDER BY created_at ASC
|
|
23462
|
+
LIMIT 100000
|
|
23458
23463
|
`).all(`-${days} days`);
|
|
23459
23464
|
if (scores.length === 0) {
|
|
23460
23465
|
if (!retried) {
|
|
@@ -23490,6 +23495,7 @@ function handleQualityReport(args2, db, retried = false) {
|
|
|
23490
23495
|
SELECT score, security_score, architecture_score, coupling_score, test_score, rule_compliance_score
|
|
23491
23496
|
FROM session_quality_scores
|
|
23492
23497
|
WHERE created_at >= datetime('now', ?)
|
|
23498
|
+
LIMIT 10000
|
|
23493
23499
|
`).all(`-${days} days`);
|
|
23494
23500
|
if (scores.length === 0) {
|
|
23495
23501
|
if (!retried) {
|
|
@@ -23976,7 +23982,7 @@ function queryAuditLog(db, options) {
|
|
|
23976
23982
|
}
|
|
23977
23983
|
function getFileChain(db, filePath) {
|
|
23978
23984
|
return db.prepare(
|
|
23979
|
-
"SELECT * FROM audit_log WHERE file_path = ? ORDER BY timestamp ASC"
|
|
23985
|
+
"SELECT * FROM audit_log WHERE file_path = ? ORDER BY timestamp ASC LIMIT 10000"
|
|
23980
23986
|
).all(filePath);
|
|
23981
23987
|
}
|
|
23982
23988
|
function getAuditToolDefinitions() {
|
|
@@ -24456,6 +24462,7 @@ function handleValidationReport(args2, db) {
|
|
|
24456
24462
|
FROM validation_results
|
|
24457
24463
|
WHERE created_at >= datetime('now', ?)
|
|
24458
24464
|
ORDER BY created_at DESC
|
|
24465
|
+
LIMIT 100000
|
|
24459
24466
|
`).all(`-${days} days`);
|
|
24460
24467
|
if (results.length === 0) {
|
|
24461
24468
|
return text9(`No validation results found in the last ${days} days. Run ${p10("validation_check")} { file: "src/path/to/file.ts" } on specific files to generate validation data, or try a longer time range with { days: 90 }.`);
|
|
@@ -24866,6 +24873,7 @@ function handleSecurityScore(args2, db) {
|
|
|
24866
24873
|
SELECT file_path, risk_score, findings FROM security_scores
|
|
24867
24874
|
WHERE session_id = ?
|
|
24868
24875
|
ORDER BY risk_score DESC
|
|
24876
|
+
LIMIT 10000
|
|
24869
24877
|
`).all(sessionId);
|
|
24870
24878
|
if (scores.length === 0) {
|
|
24871
24879
|
return text11(`No security scores for session ${sessionId.slice(0, 8)}... Security scores are generated when files are scanned. Try: ${p12("security_score")} { file_path: "src/server/api/routers/example.ts" } to scan a file, or ${p12("security_heatmap")} {} to see all scanned files.`);
|
|
@@ -25283,6 +25291,7 @@ function detectConflicts(db, daysBack = 7) {
|
|
|
25283
25291
|
AND so1.created_at >= datetime('now', ?)
|
|
25284
25292
|
AND so2.created_at >= datetime('now', ?)
|
|
25285
25293
|
GROUP BY so1.file_path, so1.developer_id, so2.developer_id
|
|
25294
|
+
LIMIT 10000
|
|
25286
25295
|
`).all(`-${daysBack} days`, `-${daysBack} days`);
|
|
25287
25296
|
return conflicts.map((c2) => ({
|
|
25288
25297
|
filePath: c2.file_path,
|
|
@@ -25432,6 +25441,7 @@ function handleTeamExpertise(args2, db) {
|
|
|
25432
25441
|
FROM developer_expertise
|
|
25433
25442
|
WHERE module = ?
|
|
25434
25443
|
ORDER BY expertise_score DESC
|
|
25444
|
+
LIMIT 10000
|
|
25435
25445
|
`).all(targetModule);
|
|
25436
25446
|
if (experts.length === 0) {
|
|
25437
25447
|
return text13(`No expertise data for module "${targetModule}". Expertise builds as developers work on files in this module across sessions. Try: ${p14("team_expertise")} {} to see all modules with tracked expertise.`);
|
|
@@ -25609,6 +25619,7 @@ function handleRegressionCheck(_args, db) {
|
|
|
25609
25619
|
FROM feature_health
|
|
25610
25620
|
WHERE modifications_since_test > 0
|
|
25611
25621
|
ORDER BY modifications_since_test DESC
|
|
25622
|
+
LIMIT 10000
|
|
25612
25623
|
`).all();
|
|
25613
25624
|
if (recentlyModified.length === 0) {
|
|
25614
25625
|
return text14(`No features have been modified since their last test run. Low regression risk. Use ${p15("feature_health")} {} to see the full feature health dashboard.`);
|
|
@@ -26516,7 +26527,7 @@ function handleRule(db, args2) {
|
|
|
26516
26527
|
}
|
|
26517
26528
|
if (withIncidents) {
|
|
26518
26529
|
const edges = db.prepare(
|
|
26519
|
-
"SELECT source_id FROM knowledge_edges WHERE target_type = 'cr' AND target_id = ? AND source_type = 'incident'"
|
|
26530
|
+
"SELECT source_id FROM knowledge_edges WHERE target_type = 'cr' AND target_id = ? AND source_type = 'incident' LIMIT 5000"
|
|
26520
26531
|
).all(ruleId);
|
|
26521
26532
|
if (edges.length > 0) {
|
|
26522
26533
|
lines.push("### Related Incidents");
|
|
@@ -26533,7 +26544,7 @@ function handleRule(db, args2) {
|
|
|
26533
26544
|
}
|
|
26534
26545
|
} else if (keyword) {
|
|
26535
26546
|
const rules = db.prepare(
|
|
26536
|
-
"SELECT * FROM knowledge_rules WHERE rule_text LIKE ? OR rule_id LIKE ? ORDER BY rule_id"
|
|
26547
|
+
"SELECT * FROM knowledge_rules WHERE rule_text LIKE ? OR rule_id LIKE ? ORDER BY rule_id LIMIT 1000"
|
|
26537
26548
|
).all(`%${keyword}%`, `%${keyword}%`);
|
|
26538
26549
|
lines.push(`## Rules matching "${keyword}" (${rules.length} found)`);
|
|
26539
26550
|
lines.push("");
|
|
@@ -26573,7 +26584,7 @@ function handleIncident(db, args2) {
|
|
|
26573
26584
|
if (incident.user_quote) lines.push(`| **User Quote** | ${incident.user_quote.replace(/\|/g, "\\|")} |`);
|
|
26574
26585
|
lines.push("");
|
|
26575
26586
|
const edges = db.prepare(
|
|
26576
|
-
"SELECT target_id FROM knowledge_edges WHERE source_type = 'incident' AND source_id = ? AND target_type = 'cr'"
|
|
26587
|
+
"SELECT target_id FROM knowledge_edges WHERE source_type = 'incident' AND source_id = ? AND target_type = 'cr' LIMIT 5000"
|
|
26577
26588
|
).all(String(incidentNum));
|
|
26578
26589
|
if (edges.length > 0) {
|
|
26579
26590
|
lines.push("### Linked Rules");
|
|
@@ -26618,7 +26629,7 @@ function handleSchemaCheck(db, args2) {
|
|
|
26618
26629
|
const lines = [];
|
|
26619
26630
|
if (table) {
|
|
26620
26631
|
const mismatches = db.prepare(
|
|
26621
|
-
"SELECT * FROM knowledge_schema_mismatches WHERE table_name = ?"
|
|
26632
|
+
"SELECT * FROM knowledge_schema_mismatches WHERE table_name = ? LIMIT 1000"
|
|
26622
26633
|
).all(table);
|
|
26623
26634
|
if (mismatches.length > 0) {
|
|
26624
26635
|
lines.push(`## Schema Mismatches for \`${table}\``);
|
|
@@ -26636,7 +26647,7 @@ function handleSchemaCheck(db, args2) {
|
|
|
26636
26647
|
}
|
|
26637
26648
|
if (column) {
|
|
26638
26649
|
const mismatches = db.prepare(
|
|
26639
|
-
"SELECT * FROM knowledge_schema_mismatches WHERE wrong_column = ?"
|
|
26650
|
+
"SELECT * FROM knowledge_schema_mismatches WHERE wrong_column = ? LIMIT 1000"
|
|
26640
26651
|
).all(column);
|
|
26641
26652
|
if (mismatches.length > 0) {
|
|
26642
26653
|
if (lines.length > 0) lines.push("");
|
|
@@ -26675,7 +26686,7 @@ function handlePattern(db, args2) {
|
|
|
26675
26686
|
`patterns-quickref`
|
|
26676
26687
|
];
|
|
26677
26688
|
const docs = db.prepare(
|
|
26678
|
-
"SELECT id, file_path, title FROM knowledge_documents WHERE category = 'patterns' OR category = 'reference' OR category = 'root'"
|
|
26689
|
+
"SELECT id, file_path, title FROM knowledge_documents WHERE category = 'patterns' OR category = 'reference' OR category = 'root' LIMIT 1000"
|
|
26679
26690
|
).all();
|
|
26680
26691
|
const relevantDocs = docs.filter(
|
|
26681
26692
|
(d2) => domainPatterns.some((pat) => d2.file_path.toLowerCase().includes(pat.toLowerCase()))
|
|
@@ -26720,7 +26731,7 @@ function handlePattern(db, args2) {
|
|
|
26720
26731
|
if (!topic && relevantDocs.length > 0) {
|
|
26721
26732
|
for (const doc of relevantDocs.slice(0, 2)) {
|
|
26722
26733
|
const chunks = db.prepare(
|
|
26723
|
-
"SELECT heading, content, chunk_type FROM knowledge_chunks WHERE document_id = ? AND chunk_type = 'section' ORDER BY line_start"
|
|
26734
|
+
"SELECT heading, content, chunk_type FROM knowledge_chunks WHERE document_id = ? AND chunk_type = 'section' ORDER BY line_start LIMIT 5000"
|
|
26724
26735
|
).all(doc.id);
|
|
26725
26736
|
lines.push(`### From: ${claudeDir}/${doc.file_path}`);
|
|
26726
26737
|
lines.push("");
|
|
@@ -26776,7 +26787,7 @@ function handleVerification(db, args2) {
|
|
|
26776
26787
|
if (vr.category) lines.push(`| **Category** | ${vr.category} |`);
|
|
26777
26788
|
} else if (situation) {
|
|
26778
26789
|
const results = db.prepare(
|
|
26779
|
-
"SELECT * FROM knowledge_verifications WHERE use_when LIKE ? OR vr_type LIKE ? OR catches LIKE ? ORDER BY vr_type"
|
|
26790
|
+
"SELECT * FROM knowledge_verifications WHERE use_when LIKE ? OR vr_type LIKE ? OR catches LIKE ? ORDER BY vr_type LIMIT 1000"
|
|
26780
26791
|
).all(`%${situation}%`, `%${situation}%`, `%${situation}%`);
|
|
26781
26792
|
lines.push(`## Verifications for "${situation}" (${results.length} found)`);
|
|
26782
26793
|
lines.push("");
|
|
@@ -26814,10 +26825,10 @@ function handleGraph(db, args2) {
|
|
|
26814
26825
|
lines.push("");
|
|
26815
26826
|
for (const entity of currentLevel) {
|
|
26816
26827
|
const outgoing = db.prepare(
|
|
26817
|
-
"SELECT target_type, target_id, edge_type FROM knowledge_edges WHERE source_type = ? AND source_id = ?"
|
|
26828
|
+
"SELECT target_type, target_id, edge_type FROM knowledge_edges WHERE source_type = ? AND source_id = ? LIMIT 5000"
|
|
26818
26829
|
).all(entity.type, entity.id);
|
|
26819
26830
|
const incoming = db.prepare(
|
|
26820
|
-
"SELECT source_type, source_id, edge_type FROM knowledge_edges WHERE target_type = ? AND target_id = ?"
|
|
26831
|
+
"SELECT source_type, source_id, edge_type FROM knowledge_edges WHERE target_type = ? AND target_id = ? LIMIT 5000"
|
|
26821
26832
|
).all(entity.type, entity.id);
|
|
26822
26833
|
for (const edge of outgoing) {
|
|
26823
26834
|
const key = `${edge.target_type}:${edge.target_id}`;
|
|
@@ -26892,6 +26903,7 @@ function handleCommand(db, args2) {
|
|
|
26892
26903
|
JOIN knowledge_documents kd ON kd.id = kc.document_id
|
|
26893
26904
|
WHERE kc.chunk_type = 'command' AND (kc.content LIKE ? OR kc.heading LIKE ?)
|
|
26894
26905
|
ORDER BY kc.heading
|
|
26906
|
+
LIMIT 1000
|
|
26895
26907
|
`).all(`%${keyword}%`, `%${keyword}%`);
|
|
26896
26908
|
lines.push(`## Commands matching "${keyword}" (${results.length} found)`);
|
|
26897
26909
|
lines.push("");
|
|
@@ -26906,6 +26918,7 @@ function handleCommand(db, args2) {
|
|
|
26906
26918
|
JOIN knowledge_documents kd ON kd.id = kc.document_id
|
|
26907
26919
|
WHERE kc.chunk_type = 'command'
|
|
26908
26920
|
ORDER BY kc.heading
|
|
26921
|
+
LIMIT 1000
|
|
26909
26922
|
`).all();
|
|
26910
26923
|
lines.push(`## All Commands (${commands.length} total)`);
|
|
26911
26924
|
lines.push("");
|
|
@@ -27022,7 +27035,7 @@ function handlePlan(db, args2) {
|
|
|
27022
27035
|
if (doc.description) lines.push(`**Description**: ${doc.description}`);
|
|
27023
27036
|
lines.push("");
|
|
27024
27037
|
const items = db.prepare(
|
|
27025
|
-
"SELECT heading, content FROM knowledge_chunks WHERE document_id = ? AND metadata LIKE '%plan_item_id%' ORDER BY heading"
|
|
27038
|
+
"SELECT heading, content FROM knowledge_chunks WHERE document_id = ? AND metadata LIKE '%plan_item_id%' ORDER BY heading LIMIT 5000"
|
|
27026
27039
|
).all(doc.id);
|
|
27027
27040
|
if (items.length > 0) {
|
|
27028
27041
|
lines.push(`### Plan Items (${items.length})`);
|
|
@@ -27048,7 +27061,7 @@ function handlePlan(db, args2) {
|
|
|
27048
27061
|
}
|
|
27049
27062
|
} else if (status) {
|
|
27050
27063
|
const docs = db.prepare(
|
|
27051
|
-
"SELECT kd.file_path, kd.title, kc.content FROM knowledge_chunks kc JOIN knowledge_documents kd ON kd.id = kc.document_id WHERE kd.category = 'plan' AND kc.heading = 'IMPLEMENTATION STATUS' AND kc.content LIKE ? ORDER BY kd.file_path DESC"
|
|
27064
|
+
"SELECT kd.file_path, kd.title, kc.content FROM knowledge_chunks kc JOIN knowledge_documents kd ON kd.id = kc.document_id WHERE kd.category = 'plan' AND kc.heading = 'IMPLEMENTATION STATUS' AND kc.content LIKE ? ORDER BY kd.file_path DESC LIMIT 1000"
|
|
27052
27065
|
).all(`%${status}%`);
|
|
27053
27066
|
lines.push(`## Plans with status "${status}" (${docs.length} found)`);
|
|
27054
27067
|
lines.push("");
|
|
@@ -27134,7 +27147,7 @@ function handleGaps(db, args2) {
|
|
|
27134
27147
|
}
|
|
27135
27148
|
} else if (checkType === "patterns") {
|
|
27136
27149
|
const patternDocs = db.prepare(
|
|
27137
|
-
"SELECT file_path, title FROM knowledge_documents WHERE category = 'patterns'"
|
|
27150
|
+
"SELECT file_path, title FROM knowledge_documents WHERE category = 'patterns' LIMIT 10000"
|
|
27138
27151
|
).all();
|
|
27139
27152
|
const documentedDomains = new Set(patternDocs.map((d2) => d2.title.replace("-patterns", "").replace(" Patterns", "").toLowerCase()));
|
|
27140
27153
|
lines.push("### Pattern Coverage");
|
|
@@ -27144,7 +27157,7 @@ function handleGaps(db, args2) {
|
|
|
27144
27157
|
try {
|
|
27145
27158
|
dataDb = getDataDb();
|
|
27146
27159
|
const domains = dataDb.prepare(
|
|
27147
|
-
`SELECT DISTINCT domain FROM ${t("sentinel")} WHERE status = 'active' ORDER BY domain`
|
|
27160
|
+
`SELECT DISTINCT domain FROM ${t("sentinel")} WHERE status = 'active' ORDER BY domain LIMIT 10000`
|
|
27148
27161
|
).all();
|
|
27149
27162
|
for (const d2 of domains) {
|
|
27150
27163
|
const hasPattern = documentedDomains.has(d2.domain.toLowerCase());
|
|
@@ -27469,7 +27482,7 @@ function handlePyImports(args2, dataDb) {
|
|
|
27469
27482
|
if (depth > maxDepth || visited.has(f2)) return;
|
|
27470
27483
|
visited.add(f2);
|
|
27471
27484
|
const imports = dataDb.prepare(
|
|
27472
|
-
`SELECT target_file, imported_names FROM ${t("py_imports")} WHERE source_file =
|
|
27485
|
+
`SELECT target_file, imported_names FROM ${t("py_imports")} WHERE source_file = ? LIMIT 10000`
|
|
27473
27486
|
).all(f2);
|
|
27474
27487
|
for (const imp of imports) {
|
|
27475
27488
|
const indent = " ".repeat(depth);
|
|
@@ -27484,7 +27497,7 @@ function handlePyImports(args2, dataDb) {
|
|
|
27484
27497
|
traverse2(file, 0);
|
|
27485
27498
|
} else {
|
|
27486
27499
|
const imports = dataDb.prepare(
|
|
27487
|
-
`SELECT target_file, import_type, imported_names, line FROM ${t("py_imports")} WHERE source_file = ? ORDER BY line`
|
|
27500
|
+
`SELECT target_file, import_type, imported_names, line FROM ${t("py_imports")} WHERE source_file = ? ORDER BY line LIMIT 10000`
|
|
27488
27501
|
).all(file);
|
|
27489
27502
|
lines.push(`## Imports from ${file} (${imports.length} edges)`);
|
|
27490
27503
|
for (const imp of imports) {
|
|
@@ -27494,7 +27507,7 @@ function handlePyImports(args2, dataDb) {
|
|
|
27494
27507
|
}
|
|
27495
27508
|
} else if (importedBy) {
|
|
27496
27509
|
const importers = dataDb.prepare(
|
|
27497
|
-
`SELECT source_file, imported_names, line FROM ${t("py_imports")} WHERE target_file = ? ORDER BY source_file`
|
|
27510
|
+
`SELECT source_file, imported_names, line FROM ${t("py_imports")} WHERE target_file = ? ORDER BY source_file LIMIT 10000`
|
|
27498
27511
|
).all(importedBy);
|
|
27499
27512
|
lines.push(`## Files importing ${importedBy} (${importers.length} edges)`);
|
|
27500
27513
|
for (const imp of importers) {
|
|
@@ -27741,14 +27754,14 @@ function handlePyImpact(args2, dataDb) {
|
|
|
27741
27754
|
const file = args2.file;
|
|
27742
27755
|
const lines = [`## Impact Analysis: ${file}`, ""];
|
|
27743
27756
|
const importedBy = dataDb.prepare(
|
|
27744
|
-
`SELECT source_file FROM ${t("py_imports")} WHERE target_file =
|
|
27757
|
+
`SELECT source_file FROM ${t("py_imports")} WHERE target_file = ? LIMIT 10000`
|
|
27745
27758
|
).all(file);
|
|
27746
27759
|
lines.push(`### Imported By (${importedBy.length} files)`);
|
|
27747
27760
|
for (const imp of importedBy.slice(0, 20)) {
|
|
27748
27761
|
lines.push(`- ${imp.source_file}`);
|
|
27749
27762
|
}
|
|
27750
27763
|
const routes = dataDb.prepare(
|
|
27751
|
-
`SELECT method, path, function_name FROM ${t("py_routes")} WHERE file =
|
|
27764
|
+
`SELECT method, path, function_name FROM ${t("py_routes")} WHERE file = ? LIMIT 10000`
|
|
27752
27765
|
).all(file);
|
|
27753
27766
|
if (routes.length > 0) {
|
|
27754
27767
|
lines.push(`
|
|
@@ -27758,7 +27771,7 @@ function handlePyImpact(args2, dataDb) {
|
|
|
27758
27771
|
}
|
|
27759
27772
|
}
|
|
27760
27773
|
const models = dataDb.prepare(
|
|
27761
|
-
`SELECT class_name, table_name FROM ${t("py_models")} WHERE file =
|
|
27774
|
+
`SELECT class_name, table_name FROM ${t("py_models")} WHERE file = ? LIMIT 10000`
|
|
27762
27775
|
).all(file);
|
|
27763
27776
|
if (models.length > 0) {
|
|
27764
27777
|
lines.push(`
|
|
@@ -27771,7 +27784,7 @@ function handlePyImpact(args2, dataDb) {
|
|
|
27771
27784
|
if (routeIds.length > 0) {
|
|
27772
27785
|
const placeholders = routeIds.map(() => "?").join(",");
|
|
27773
27786
|
const callers = dataDb.prepare(
|
|
27774
|
-
`SELECT DISTINCT frontend_file FROM ${t("py_route_callers")} WHERE route_id IN (${placeholders})`
|
|
27787
|
+
`SELECT DISTINCT frontend_file FROM ${t("py_route_callers")} WHERE route_id IN (${placeholders}) LIMIT 100000`
|
|
27775
27788
|
).all(...routeIds.map((r2) => r2.id));
|
|
27776
27789
|
if (callers.length > 0) {
|
|
27777
27790
|
lines.push(`
|
|
@@ -27812,14 +27825,14 @@ function handlePyContext(args2, dataDb) {
|
|
|
27812
27825
|
lines.push(`- ${imp.source_file}`);
|
|
27813
27826
|
}
|
|
27814
27827
|
}
|
|
27815
|
-
const routes = dataDb.prepare(`SELECT method, path, function_name, line FROM ${t("py_routes")} WHERE file =
|
|
27828
|
+
const routes = dataDb.prepare(`SELECT method, path, function_name, line FROM ${t("py_routes")} WHERE file = ? LIMIT 10000`).all(file);
|
|
27816
27829
|
if (routes.length > 0) {
|
|
27817
27830
|
lines.push("\n### Routes");
|
|
27818
27831
|
for (const r2 of routes) {
|
|
27819
27832
|
lines.push(`- ${r2.method} ${r2.path} \u2192 ${r2.function_name} (L${r2.line})`);
|
|
27820
27833
|
}
|
|
27821
27834
|
}
|
|
27822
|
-
const models = dataDb.prepare(`SELECT class_name, table_name, line FROM ${t("py_models")} WHERE file =
|
|
27835
|
+
const models = dataDb.prepare(`SELECT class_name, table_name, line FROM ${t("py_models")} WHERE file = ? LIMIT 10000`).all(file);
|
|
27823
27836
|
if (models.length > 0) {
|
|
27824
27837
|
lines.push("\n### Models");
|
|
27825
27838
|
for (const m3 of models) {
|
|
@@ -28226,7 +28239,7 @@ Feature scan failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
|
28226
28239
|
function handleContext(file, dataDb, codegraphDb) {
|
|
28227
28240
|
const lines = [];
|
|
28228
28241
|
const nodes = codegraphDb.prepare(
|
|
28229
|
-
"SELECT name, kind, start_line, end_line FROM nodes WHERE file_path = ? ORDER BY start_line"
|
|
28242
|
+
"SELECT name, kind, start_line, end_line FROM nodes WHERE file_path = ? ORDER BY start_line LIMIT 10000"
|
|
28230
28243
|
).all(file);
|
|
28231
28244
|
if (nodes.length > 0) {
|
|
28232
28245
|
lines.push("## CodeGraph Nodes");
|
|
@@ -28343,7 +28356,7 @@ function handleContext(file, dataDb, codegraphDb) {
|
|
|
28343
28356
|
if (relevantCRs.length > 0) {
|
|
28344
28357
|
const placeholders = relevantCRs.map(() => "?").join(",");
|
|
28345
28358
|
const crRules = knowledgeDb.prepare(
|
|
28346
|
-
`SELECT rule_id, rule_text, vr_type FROM knowledge_rules WHERE rule_id IN (${placeholders})`
|
|
28359
|
+
`SELECT rule_id, rule_text, vr_type FROM knowledge_rules WHERE rule_id IN (${placeholders}) LIMIT 10000`
|
|
28347
28360
|
).all(...relevantCRs);
|
|
28348
28361
|
if (crRules.length > 0) {
|
|
28349
28362
|
lines.push("## Relevant Canonical Rules");
|
|
@@ -28440,7 +28453,7 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
28440
28453
|
const lines = [];
|
|
28441
28454
|
if (args2.uncoupled) {
|
|
28442
28455
|
const uncoupled = dataDb.prepare(
|
|
28443
|
-
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0 ORDER BY router_name, procedure_name`
|
|
28456
|
+
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0 ORDER BY router_name, procedure_name LIMIT 10000`
|
|
28444
28457
|
).all();
|
|
28445
28458
|
lines.push(`## Uncoupled Procedures (${uncoupled.length} total)`);
|
|
28446
28459
|
lines.push("These procedures have ZERO UI callers.");
|
|
@@ -28455,7 +28468,7 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
28455
28468
|
}
|
|
28456
28469
|
} else if (args2.router) {
|
|
28457
28470
|
const procs = dataDb.prepare(
|
|
28458
|
-
`SELECT id, procedure_name, procedure_type, has_ui_caller FROM ${t("trpc_procedures")} WHERE router_name = ? ORDER BY procedure_name`
|
|
28471
|
+
`SELECT id, procedure_name, procedure_type, has_ui_caller FROM ${t("trpc_procedures")} WHERE router_name = ? ORDER BY procedure_name LIMIT 10000`
|
|
28459
28472
|
).all(args2.router);
|
|
28460
28473
|
lines.push(`## Router: ${args2.router} (${procs.length} procedures)`);
|
|
28461
28474
|
lines.push("");
|
|
@@ -28463,7 +28476,7 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
28463
28476
|
const status = proc.has_ui_caller ? "" : " [NO UI CALLERS]";
|
|
28464
28477
|
lines.push(`### ${args2.router}.${proc.procedure_name} (${proc.procedure_type})${status}`);
|
|
28465
28478
|
const callSites = dataDb.prepare(
|
|
28466
|
-
`SELECT file, line, call_pattern FROM ${t("trpc_call_sites")} WHERE procedure_id =
|
|
28479
|
+
`SELECT file, line, call_pattern FROM ${t("trpc_call_sites")} WHERE procedure_id = ? LIMIT 10000`
|
|
28467
28480
|
).all(proc.id);
|
|
28468
28481
|
if (callSites.length > 0) {
|
|
28469
28482
|
lines.push("UI Call Sites:");
|
|
@@ -28477,7 +28490,7 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
28477
28490
|
}
|
|
28478
28491
|
} else if (args2.procedure) {
|
|
28479
28492
|
const procs = dataDb.prepare(
|
|
28480
|
-
`SELECT id, router_name, router_file, procedure_type, has_ui_caller FROM ${t("trpc_procedures")} WHERE procedure_name = ? ORDER BY router_name`
|
|
28493
|
+
`SELECT id, router_name, router_file, procedure_type, has_ui_caller FROM ${t("trpc_procedures")} WHERE procedure_name = ? ORDER BY router_name LIMIT 10000`
|
|
28481
28494
|
).all(args2.procedure);
|
|
28482
28495
|
lines.push(`## Procedure "${args2.procedure}" found in ${procs.length} routers`);
|
|
28483
28496
|
lines.push("");
|
|
@@ -28485,7 +28498,7 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
28485
28498
|
lines.push(`### ${proc.router_name}.${args2.procedure} (${proc.procedure_type})`);
|
|
28486
28499
|
lines.push(`File: ${proc.router_file}`);
|
|
28487
28500
|
const callSites = dataDb.prepare(
|
|
28488
|
-
`SELECT file, line, call_pattern FROM ${t("trpc_call_sites")} WHERE procedure_id =
|
|
28501
|
+
`SELECT file, line, call_pattern FROM ${t("trpc_call_sites")} WHERE procedure_id = ? LIMIT 10000`
|
|
28489
28502
|
).all(proc.id);
|
|
28490
28503
|
if (callSites.length > 0) {
|
|
28491
28504
|
lines.push("UI Call Sites:");
|
|
@@ -28530,11 +28543,11 @@ function handleCouplingCheck(args2, dataDb, codegraphDb) {
|
|
|
28530
28543
|
let uncoupledProcs;
|
|
28531
28544
|
if (stagedFiles) {
|
|
28532
28545
|
uncoupledProcs = dataDb.prepare(
|
|
28533
|
-
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0 AND router_file IN (${stagedFiles.map(() => "?").join(",")})`
|
|
28546
|
+
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0 AND router_file IN (${stagedFiles.map(() => "?").join(",")}) LIMIT 10000`
|
|
28534
28547
|
).all(...stagedFiles);
|
|
28535
28548
|
} else {
|
|
28536
28549
|
uncoupledProcs = dataDb.prepare(
|
|
28537
|
-
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0`
|
|
28550
|
+
`SELECT router_name, procedure_name, procedure_type, router_file FROM ${t("trpc_procedures")} WHERE has_ui_caller = 0 LIMIT 10000`
|
|
28538
28551
|
).all();
|
|
28539
28552
|
}
|
|
28540
28553
|
lines.push("## Coupling Check Results");
|
|
@@ -28550,12 +28563,12 @@ function handleCouplingCheck(args2, dataDb, codegraphDb) {
|
|
|
28550
28563
|
lines.push("");
|
|
28551
28564
|
}
|
|
28552
28565
|
const allPages = codegraphDb.prepare(
|
|
28553
|
-
"SELECT path FROM files WHERE path LIKE 'src/app/%/page.tsx' OR path = 'src/app/page.tsx'"
|
|
28566
|
+
"SELECT path FROM files WHERE path LIKE 'src/app/%/page.tsx' OR path = 'src/app/page.tsx' LIMIT 10000"
|
|
28554
28567
|
).all();
|
|
28555
28568
|
const pageImports = /* @__PURE__ */ new Set();
|
|
28556
28569
|
for (const page of allPages) {
|
|
28557
28570
|
const imports = dataDb.prepare(
|
|
28558
|
-
`SELECT target_file FROM ${t("imports")} WHERE source_file =
|
|
28571
|
+
`SELECT target_file FROM ${t("imports")} WHERE source_file = ? LIMIT 10000`
|
|
28559
28572
|
).all(page.path);
|
|
28560
28573
|
for (const imp of imports) {
|
|
28561
28574
|
pageImports.add(imp.target_file);
|
|
@@ -28565,7 +28578,7 @@ function handleCouplingCheck(args2, dataDb, codegraphDb) {
|
|
|
28565
28578
|
if (stagedFiles) {
|
|
28566
28579
|
const placeholders = stagedFiles.map(() => "?").join(",");
|
|
28567
28580
|
componentFiles = codegraphDb.prepare(
|
|
28568
|
-
`SELECT path FROM files WHERE path LIKE 'src/components/%' AND path IN (${placeholders})`
|
|
28581
|
+
`SELECT path FROM files WHERE path LIKE 'src/components/%' AND path IN (${placeholders}) LIMIT 10000`
|
|
28569
28582
|
).all(...stagedFiles);
|
|
28570
28583
|
} else {
|
|
28571
28584
|
componentFiles = [];
|
|
@@ -28627,7 +28640,7 @@ function handleImpact2(file, dataDb, codegraphDb) {
|
|
|
28627
28640
|
const fileDomain = classifyFile(file);
|
|
28628
28641
|
lines.push(`### Domain: ${fileDomain}`);
|
|
28629
28642
|
const imports = dataDb.prepare(
|
|
28630
|
-
`SELECT target_file FROM ${t("imports")} WHERE source_file =
|
|
28643
|
+
`SELECT target_file FROM ${t("imports")} WHERE source_file = ? LIMIT 10000`
|
|
28631
28644
|
).all(file);
|
|
28632
28645
|
const crossings = [];
|
|
28633
28646
|
for (const imp of imports) {
|
|
@@ -2028,7 +2028,7 @@ async function main() {
|
|
|
2028
2028
|
const counts = parseTestRunOutput(tool_response ?? "");
|
|
2029
2029
|
if (counts) {
|
|
2030
2030
|
const modifiedFeatures = db.prepare(
|
|
2031
|
-
"SELECT feature_key FROM feature_health WHERE modifications_since_test > 0"
|
|
2031
|
+
"SELECT feature_key FROM feature_health WHERE modifications_since_test > 0 LIMIT 10000"
|
|
2032
2032
|
).all();
|
|
2033
2033
|
for (const row of modifiedFeatures) {
|
|
2034
2034
|
recordTestResult(db, row.feature_key, counts.passing, counts.failing);
|
|
@@ -1177,7 +1177,7 @@ async function main() {
|
|
|
1177
1177
|
).all(session_id);
|
|
1178
1178
|
const observations = observationsDesc.reverse();
|
|
1179
1179
|
const prompts = db.prepare(
|
|
1180
|
-
"SELECT prompt_text FROM user_prompts WHERE session_id = ? ORDER BY prompt_number ASC"
|
|
1180
|
+
"SELECT prompt_text FROM user_prompts WHERE session_id = ? ORDER BY prompt_number ASC LIMIT 10000"
|
|
1181
1181
|
).all(session_id);
|
|
1182
1182
|
const summary = buildSnapshotSummary(observations, prompts);
|
|
1183
1183
|
addSummary(db, session_id, summary);
|