<a id="db-access-matrix"></a>
# DB production SQL access matrix

PostgreSQL 51개 table과 Traffic SQLite 3개 table+FTS virtual table을 production Go 함수 단위로 역추적한다. 각 행은 exact file/symbol과 정적으로 확인한 table·SQL verb·source fragment를 보존한다. literal/evaluated expression과 닫힌 allowlist만 C 후보이고, runtime에서 predicate/order/placeholder를 조립하는 행은 최종 실행 SQL을 재구성하지 않고 P/U로 표시한다. arbitrary formatted identifier와 실제 call reachability는 U다.

## 분모와 판정

| 저장소 | 객체 | table-symbol binding | query occurrence | 처분 |
|---|---:|---:|---:|---|
| PostgreSQL | 51/51 | 709 located | 924 located | symbol·consumer·evidence 등록; runtime template/arbitrary dynamic input 때문에 source-complete 분모는 U |
| Traffic SQLite | 4/4 | 30 located | 37 located | symbol·consumer·evidence 등록; runtime template와 FTS availability는 P/U |

- `FROM`과 `JOIN`은 read, `INSERT`·`UPDATE`·`DELETE`·`TRUNCATE`는 write로 분류한다. 한 query가 대상 table을 join하면서 수정하면 두 mode가 함께 나타날 수 있다.
- `LOCK TABLE`은 `LOCK`/`lock`으로 분류한다. 한 statement가 여러 table을 고정하면 각 table-object에 같은 lock occurrence를 연결한다.
- `task_archives_restore.go`의 세 동적 table 자리만 source allowlist로 해석했다. 허용 목록 밖 동적 identifier는 확정하지 않는다.
- Located occurrence 중 runtime-built template 표시는 PostgreSQL 108개, SQLite 14개다. 자산/탐색/command/LLM/notification filter builder와 `FanOutPendingEvents`, `DeleteByIDs`, `RescheduleDeliveries`, `Search`, `query`, `ExportHosts`, `Page`, `deleteWhere`, `hostTrees` 등이 포함된다. table/verb와 source fragment만 확정하고 최종 실행 SQL은 P/U다.
- `Traffic.deleteWhere`와 `hostTrees` helper 자체는 predicate를 검증하지 않는다. 현재 production caller가 넘기는 `host LIKE ?`, `1=1`, `host=?`의 닫힌 내부 집합에서만 안전성 경계를 읽는다.
- 이 문서의 symbol 분모는 source에서 정적으로 위치를 확인한 SQL 접근의 하한이다. field 의미 551개 분모와 route 261개 분모를 섞지 않는다.

<a id="runtime-builder-u-index"></a>
## Runtime builder U index

두 감사를 분리한다. 독립 AST syntactic-unresolved 감사가 production DB API 호출 중 정적으로 실행 SQL을 닫지 못한 68개 call site/56개 file-symbol을 찾았다. schema 전체 DDL·`CREATE DATABASE`·PRAGMA인 5개 call site/4개 symbol은 table-access 분모에서 제외한다. 나머지 63개 call site/52개 symbol은 known table binding이 위 matrix에 있더라도 최종 predicate·placeholder·inner-query 완전성을 P/U로 둔다. 이 detector가 pseudo-static 값으로 평탄화한 조건부 조합 SQL은 별도 source review에서 서로 겹치지 않는 11개 execution call site/10개 file-symbol을 추가했다. 합집합은 79개 call site/66개 file-symbol이고, table-access 대상은 74개/62개다.

### Syntactic-unresolved call sites

| file/symbol | call site | 처분 |
|---|---|---|
| `db/asset_dsl.go::AssetStore.CountDSL` | L501 `QueryRow` | table binding 후보 · runtime SQL P/U |
| `db/asset_dsl.go::AssetStore.GetByIDsInScope` | L624 `Query` | table binding 후보 · runtime SQL P/U |
| `db/asset_dsl.go::AssetStore.QueryDSL` | L535 `Query` | table binding 후보 · runtime SQL P/U |
| `db/asset_dsl.go::AssetStore.QueryDSLInScope` | L588 `Query` | table binding 후보 · runtime SQL P/U |
| `db/assets.go::AssetStore.DeleteByIDs` | L1440 `Exec` | table binding 후보 · runtime SQL P/U |
| `db/assets.go::AssetStore.GetByIDs` | L1380 `Query` | table binding 후보 · runtime SQL P/U |
| `db/commands.go::DB.ListCommands` | L97 `QueryRow`, L112 `Query` | table binding 후보 · runtime SQL P/U |
| `db/commands.go::DB.ListLLMRecords` | L261 `Query` | table binding 후보 · runtime SQL P/U |
| `db/commands.go::DB.ToolStats` | L56 `Query` | table binding 후보 · runtime SQL P/U |
| `db/config.go::DB.AgentBindingCounts` | L515 `Query` | table binding 후보 · runtime SQL P/U |
| `db/config.go::lockProfileReferenceRows` | L399 `QueryContext` | table binding 후보 · runtime SQL P/U |
| `db/db.go::applySchemaWithRetry` | L43 `ExecContext` | schema/DB/PRAGMA control · table-access 분모 제외 |
| `db/db.go::ensureDatabase` | L120 `Exec` | schema/DB/PRAGMA control · table-access 분모 제외 |
| `db/digest.go::ExplorationStore.NodeAssets` | L237 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.ActivityByIDs` | L1963 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.ActivityByIDsForTerminalIntents` | L1995 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.ActivityPage` | L1606 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.EdgesTouching` | L957 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.NodesByIDs` | L934 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.NodesPage` | L899 `QueryRow`, L907 `Query` | table binding 후보 · runtime SQL P/U |
| `db/exploration.go::ExplorationStore.listByKindPageFiltered` | L776 `Query` | table binding 후보 · runtime SQL P/U |
| `db/finding_assets.go::DB.buildFindingAssetTree` | L143 `Query` | table binding 후보 · runtime SQL P/U |
| `db/finding_assets.go::DB.loadAssetsByHost` | L395 `Query` | table binding 후보 · runtime SQL P/U |
| `db/finding_traffic.go::ExplorationStore.PopulateFindingTrafficIDs` | L439 `Query` | table binding 후보 · runtime SQL P/U |
| `db/findings.go::DB.ListFindingGroups` | L317 `QueryRow`, L343 `Query` | table binding 후보 · runtime SQL P/U |
| `db/findings.go::DB.ListFindingsForExport` | L502 `Query` | table binding 후보 · runtime SQL P/U |
| `db/findings.go::DB.ListFindingsPage` | L250 `QueryRow`, L271 `Query` | table binding 후보 · runtime SQL P/U |
| `db/findings.go::DB.setFindingCol` | L720 `QueryRow`, L728 `Exec` | table binding 후보 · runtime SQL P/U |
| `db/intercept.go::DB.listInterceptsPage` | L360 `Query` | table binding 후보 · runtime SQL P/U |
| `db/notification.go::DB.FanOutPendingEvents` | L344 `ExecContext`, L356 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification.go::DB.NotificationAssetNames` | L392 `QueryContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.ClaimDigestBatch` | L202 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.DeferDeliveries` | L322 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.FailDeliveries` | L336 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.ListNotificationDeliveries` | L396 `QueryRowContext`, L403 `QueryContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.MarkDeliveriesSent` | L287 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.RescheduleDeliveries` | L301 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::DB.claimDeliveries` | L228 `ExecContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::loadDeliveriesTx` | L265 `QueryContext` | table binding 후보 · runtime SQL P/U |
| `db/notification_delivery.go::selectForClaim` | L247 `QueryContext` | table binding 후보 · runtime SQL P/U |
| `db/task_archives.go::archiveAssetMetadata` | L682 `Query` | table binding 후보 · runtime SQL P/U |
| `db/task_archives.go::queryArchiveRows` | L446 `Query` | table binding 후보 · runtime SQL P/U |
| `db/task_archives.go::streamArchiveRows` | L512 `Query` | table binding 후보 · runtime SQL P/U |
| `db/task_archives.go::taskArchiveAggregates` | L762 `QueryRow` | table binding 후보 · runtime SQL P/U |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` | L77 `Exec`, L99 `Exec` | table binding 후보 · runtime SQL P/U |
| `db/task_archives_restore.go::insertArchiveJSONSequenceRows` | L425 `Exec` | table binding 후보 · runtime SQL P/U |
| `db/task_archives_restore.go::insertArchiveRows` | L399 `Exec` | table binding 후보 · runtime SQL P/U |
| `db/task_archives_restore.go::rowExists` | L360 `QueryRow` | table binding 후보 · runtime SQL P/U |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` | L177 `Query` | table binding 후보 · runtime SQL P/U |
| `db/task_scope.go::AssetStore.ListUntestedAssets` | L627 `Query` | table binding 후보 · runtime SQL P/U |
| `db/triggers.go::DB.queryTriggers` | L102 `Query` | table binding 후보 · runtime SQL P/U |
| `traffic/archive.go::Traffic.ExportHosts` | L63 `Query` | table binding 후보 · runtime SQL P/U |
| `traffic/traffic.go::Traffic.deleteWhere` | L1185 `Exec`, L1189 `Exec`, L1192 `Exec`, L1195 `Exec` | table binding 후보 · runtime SQL P/U |
| `traffic/traffic.go::Traffic.hostTrees` | L1210 `Query` | table binding 후보 · runtime SQL P/U |
| `traffic/traffic.go::Traffic.initIndex` | L260 `ExecContext`, L270 `ExecContext` | schema/DB/PRAGMA control · table-access 분모 제외 |
| `traffic/traffic.go::Traffic.reclaimChunk` | L1784 `ExecContext` | schema/DB/PRAGMA control · table-access 분모 제외 |

### Conditional-composition additions

아래 행은 syntactic-unresolved 목록에는 없지만 source branch 또는 helper 조합 때문에 최종 실행 SQL이 닫히지 않는 symbol이다.

| file/symbol | composition source | execution call site | 빠진 동적 부분 |
|---|---|---|---|
| `db/assets.go::AssetStore.QueryByCompany` | L1106-L1122 | L1123 `Query` | optional type predicate + pageClause |
| `db/assets.go::AssetStore.CountByCompany` | L1132-L1137 | L1139 `QueryRow` | optional type predicate |
| `db/assets.go::AssetStore.QueryByTask` | L1158-L1174 | L1175 `Query` | optional type predicate + pageClause |
| `db/assets.go::AssetStore.CountByTask` | L1191-L1196 | L1198 `QueryRow` | optional type predicate |
| `db/exploration.go::ExplorationStore.countByKindFiltered` | L788-L795 | L795 `QueryRow` | optional summary predicate |
| `db/task_archives.go::DB.snapshotTaskArchive` | L573-L599 | L614 `queryArchiveRows` | query-list/helper composition; assets inner query is runtime-composed |
| `db/task_assets_context.go::AssetStore.ListTaskScopeWithSources` | L94-L100 | L94 `Query` | global CTE + local query composition |
| `traffic/traffic.go::Traffic.Search` | L770-L777 | L778 `Query` | optional host predicate + paging |
| `traffic/traffic.go::Traffic.Page` | L864-L931 | L915 `QueryRow`, L931 `Query` | filter/FTS/order/page fragments |
| `traffic/traffic.go::Traffic.query` | L1907-L1945 | L1946 `Query` | host/port/URL/FTS predicates + paging |

두 목록은 `QueryDSL*`, `GetByIDs*`, node/activity list builders, finding/notification filters, archive inner-query wrappers와 SQLite search builders를 합쳐 추적한다. 문서가 개별 table binding을 제시하더라도 이 index에 든 symbol의 완전한 실행 SQL을 확정한 것으로 읽지 않는다.

<a id="access-companies"></a>
## `companies`

[companies 물리 객체](task-exploration.md#table-companies) · [field 의미](semantic-catalog.md#semantic-companies)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/chat_mentions.go::DB.SearchChatMentionsPage` · [근거](evidence:db-pg-access-companies-027ee36311) | `read` / `FROM` | L69 `FROM` `…'>$5)))) ORDER BY (id::text=$2) DESC, id DESC LIMIT 21) UNION ALL (SELECT 'company', id, name, nkey FROM companies WHERE ($1='' OR $1='company') AND ($2='' OR id::text=$2 OR name ILIKE $3 OR nkey ILIKE $3) AND ($4::bigint=0 OR (id::text=$2)<$6 OR ((id::text=$2)=$6 AND (id<$4 OR (id=$4 AND 'company'>$5)))) ORDER BY (id::text=$2) DESC…` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.CreateCompanyWithScope` · [근거](evidence:db-pg-access-companies-8a08847bd5) | `write` / `INSERT` | L145 `INSERT` `INSERT INTO companies(name, nkey, logo) VALUES ($1, $2, $3) ON CONFLICT (nkey) DO NOTHING RETURNING id` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.DeleteCompanyWithAssets` · [근거](evidence:db-pg-access-companies-5d7af36dbc) | `write` / `DELETE` | L235 `DELETE` `DELETE FROM companies WHERE id = $1` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.GetCompany` · [근거](evidence:db-pg-access-companies-82f2f97b5f) | `read` / `FROM` | L176 `FROM` `SELECT id, name, nkey, logo, created_at::text, updated_at::text FROM companies WHERE id = $1` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.GetCompanyByName` · [근거](evidence:db-pg-access-companies-5a99aca97f) | `read` / `FROM` | L190 `FROM` `SELECT id, name, nkey, logo, created_at::text, updated_at::text FROM companies WHERE nkey = $1` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.ListCompanies` · [근거](evidence:db-pg-access-companies-9c33327a89) | `read` / `FROM` | L261 `FROM` `…c.name, c.nkey, c.logo, c.created_at::text, c.updated_at::text, COUNT(DISTINCT a.id) AS asset_count FROM companies c LEFT JOIN assets a ON a.company_id = c.id GROUP BY c.id ORDER BY c.name` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::CompanyStore.UpsertCompany` · [근거](evidence:db-pg-access-companies-5558ff7874) | `write` / `INSERT` | L106 `INSERT` `INSERT INTO companies(name, nkey, logo) VALUES ($1, $2, $3) ON CONFLICT (nkey) DO UPDATE SET name = EXCLUDED.name, logo = COALESCE(EXCLUDED.logo, companies.logo), updated_at = now() RETURNING id, (xmax = 0)` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/companies.go::ensureCompanyExistsTx` · [근거](evidence:db-pg-access-companies-1c607bde47) | `read` / `FROM` | L417 `FROM` `SELECT EXISTS(SELECT 1 FROM companies WHERE id = $1)` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/finding_assets.go::DB.attachCompanyNodes` · [근거](evidence:db-pg-access-companies-e668bfbdce) | `read` / `FROM` | L536 `FROM` `SELECT id, COALESCE(name,'') FROM companies WHERE id = ANY($1::bigint[])` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives_restore.go::rowExists` · [근거](evidence:db-pg-access-companies-451348e66d) | `read` / `FROM` | L360 `FROM` `SELECT EXISTS(SELECT 1 FROM <allowlisted table> WHERE id=$1)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets_context.go::AssetStore.ListTaskScopeWithSources` · [근거](evidence:db-pg-access-companies-e2feb4cf84) | `read` / `JOIN` | L94 `JOIN` `source fragment: …ce, COALESCE(ts.reason,'') FROM task_scope ts JOIN context_tasks ctx ON ctx.task_id=ts.task_id LEFT JOIN companies c ON c.id=ts.company_id ORDER BY CASE WHEN ts.task_id=$1 THEN 0 ELSE 1 END, ts.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-companies-26853e3459) | `read` / `FROM` | L536 `FROM` `SELECT name FROM companies WHERE id=$1` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/task_scope.go::AssetStore.ListTaskScope` · [근거](evidence:db-pg-access-companies-83c7ae4ebd) | `read` / `JOIN` | L236 `JOIN` `…(ts.net::text,''), COALESCE(ts.value,''), ts.source, COALESCE(ts.reason,'') FROM task_scope ts LEFT JOIN companies c ON c.id=ts.company_id WHERE ts.task_id=$1 ORDER BY ts.id` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |
| `db/tasks.go::insertTaskCompanies` · [근거](evidence:db-pg-access-companies-592d9370e6) | `read` / `JOIN` | L264 `JOIN` `… reason) SELECT $1, 'company', companies.id, 'manual', '任务创建时关联企业' FROM requested JOIN companies ON companies.id=requested.company_id ORDER BY requested.position RETURNING company_id ) SELECT count(*) FROM inserted`<br>L296 `JOIN` `…ummary) SELECT $1, asset.id, $3, '任务创建时关联企业：' \|\| company.name FROM assets asset JOIN companies company ON company.id=asset.company_id WHERE asset.company_id=ANY($2::bigint[]) AND $1=ANY(asset.task_ids) ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_summary, so…` | [`feature-asset-sources`](../../features/assets-scope.md#asset-sources) |

**처분** · located production table-symbol binding 14개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-assets"></a>
## `assets`

[assets 물리 객체](task-exploration.md#table-assets) · [field 의미](semantic-catalog.md#semantic-assets)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/asset_dsl.go::AssetStore.CountDSL` · [근거](evidence:db-pg-access-assets-ac89e52754) | `read` / `FROM` | L501 `FROM` `SELECT count(*) FROM assets WHERE <buildDSLWhere predicate plus optional type/task filters>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/asset_dsl.go::AssetStore.GetByIDsInScope` · [근거](evidence:db-pg-access-assets-bfe357fb46) | `read` / `FROM` | L624 `FROM` `scopeTargetCTE + assetSelectCols + runtime id placeholders + target membership` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/asset_dsl.go::AssetStore.QueryDSL` · [근거](evidence:db-pg-access-assets-c2af0e3866) | `read` / `FROM` | L535 `FROM` `source fragment: assetSelectCols + buildDSLWhere + optional type/task predicates + ORDER/LIMIT/OFFSET <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/asset_dsl.go::AssetStore.QueryDSLInScope` · [근거](evidence:db-pg-access-assets-08e4edbca3) | `read` / `FROM` | L588 `FROM` `source fragment: scopeTargetCTE + assetSelectCols + DSL/type/target predicates + ORDER/LIMIT/OFFSET <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.AppendIPBoundDomain` · [근거](evidence:db-pg-access-assets-b7f549daa9) | `write` / `UPDATE` | L430 `UPDATE` `UPDATE assets SET bound_domains = (SELECT ARRAY(SELECT DISTINCT unnest(bound_domains \|\| ARRAY[$1::text]))), last_seen = now() WHERE type = 'ip' AND ip = $2` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.AppendIPPort` · [근거](evidence:db-pg-access-assets-920527bebb) | `write` / `UPDATE` | L410 `UPDATE` `UPDATE assets SET open_ports = ( SELECT ARRAY( SELECT DISTINCT ON ((elem->>'port')::int) elem FROM unnest(open_ports \|\| ARRAY[$1::jsonb]) AS elem ORDER BY (elem->>'port')::int, CASE WHEN elem->>'service' IS NOT NULL AND elem->>'servi…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.CountByCompany` · [근거](evidence:db-pg-access-assets-34e71511f9) | `read` / `FROM` | L1132 `FROM` `source fragment: SELECT count(*) FROM assets WHERE company_id = $1 <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L1139 `FROM` `source fragment: SELECT count(*) FROM assets WHERE company_id = $1 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.CountByTask` · [근거](evidence:db-pg-access-assets-3407544ec0) | `read` / `FROM` | L1191 `FROM` `source fragment: SELECT count(*) FROM assets WHERE $1 = ANY(task_ids) <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L1198 `FROM` `source fragment: SELECT count(*) FROM assets WHERE $1 = ANY(task_ids) <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.CountByType` · [근거](evidence:db-pg-access-assets-f73d325aea) | `read` / `FROM` | L1099 `FROM` `SELECT count(*) FROM assets WHERE type = $1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.CountsByType` · [근거](evidence:db-pg-access-assets-ec341d7f00) | `read` / `FROM` | L1449 `FROM` `SELECT type, COUNT(*) FROM assets GROUP BY type` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.CountsByTypeForTask` · [근거](evidence:db-pg-access-assets-474e1ac90a) | `read` / `FROM` | L1203 `FROM` `SELECT type, COUNT(*) FROM assets WHERE $1 = ANY(task_ids) GROUP BY type` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.DeleteByCompanyID` · [근거](evidence:db-pg-access-assets-689a6eff52) | `write` / `DELETE` | L1390 `DELETE` `DELETE FROM assets WHERE company_id = $1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.DeleteByHost` · [근거](evidence:db-pg-access-assets-3c600226f2) | `write` / `DELETE` | L1410 `DELETE` `DELETE FROM assets WHERE domain = $1 OR root_domain = $1 OR ip = $1 RETURNING type` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.DeleteByIDs` · [근거](evidence:db-pg-access-assets-b189a1320e) | `write` / `DELETE` | L1440 `DELETE` `DELETE FROM assets WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.DeleteByTaskID` · [근거](evidence:db-pg-access-assets-0e43349555) | `write` / `DELETE,UPDATE` | L1216 `DELETE` `DELETE FROM assets WHERE task_ids = ARRAY[$1]::bigint[]`<br>L1221 `UPDATE` `UPDATE assets SET task_ids = array_remove(task_ids, $1) WHERE $1 = ANY(task_ids)` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.GetByIDs` · [근거](evidence:db-pg-access-assets-fabc282c04) | `read` / `FROM` | L1380 `FROM` `assetSelectCols + runtime id placeholders + ORDER BY last_seen` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.HostsByTask` · [근거](evidence:db-pg-access-assets-9727e52143) | `read` / `FROM` | L1231 `FROM` `SELECT COALESCE(domain,''), COALESCE(ip,''), COALESCE(url,'') FROM assets WHERE $1 = ANY(task_ids)` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.QueryByCompany` · [근거](evidence:db-pg-access-assets-381590ebb9) | `read` / `FROM` | L1106 `FROM` `source fragment: …array_to_json(auth)::text, COALESCE(method,''), array_to_json(params)::text, extra, last_seen::text FROM assets WHERE company_id = $1 <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L1123 `FROM` `source fragment: …array_to_json(auth)::text, COALESCE(method,''), array_to_json(params)::text, extra, last_seen::text FROM assets WHERE company_id = $1 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.QueryByTask` · [근거](evidence:db-pg-access-assets-2ef5a4abe7) | `read` / `FROM` | L1158 `FROM` `source fragment: …array_to_json(auth)::text, COALESCE(method,''), array_to_json(params)::text, extra, last_seen::text FROM assets WHERE $1 = ANY(task_ids) <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L1175 `FROM` `source fragment: …array_to_json(auth)::text, COALESCE(method,''), array_to_json(params)::text, extra, last_seen::text FROM assets WHERE $1 = ANY(task_ids) <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.QueryByType` · [근거](evidence:db-pg-access-assets-292f7c7f0e) | `read` / `FROM` | L1074 `FROM` `…array_to_json(auth)::text, COALESCE(method,''), array_to_json(params)::text, extra, last_seen::text FROM assets WHERE type = $1 ORDER BY last_seen DESC, id DESC LIMIT $2 OFFSET $3` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertApp` · [근거](evidence:db-pg-access-assets-3d08c5ef9a) | `write` / `INSERT` | L616 `INSERT` `INSERT INTO assets(type, bundle_id, app_name, category, app_description, app_icp, company_id, company_source, task_ids) VALUES ('app', $1, $2, $3, $4, $5, $6, $7, $8::bigint[]) ON CONFLICT (bundle_id) WHERE type = 'app' AND bundle_id IS N…`<br>L639 `INSERT` `INSERT INTO assets(type, bundle_id, app_name, category, app_description, app_icp, company_id, company_source, task_ids) VALUES ('app', NULL, $1, $2, $3, $4, $5, $6, $7::bigint[]) ON CONFLICT (app_name) WHERE type = 'app' AND bundle_id IS …` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertEndpoint` · [근거](evidence:db-pg-access-assets-49f3abc241) | `write` / `INSERT` | L1019 `INSERT` `INSERT INTO assets( type, url, method, domain, ip, port, root_domain, params, company_id, company_source, task_ids, c_segment ) VALUES ('endpoint', $1, $2, $3, $4, $5, $6, $7::jsonb[], $8, 'scope', $9::bigint[], $10::cidr) ON CONFLICT (ur…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertHTTPService` · [근거](evidence:db-pg-access-assets-d244c644c2) | `write` / `INSERT` | L739 `INSERT` `INSERT INTO assets( type, url, service_type, service_name, domain, ip, port, root_domain, c_segment, favicon_mmh3, technologies, status_code, content_length, page_title, auth, company_id, company_source, task_ids ) VALUES ( 'service', $1,…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertIP` · [근거](evidence:db-pg-access-assets-1c56c5bc53) | `write` / `INSERT` | L375 `INSERT` `INSERT INTO assets(type, ip, c_segment, bound_domains, open_ports, company_id, company_source, task_ids) VALUES ('ip', $1, $2::cidr, $3::text[], $4::jsonb[], $5, 'scope', $6::bigint[]) ON CONFLICT (ip) WHERE type = 'ip' DO UPDATE SET boun…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertOtherService` · [근거](evidence:db-pg-access-assets-7bb8deead0) | `write` / `INSERT` | L884 `INSERT` `INSERT INTO assets( type, service_type, service_name, domain, ip, port, root_domain, c_segment, auth, company_id, company_source, task_ids ) VALUES ('service', 'other', $1, $2, $3, $4, $5, $6::cidr, $7::jsonb[], $8, 'scope', $9::bigint[])…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertRootDomain` · [근거](evidence:db-pg-access-assets-f45086ef34) | `write` / `INSERT` | L283 `INSERT` `INSERT INTO assets(type, domain, root_domain, icp, company_id, company_source, task_ids) VALUES ('root_domain', $1, $1, $2, $3, 'scope', $4::bigint[]) ON CONFLICT (domain) WHERE type = 'root_domain' DO UPDATE SET icp = COALESCE(EXCLUDED.i…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::AssetStore.UpsertSubdomain` · [근거](evidence:db-pg-access-assets-5d280f205c) | `write` / `INSERT` | L528 `INSERT` `INSERT INTO assets(type, domain, root_domain, record_type, record_value, ip, c_segment, icp, company_id, company_source, task_ids) VALUES ('subdomain', $1, $2, $3, $4::text[], $5, $6::cidr, $7, $8, 'scope', $9::bigint[]) ON CONFLICT (doma…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/assets.go::hostsForTaskDeletion` · [근거](evidence:db-pg-access-assets-ac91a2052c) | `read` / `FROM` | L1286 `FROM` `…tion_nodes n ON n.id=ea.node_id WHERE n.exploration_id=$2 ), other_assets AS ( SELECT DISTINCT a.id FROM assets a WHERE EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) OR EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.ex…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/chat_mentions.go::DB.SearchChatMentionsPage` · [근거](evidence:db-pg-access-assets-9923205705) | `read` / `FROM` | L69 `FROM` `…',type,NULLIF(page_title,''),NULLIF(service_name,''),NULLIF(bundle_id,''),NULLIF(ip,''),port::text) FROM assets WHERE ($1='' OR $1='asset' OR type=$1) AND ($2='' OR id::text=$2 OR concat_ws(' ',domain,root_domain,ip,url,app_name,bundle_id,page_title,service_name,method) ILIKE $3) AND ($4::bigint=0 OR (id::text=$2)<$6 OR ((id::tex…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/companies.go::CompanyStore.DeleteCompanyWithAssets` · [근거](evidence:db-pg-access-assets-67058e4a73) | `write` / `DELETE` | L226 `DELETE` `DELETE FROM assets WHERE company_id = $1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/companies.go::CompanyStore.ListCompanies` · [근거](evidence:db-pg-access-assets-08131b651c) | `read` / `JOIN` | L261 `JOIN` `…, c.created_at::text, c.updated_at::text, COUNT(DISTINCT a.id) AS asset_count FROM companies c LEFT JOIN assets a ON a.company_id = c.id GROUP BY c.id ORDER BY c.name` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/companies.go::malformedIPAssetWarning` · [근거](evidence:db-pg-access-assets-1568fdd7ed) | `read` / `FROM` | L607 `FROM` `SELECT id, ip, count(*) OVER () AS total FROM assets WHERE ip IS NOT NULL AND ip <> '' AND try_inet(ip) IS NULL AND type IN ('ip','subdomain','service','endpoint') ORDER BY id LIMIT $1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/companies.go::recomputeAttributionTx` · [근거](evidence:db-pg-access-assets-697813c1b5) | `read,write` / `FROM,UPDATE` | L509 `UPDATE` `UPDATE assets SET company_id = NULL, company_source = 'scope' WHERE company_source = 'scope'`<br>L517 `FROM` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind = 'domain' AND a.root_domain = cs.domain WHERE a.company_id IS NULL AND a.type IN ('root_domain','subdomain','service','endpoint') AND a.root_domain IS NOT NULL ORDER BY a.id, length(c…`<br>L517 `UPDATE` `…e','endpoint') AND a.root_domain IS NOT NULL ORDER BY a.id, length(cs.domain) DESC, cs.company_id ) UPDATE assets a SET company_id = matched.company_id, company_source = 'scope' FROM matched WHERE a.id = matched.asset_id`<br>L535 `FROM` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind IN ('ip','cidr') AND cs.net >>= try_inet(a.ip) WHERE a.company_id IS NULL AND a.type IN ('ip','subdomain','service','endpoint') AND a.ip IS NOT NULL ORDER BY a.id, masklen(cs.net) DESC…`<br>L535 `UPDATE` `…in','service','endpoint') AND a.ip IS NOT NULL ORDER BY a.id, masklen(cs.net) DESC, cs.company_id ) UPDATE assets a SET company_id = matched.company_id, company_source = 'scope' FROM matched WHERE a.id = matched.asset_id`<br>L553 `FROM` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind = 'icp' AND ( lower(regexp_replace(COALESCE(a.icp,''), '[[:space:]]+', '', 'g')) = cs.value OR lower(regexp_replace(COALESCE(a.app_icp,''), '[[:space:]]+', '', 'g')) = cs.value ) WHERE…`<br>L553 `UPDATE` `… NULL AND (COALESCE(a.icp,'') <> '' OR COALESCE(a.app_icp,'') <> '') ORDER BY a.id, cs.company_id ) UPDATE assets a SET company_id = matched.company_id, company_source = 'scope' FROM matched WHERE a.id = matched.asset_id` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/finding_assets.go::DB.loadAssetsByHost` · [근거](evidence:db-pg-access-assets-f45cca9cff) | `read` / `FROM` | L412 `FROM` `FROM assets a WHERE a.type='service' AND (a.domain = ANY($1::text[]) OR a.ip = ANY($1::text[]))`<br>L416 `FROM` `FROM assets a WHERE a.type='subdomain' AND a.domain = ANY($1::text[])`<br>L420 `FROM` `FROM assets a WHERE a.type='ip' AND a.ip = ANY($1::text[])`<br>L424 `FROM` `FROM assets a WHERE a.type='root_domain' AND a.domain = ANY($1::text[])` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_assets.go::DB.loadFindingAssetRows` · [근거](evidence:db-pg-access-assets-12f762afa6) | `read` / `FROM` | L258 `FROM` `…p,''), COALESCE(a.url,''), COALESCE(a.port,0), COALESCE(a.service_type,''), COALESCE(a.app_name,'') FROM assets a WHERE a.id = ANY($1::bigint[])` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-assets-4563afa922) | `read` / `FROM` | L85 `FROM` `…类'), jsonb_build_object('finding', to_jsonb(f), 'assets', COALESCE((SELECT jsonb_agg(to_jsonb(a)) FROM assets a WHERE f.asset_ids @> to_jsonb(ARRAY[a.id])), '[]'::jsonb), 'constraints', COALESCE((SELECT jsonb_agg(to_jsonb(c)) FROM task_constraints c JOIN tasks t ON t.exploration_id=c.exploration_id WHERE t.id=f.task_id), '[]'::…` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::FindingFilter.where` · [근거](evidence:db-pg-access-assets-494ba72146) | `read` / `JOIN` | L205 `JOIN` `…et_ids, '[]'::jsonb)) = 0 OR NOT EXISTS ( SELECT 1 FROM jsonb_array_elements_text(f.asset_ids) e(v) JOIN assets a ON a.id = e.v::bigint ) )` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.NotificationAssetNames` · [근거](evidence:db-pg-access-assets-b49b77c116) | `read` / `FROM` | L392 `FROM` `SELECT id, type, domain, ip, url, app_name, bundle_id FROM assets WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-assets-1cd2a35e08) | `read` / `FROM` | L599 `FROM` `source fragment: SELECT asset.* FROM assets asset WHERE asset.id IN (<archiveAssetIDsQuery helper composition>) ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetIDsQuery` · [근거](evidence:db-pg-access-assets-b1e13d04c1) | `read` / `FROM` | L529 `FROM` `SELECT id FROM assets WHERE $1=ANY(task_ids) UNION SELECT link.asset_id FROM task_asset_links link WHERE link.task_id=$1 UNION SELECT anchor.asset_id FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetMetadata` · [근거](evidence:db-pg-access-assets-266516fe7e) | `read` / `FROM` | L682 `FROM` `source fragment: WITH candidate AS (<archiveAssetIDsQuery helper composition>) SELECT asset.id FROM assets asset JOIN candidate ON candidate.id=asset.id WHERE <cross-task ownership and live-anchor exclusions> ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-assets-42719fef02) | `lock,write` / `DELETE,LOCK,UPDATE` | L64 `LOCK` `LOCK TABLE assets, exploration_anchors IN SHARE ROW EXCLUSIVE MODE`<br>L103 `UPDATE` `UPDATE assets SET task_ids=array_remove(task_ids,$1) WHERE $1=ANY(task_ids)`<br>L107 `DELETE` `DELETE FROM assets asset WHERE asset.id=ANY($2::bigint[]) AND asset.company_id IS NULL AND NOT EXISTS (SELECT 1 FROM tasks task WHERE task.id<>$1 AND task.deleted_at IS NULL AND task.id=ANY(asset.task_ids)) AND NOT EXISTS ( SELECT 1 FROM …` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::findArchiveAssetNaturalID` · [근거](evidence:db-pg-access-assets-8ccea69ea4) | `read` / `FROM` | L516 `FROM` `SELECT id FROM assets WHERE type='root_domain' AND domain=$1`<br>L518 `FROM` `SELECT id FROM assets WHERE type='ip' AND ip=$1`<br>L520 `FROM` `SELECT id FROM assets WHERE type='subdomain' AND domain=$1 AND COALESCE(record_type,'')=$2`<br>L523 `FROM` `SELECT id FROM assets WHERE type='app' AND bundle_id=$1`<br>L525 `FROM` `SELECT id FROM assets WHERE type='app' AND bundle_id IS NULL AND app_name=$1`<br>L529 `FROM` `SELECT id FROM assets WHERE type='service' AND service_type='http' AND url=$1`<br>L532 `FROM` `SELECT id FROM assets WHERE type='service' AND service_type='other' AND COALESCE(domain,'')=$1 AND COALESCE(ip,'')=$2 AND port=$3 AND service_name=$4`<br>L535 `FROM` `SELECT id FROM assets WHERE type='endpoint' AND url=$1 AND method=$2` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreArchiveAssets` · [근거](evidence:db-pg-access-assets-4552dc4867) | `write` / `INSERT,UPDATE` | L454 `UPDATE` `UPDATE assets SET task_ids=CASE WHEN $1=ANY(task_ids) THEN task_ids ELSE array_append(task_ids,$1) END WHERE id=$2`<br>L469 `INSERT` `INSERT INTO assets SELECT * FROM json_populate_record(NULL::assets,$1::json) ON CONFLICT DO NOTHING`<br>L480 `UPDATE` `UPDATE assets SET task_ids=CASE WHEN $1=ANY(task_ids) THEN task_ids ELSE array_append(task_ids,$1) END WHERE id=$2` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::rowExists` · [근거](evidence:db-pg-access-assets-f214bc708b) | `read` / `FROM` | L360 `FROM` `SELECT EXISTS(SELECT 1 FROM <allowlisted table> WHERE id=$1)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.AttachAssetsToTask` · [근거](evidence:db-pg-access-assets-c773b403af) | `read,write` / `FROM,UPDATE` | L283 `FROM` `SELECT count(*), count(*) FILTER (WHERE $1=ANY(task_ids)) FROM assets WHERE id=ANY($2::bigint[])`<br>L295 `UPDATE` `UPDATE assets SET task_ids=CASE WHEN $1=ANY(task_ids) THEN task_ids ELSE array_append(task_ids,$1) END WHERE id=ANY($2::bigint[])`<br>L301 `FROM` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary) SELECT $1, id, 'manual', $3 FROM assets WHERE id=ANY($2::bigint[]) ON CONFLICT (task_id, asset_id) DO UPDATE SET source='manual', source_summary=EXCLUDED.source_summary, source_node_id=NULL` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.DetachAssetFromTask` · [근거](evidence:db-pg-access-assets-9b183fabbc) | `write` / `UPDATE` | L321 `UPDATE` `UPDATE assets SET task_ids=array_remove(task_ids,$1) WHERE id=$2 AND $1=ANY(task_ids) RETURNING id` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-assets-71a2b29744) | `read` / `JOIN` | L375 `JOIN` `…exploration_id AND intent.kind='intent' JOIN exploration_anchors anchor ON anchor.node_id=intent.id JOIN assets asset ON asset.id=anchor.asset_id LEFT JOIN task_asset_links link ON link.task_id=context.task_id AND link.asset_id=asset.id WHERE NOT context.inherited OR intent.state IN ('done','blocked','exhausted','stopped') ORDER …` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.RegisterTaskAssetScopes` · [근거](evidence:db-pg-access-assets-52bc975351) | `read` / `FROM` | L185 `FROM` `SELECT id, $2=ANY(task_ids) FROM assets WHERE type='root_domain' AND domain=$1`<br>L208 `FROM` `SELECT id, $2=ANY(task_ids) FROM assets WHERE type='ip' AND ip=$1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.SetTaskAssetSource` · [근거](evidence:db-pg-access-assets-067d17d02d) | `read` / `JOIN` | L101 `JOIN` `…et_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_summary, source_node…`<br>L113 `JOIN` `…et_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_summary, source_node…`<br>L115 `JOIN` `…et_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_summary, source_node…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-assets-32bf6ec1b3) | `read` / `FROM` | L202 `FROM` `…AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), context_assets AS ( SELECT DISTINCT a.id FROM assets a WHERE EXISTS (SELECT 1 FROM context_tasks ctx WHERE ctx.task_id=ANY(a.task_ids)) UNION SELECT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.explora…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-assets-4e75062863) | `read` / `FROM` | L170 `FROM` `… UNION SELECT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_…`<br>L177 `FROM` `… UNION SELECT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-assets-e1e6c3d434) | `read` / `FROM` | L127 `FROM` `… UNION SELECT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-assets-4cfef63802) | `read` / `FROM` | L428 `FROM` `… UNION SELECT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_…`<br>L513 `FROM` `SELECT id, COALESCE(company_id,0) FROM assets WHERE type='root_domain' AND domain=$1 LIMIT 1` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_scope.go::AssetStore.ListUntestedAssets` · [근거](evidence:db-pg-access-assets-046fd89c65) | `read` / `FROM` | L622 `FROM` `…LECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind I…`<br>L627 `FROM` `…LECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind I…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_scope.go::AssetStore.TaskCoverage` · [근거](evidence:db-pg-access-assets-429d7e60de) | `read` / `FROM` | L331 `FROM` `…LECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind I…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-assets-439a90dd4a) | `lock,read,write` / `DELETE,FROM,LOCK,UPDATE` | L574 `LOCK` `LOCK TABLE assets, exploration_anchors IN SHARE ROW EXCLUSIVE MODE`<br>L595 `DELETE` `… t.exploration_id=n.exploration_id WHERE ea.asset_id=a.id AND t.id<>$1 AND t.deleted_at IS NULL ) ) DELETE FROM assets a USING deletable d WHERE a.id=d.id`<br>L595 `FROM` `…JOIN exploration_nodes n ON n.id=ea.node_id WHERE n.exploration_id=$2 ), deletable AS ( SELECT a.id FROM assets a JOIN candidate_assets c ON c.id=a.id WHERE NOT EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_n…`<br>L625 `UPDATE` `UPDATE assets SET task_ids = array_remove(task_ids, $1) WHERE $1 = ANY(task_ids)` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/tasks.go::insertTaskCompanies` · [근거](evidence:db-pg-access-assets-cab0f39b8c) | `read,write` / `FROM,UPDATE` | L287 `UPDATE` `UPDATE assets SET task_ids=CASE WHEN $1=ANY(task_ids) THEN task_ids ELSE array_append(task_ids, $1) END WHERE company_id=ANY($2::bigint[])`<br>L296 `FROM` `…, source, source_summary) SELECT $1, asset.id, $3, '任务创建时关联企业：' \|\| company.name FROM assets asset JOIN companies company ON company.id=asset.company_id WHERE asset.company_id=ANY($2::bigint[]) AND $1=ANY(asset.task_ids) ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUD…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |

**처분** · located production table-symbol binding 58개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-company-scope"></a>
## `company_scope`

[company_scope 물리 객체](task-exploration.md#table-company-scope) · [field 의미](semantic-catalog.md#semantic-company-scope)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/companies.go::CompanyStore.GetScope` · [근거](evidence:db-pg-access-company-scope-7e40c33b76) | `read` / `FROM` | L298 `FROM` `…id, kind, COALESCE(domain,''), COALESCE(net::text,''), COALESCE(value,''), raw, COALESCE(reason,'') FROM company_scope WHERE company_id = $1 ORDER BY id` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/companies.go::CompanyStore.UpdateScopeInputsChecked` · [근거](evidence:db-pg-access-company-scope-5d479bbe19) | `write` / `DELETE` | L690 `DELETE` `DELETE FROM company_scope WHERE company_id = $1` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/companies.go::insertScopeRuleTx` · [근거](evidence:db-pg-access-company-scope-cc48b3bcc4) | `write` / `INSERT` | L455 `INSERT` `INSERT INTO company_scope(company_id, kind, domain, raw, reason) VALUES ($1, 'domain', $2, $3, $4) ON CONFLICT ON CONSTRAINT uq_sv2_domain DO NOTHING`<br>L461 `INSERT` `INSERT INTO company_scope(company_id, kind, net, raw, reason) VALUES ($1, $2, $3::cidr, $4, $5) ON CONFLICT ON CONSTRAINT uq_sv2_net DO NOTHING`<br>L467 `INSERT` `INSERT INTO company_scope(company_id, kind, value, raw, reason) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (company_id, kind, value) WHERE kind IN ('icp','keyword') DO NOTHING` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/companies.go::recomputeAttributionTx` · [근거](evidence:db-pg-access-company-scope-2dcedff17b) | `read` / `JOIN` | L517 `JOIN` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind = 'domain' AND a.root_domain = cs.domain WHERE a.company_id IS NULL AND a.type IN ('root_domain','subdomain','service','endpoint') AND a.root_domain IS NOT NULL ORDER BY a.id, length(cs.domain) DESC, cs.co…`<br>L535 `JOIN` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind IN ('ip','cidr') AND cs.net >>= try_inet(a.ip) WHERE a.company_id IS NULL AND a.type IN ('ip','subdomain','service','endpoint') AND a.ip IS NOT NULL ORDER BY a.id, masklen(cs.net) DESC, cs.company_id ) UPD…`<br>L553 `JOIN` `WITH matched AS ( SELECT DISTINCT ON (a.id) a.id AS asset_id, cs.company_id FROM assets a JOIN company_scope cs ON cs.kind = 'icp' AND ( lower(regexp_replace(COALESCE(a.icp,''), '[[:space:]]+', '', 'g')) = cs.value OR lower(regexp_replace(COALESCE(a.app_icp,''), '[[:space:]]+', '', 'g')) = cs.value ) WHERE a.company_id IS NULL…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/companies.go::resolveCompanyWithICP` · [근거](evidence:db-pg-access-company-scope-910c65209a) | `read` / `FROM` | L729 `FROM` `SELECT company_id FROM company_scope WHERE kind = 'domain' AND domain = $1 ORDER BY length(domain) DESC, company_id LIMIT 1`<br>L745 `FROM` `SELECT company_id FROM company_scope WHERE kind IN ('ip','cidr') AND net >>= $1::inet ORDER BY masklen(net) DESC, company_id LIMIT 1`<br>L761 `FROM` `SELECT company_id FROM company_scope WHERE kind = 'icp' AND value = $1 ORDER BY company_id LIMIT 1` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |

**처분** · located production table-symbol binding 5개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-explorations"></a>
## `explorations`

[explorations 물리 객체](task-exploration.md#table-explorations) · [field 의미](semantic-catalog.md#semantic-explorations)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/digest.go::ExplorationStore.BumpRound` · [근거](evidence:db-pg-access-explorations-1cde922da3) | `write` / `UPDATE` | L19 `UPDATE` `UPDATE explorations SET round_no = round_no + 1 WHERE id=$1 RETURNING round_no` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/digest.go::ExplorationStore.RoundNo` · [근거](evidence:db-pg-access-explorations-d6a6e892aa) | `read` / `FROM` | L26 `FROM` `SELECT round_no FROM explorations WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration.go::DB.CreateExploration` · [근거](evidence:db-pg-access-explorations-148ac9d22a) | `write` / `INSERT` | L180 `INSERT` `INSERT INTO explorations(description, goal) VALUES ($1, $2) RETURNING id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration.go::DB.ExplorationDiag` · [근거](evidence:db-pg-access-explorations-0ffe72b87c) | `read` / `FROM` | L1229 `FROM` `SELECT EXISTS(SELECT 1 FROM explorations WHERE id=$1), (SELECT COUNT(*) FROM tasks WHERE exploration_id=$1), COALESCE((SELECT MAX(id) FROM explorations),0)` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration.go::ExplorationStore.Root` · [근거](evidence:db-pg-access-explorations-d750c727e6) | `read` / `FROM` | L192 `FROM` `SELECT description, goal FROM explorations WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-explorations-f87592c5a7) | `read` / `FROM` | L579 `FROM` `source fragment: SELECT * FROM explorations WHERE id=$1 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-explorations-0f43bc3f8d) | `write` / `UPDATE` | L118 `UPDATE` `UPDATE explorations SET description='',goal='',status='open' WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.DeleteTaskArchiveStub` · [근거](evidence:db-pg-access-explorations-11808b0f2b) | `write` / `DELETE` | L767 `DELETE` `DELETE FROM explorations WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreExplorationStub` · [근거](evidence:db-pg-access-explorations-e10c8a676c) | `write` / `UPDATE` | L305 `UPDATE` `UPDATE explorations current SET description=archived.description,goal=archived.goal,status=archived.status, created_at=archived.created_at,updated_at=archived.updated_at FROM json_populate_record(NULL::explorations,$2::json) archived WHERE…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/tasks.go::DB.CreateTaskWithOptions` · [근거](evidence:db-pg-access-explorations-7b5ecbeb86) | `write` / `INSERT` | L178 `INSERT` `INSERT INTO explorations(description, goal) VALUES ($1,$2) RETURNING id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-explorations-ab3e7603f2) | `write` / `DELETE` | L650 `DELETE` `DELETE FROM explorations WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |

**처분** · located production table-symbol binding 11개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-exploration-nodes"></a>
## `exploration_nodes`

[exploration_nodes 물리 객체](task-exploration.md#table-exploration-nodes) · [field 의미](semantic-catalog.md#semantic-exploration-nodes)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/assets.go::hostsForTaskDeletion` · [근거](evidence:db-pg-access-exploration-nodes-f98e35c886) | `read` / `JOIN` | L1286 `JOIN` `…ND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) OR EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WHERE ea.asset_id=a.id AND t.id<>$1 AND t.deleted_at IS NULL ) ) SELECT COALESCE(a.domain,''), COALESCE(a.ip,''), COALESCE(a.url,''), true FROM asse…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.ActiveDigests` · [근거](evidence:db-pg-access-exploration-nodes-6451d26bf7) | `read` / `FROM` | L110 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND kind=$2 AND state=$3 ORDER BY id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.AddDigest` · [근거](evidence:db-pg-access-exploration-nodes-d30caf782b) | `write` / `INSERT` | L130 `INSERT` `INSERT INTO exploration_nodes(exploration_id, kind, payload, priority, state, origin) VALUES ($1, $2, $3, 0, $4, 'compactor') RETURNING id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.ApplyStampOps` · [근거](evidence:db-pg-access-exploration-nodes-5e28c79b6c) | `write` / `UPDATE` | L76 `UPDATE` `UPDATE exploration_nodes SET cold_since_round=$1 WHERE id=$2 AND exploration_id=$3`<br>L80 `UPDATE` `UPDATE exploration_nodes SET cold_since_round=NULL WHERE id=$1 AND exploration_id=$2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.ColdStamps` · [근거](evidence:db-pg-access-exploration-nodes-6f36c45653) | `read` / `FROM` | L34 `FROM` `SELECT id, cold_since_round FROM exploration_nodes WHERE exploration_id=$1 AND kind IN ('intent','fact')` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.ContentVersions` · [근거](evidence:db-pg-access-exploration-nodes-4f0f2e9ad3) | `read` / `FROM` | L90 `FROM` `SELECT id, content_version FROM exploration_nodes WHERE exploration_id=$1` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.CoveredMembers` · [근거](evidence:db-pg-access-exploration-nodes-2c30687866) | `read` / `JOIN` | L154 `JOIN` `SELECT e.dst_id, e.src_id FROM exploration_edges e JOIN exploration_nodes d ON d.id=e.src_id AND d.exploration_id=e.exploration_id WHERE e.exploration_id=$1 AND e.rel=$2 AND d.kind=$3 AND d.state=$4 ORDER BY e.src_id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.NodeAssets` · [근거](evidence:db-pg-access-exploration-nodes-a66e196ed3) | `read` / `JOIN` | L237 `JOIN` `SELECT a.node_id, a.asset_id FROM exploration_anchors a JOIN exploration_nodes n ON n.id=a.node_id WHERE n.exploration_id=$1 AND a.node_id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.SupersedeDigests` · [근거](evidence:db-pg-access-exploration-nodes-fa614862de) | `write` / `UPDATE` | L215 `UPDATE` `UPDATE exploration_nodes SET state=$1 WHERE id=$2 AND exploration_id=$3 AND kind=$4` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::DB.GoalCountsAll` · [근거](evidence:db-pg-access-exploration-nodes-e128b07ee9) | `read` / `FROM` | L1396 `FROM` `SELECT exploration_id, COUNT(*) AS total, COUNT(*) FILTER (WHERE state = 'met') AS met FROM exploration_nodes WHERE kind = 'goal' GROUP BY exploration_id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::DB.TaskListMetricsAll` · [근거](evidence:db-pg-access-exploration-nodes-4e01ec1291) | `read` / `FROM` | L1313 `FROM` `…ty ON true LEFT JOIN LATERAL ( SELECT COUNT(*) AS total, COUNT(*) FILTER (WHERE state='met') AS met FROM exploration_nodes WHERE exploration_id=task.exploration_id AND kind='goal' ) goal_metrics ON true LEFT JOIN LATERAL ( SELECT COUNT(*) AS running FROM exploration_nodes WHERE exploration_id=task.exploration_id AND kind='intent' AND state=…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityByIDsForTerminalIntents` · [근거](evidence:db-pg-access-exploration-nodes-f5d9cecafa) | `read` / `JOIN` | L1995 `JOIN` `…ode_id, COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.detail,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.kind NOT IN ('thinking','usage') AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.id IN (<runtime-expanded placeholders>) ORDER…` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityListForTerminalIntent` · [근거](evidence:db-pg-access-exploration-nodes-68eecf0476) | `read` / `JOIN` | L1521 `JOIN` `…ated_at, a.input_tokens, a.output_tokens, a.cache_read_tokens, a.cache_write_tokens FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND a.id>$3 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking',…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityPageForTerminalIntent` · [근거](evidence:db-pg-access-exploration-nodes-6a188d9e75) | `read` / `JOIN` | L1642 `JOIN` `…ated_at, a.input_tokens, a.output_tokens, a.cache_read_tokens, a.cache_write_tokens FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking','usage') AND…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityTraceForTerminalIntent` · [근거](evidence:db-pg-access-exploration-nodes-2cd50148b3) | `read` / `JOIN` | L1794 `JOIN` `…r,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking','usage') ORD…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearchForTerminalIntent` · [근거](evidence:db-pg-access-exploration-nodes-e7118eba8d) | `read` / `JOIN` | L1842 `JOIN` `…r,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking','usage') AND…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearchTerminalIntents` · [근거](evidence:db-pg-access-exploration-nodes-ad73ed6b38) | `read` / `JOIN` | L1864 `JOIN` `…r,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking','usage') AND (a.summary ILIKE…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.AddNode` · [근거](evidence:db-pg-access-exploration-nodes-2d8c2df3cf) | `write` / `INSERT` | L205 `INSERT` `INSERT INTO exploration_nodes(exploration_id, kind, payload, priority, state, origin) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.AssetRefs` · [근거](evidence:db-pg-access-exploration-nodes-8ccc10e56b) | `read` / `JOIN` | L1896 `JOIN` `SELECT en.id, en.kind, en.state, en.payload FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE ea.asset_id = $1 AND en.exploration_id = $2 AND en.kind IN ('intent','fact','finding') ORDER BY en.id DESC` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.CancelIntent` · [근거](evidence:db-pg-access-exploration-nodes-460d830d77) | `read,write` / `DELETE,FROM` | L444 `FROM` `SELECT 1 FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='intent' FOR UPDATE`<br>L455 `FROM` `SELECT id, kind, state FROM exploration_nodes WHERE exploration_id=$1`<br>L585 `DELETE` `DELETE FROM exploration_nodes WHERE id=$1 AND exploration_id=$2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ClaimIntent` · [근거](evidence:db-pg-access-exploration-nodes-f7fa8c573c) | `write` / `UPDATE` | L1174 `UPDATE` `UPDATE exploration_nodes SET state='running', owner=$1 WHERE id=$2 AND exploration_id=$3 AND kind='intent' AND state='open'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.CompareAndSetIntentState` · [근거](evidence:db-pg-access-exploration-nodes-e8f89c3ef6) | `write` / `UPDATE` | L365 `UPDATE` `UPDATE exploration_nodes SET state=$1, blocked_reason=NULL, content_version=content_version+1, completed_at = CASE WHEN $5 THEN now() ELSE NULL END WHERE id=$2 AND exploration_id=$3 AND kind='intent' AND state=$4` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.CountFinishedIntents` · [근거](evidence:db-pg-access-exploration-nodes-1d9b978960) | `read` / `FROM` | L806 `FROM` `SELECT COUNT(*) FROM exploration_nodes WHERE exploration_id=$1 AND kind='intent' AND state IN ('done','blocked','exhausted')` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.CountOpenIntents` · [근거](evidence:db-pg-access-exploration-nodes-076c07639d) | `read` / `FROM` | L816 `FROM` `SELECT COUNT(*) FROM exploration_nodes WHERE exploration_id=$1 AND kind='intent' AND state='open'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.DeleteGoal` · [근거](evidence:db-pg-access-exploration-nodes-067cf150f2) | `write` / `DELETE` | L297 `DELETE` `DELETE FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='goal'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FactsYielded` · [근거](evidence:db-pg-access-exploration-nodes-3cdf4329cb) | `read` / `JOIN` | L1007 `JOIN` `SELECT n.id FROM exploration_edges e JOIN exploration_nodes n ON n.id=e.dst_id AND n.exploration_id=e.exploration_id WHERE e.exploration_id=$1 AND e.src_id=$2 AND e.rel=$3 AND n.kind=$4 ORDER BY n.id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingIntents` · [근거](evidence:db-pg-access-exploration-nodes-fc89be98dd) | `read` / `JOIN` | L1091 `JOIN` `SELECT e.dst_id, e.src_id FROM exploration_edges e JOIN exploration_nodes n ON n.id = e.dst_id AND n.exploration_id = e.exploration_id WHERE e.exploration_id=$1 AND e.rel=$2 AND n.kind='finding'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingIntentsTerminal` · [근거](evidence:db-pg-access-exploration-nodes-bcff87f031) | `read` / `JOIN` | L1114 `JOIN` `…e JOIN exploration_nodes finding ON finding.id=e.dst_id AND finding.exploration_id=e.exploration_id JOIN exploration_nodes intent ON intent.id=e.src_id AND intent.exploration_id=e.exploration_id WHERE e.exploration_id=$1 AND e.rel=$2 AND finding.kind='finding' AND intent.kind='intent' AND intent.state IN ('done','blocked','exhausted','stopp…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingLineage` · [근거](evidence:db-pg-access-exploration-nodes-dea2424b70) | `read` / `FROM` | L1034 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id = $1 AND id IN (SELECT id FROM anc) ORDER BY id`<br>L1043 `FROM` `FROM exploration_nodes WHERE exploration_id = $1 AND id IN (SELECT id FROM anc) ORDER BY id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.Frontier` · [근거](evidence:db-pg-access-exploration-nodes-c17cfcbbb8) | `read` / `FROM` | L1140 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND kind='intent' AND state='open' ORDER BY priority DESC, id ASC LIMIT $2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.GetNode` · [근거](evidence:db-pg-access-exploration-nodes-296f47bb59) | `read` / `FROM` | L823 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE id=$1 AND exploration_id=$2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.HasActiveIntent` · [근거](evidence:db-pg-access-exploration-nodes-343fca7e02) | `read` / `FROM` | L1157 `FROM` `SELECT EXISTS(SELECT 1 FROM exploration_nodes WHERE exploration_id=$1 AND kind='intent' AND state IN ('open','running'))` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.HasOpenGoal` · [근거](evidence:db-pg-access-exploration-nodes-da339303ec) | `read` / `FROM` | L1167 `FROM` `SELECT EXISTS(SELECT 1 FROM exploration_nodes WHERE exploration_id=$1 AND kind='goal' AND state='open')` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ListByKind` · [근거](evidence:db-pg-access-exploration-nodes-2eec126b66) | `read` / `FROM` | L730 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND kind=$2 ORDER BY id DESC LIMIT $3` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ListByKindPage` · [근거](evidence:db-pg-access-exploration-nodes-94d3101018) | `read` / `FROM` | L747 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND kind=$2 AND ($3 <= 0 OR id < $3) ORDER BY id DESC LIMIT $4` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.Nodes` · [근거](evidence:db-pg-access-exploration-nodes-2d45067d9e) | `read` / `FROM` | L835 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 ORDER BY id LIMIT $2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.NodesByIDs` · [근거](evidence:db-pg-access-exploration-nodes-20fa484c5f) | `read` / `FROM` | L934 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND id IN (<runtime-expanded placeholders>) ORDER BY id` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.NodesPage` · [근거](evidence:db-pg-access-exploration-nodes-7f95ad8387) | `read` / `FROM` | L899 `FROM` `SELECT COUNT(*) FROM exploration_nodes`<br>L907 `FROM` `…origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes ORDER BY id ASC LIMIT $ OFFSET $` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.OriginFactID` · [근거](evidence:db-pg-access-exploration-nodes-6707a6e6ff) | `read` / `FROM` | L238 `FROM` `SELECT id FROM exploration_nodes WHERE exploration_id=$1 AND kind='fact' AND state='origin' ORDER BY id LIMIT 1` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ReopenBlockedIntents` · [근거](evidence:db-pg-access-exploration-nodes-a2896c79b4) | `write` / `UPDATE` | L342 `UPDATE` `UPDATE exploration_nodes SET state='open', completed_at=NULL, blocked_reason=NULL WHERE exploration_id=$1 AND kind='intent' AND state='blocked'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ReopenIntent` · [근거](evidence:db-pg-access-exploration-nodes-e65799314b) | `write` / `UPDATE` | L327 `UPDATE` `UPDATE exploration_nodes SET state='open', completed_at=NULL, blocked_reason=NULL WHERE id=$1 AND exploration_id=$2 AND kind='intent' AND state IN ('blocked','exhausted','stopped')` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.ResetRunningIntents` · [근거](evidence:db-pg-access-exploration-nodes-01572f975f) | `write` / `UPDATE` | L313 `UPDATE` `UPDATE exploration_nodes SET state='open', completed_at=NULL, blocked_reason=NULL WHERE exploration_id=$1 AND kind='intent' AND state='running'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.SetIntentState` · [근거](evidence:db-pg-access-exploration-nodes-dbfee56565) | `write` / `UPDATE` | L354 `UPDATE` `UPDATE exploration_nodes SET state=$1, blocked_reason=NULL, content_version=content_version+1, completed_at = CASE WHEN $4 THEN now() ELSE NULL END WHERE id=$2 AND exploration_id=$3 AND kind='intent'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.SetNodeState` · [근거](evidence:db-pg-access-exploration-nodes-8c7782306f) | `write` / `UPDATE` | L269 `UPDATE` `UPDATE exploration_nodes SET state=$1, blocked_reason=NULL, content_version=content_version+1 WHERE id=$2 AND exploration_id=$3` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.SoftDeleteIntent` · [근거](evidence:db-pg-access-exploration-nodes-19ae98bf02) | `read,write` / `FROM,UPDATE` | L398 `FROM` `SELECT state, payload FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='intent' FOR UPDATE`<br>L408 `UPDATE` `UPDATE exploration_nodes SET state='deleted', delete_reason=$3, blocked_reason=NULL, content_version=content_version+1, completed_at=now() WHERE id=$1 AND exploration_id=$2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.Stats` · [근거](evidence:db-pg-access-exploration-nodes-fdb7c0ee53) | `read` / `FROM` | L1185 `FROM` `SELECT kind, count(*) FROM exploration_nodes WHERE exploration_id=$1 GROUP BY kind` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.TokenStatsBySession` · [근거](evidence:db-pg-access-exploration-nodes-13feab6dd0) | `read` / `JOIN` | L1446 `JOIN` `…), COALESCE(SUM(a.cache_read_tokens),0), COALESCE(SUM(a.cache_write_tokens),0) FROM activity a LEFT JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id AND n.kind='intent' WHERE a.exploration_id=$1 AND a.kind='result' AND (COALESCE(a.worker,'') IN ('mainagent','planner') OR n.id IS NOT NULL) GROUP BY session_key…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.UpdateGoalPayload` · [근거](evidence:db-pg-access-exploration-nodes-36e1c80def) | `write` / `UPDATE` | L282 `UPDATE` `UPDATE exploration_nodes SET payload=$1 WHERE id=$2 AND exploration_id=$3 AND kind='goal'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.countByKindFiltered` · [근거](evidence:db-pg-access-exploration-nodes-86286e352e) | `read` / `FROM` | L795 `FROM` `source fragment: SELECT COUNT(*) FROM exploration_nodes WHERE exploration_id=$1 AND kind=$2 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.listByKindPageFiltered` · [근거](evidence:db-pg-access-exploration-nodes-fe309e4470) | `read` / `FROM` | L776 `FROM` `source fragment: …origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM exploration_nodes WHERE exploration_id=$1 AND kind=$2 AND ($3 <= 0 OR id < $3) ORDER BY id DESC LIMIT $ <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/finding_traffic.go::RecordFindingTx` · [근거](evidence:db-pg-access-exploration-nodes-edfd3215f9) | `read,write` / `FROM,INSERT` | L357 `FROM` `SELECT EXISTS(SELECT 1 FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='intent')`<br>L366 `INSERT` `INSERT INTO exploration_nodes(exploration_id,kind,payload,priority,state,origin) VALUES($1,'finding',$2,9,'confirmed',$3) RETURNING id` | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::DB.DeleteFinding` · [근거](evidence:db-pg-access-exploration-nodes-83a9bdd4a8) | `write` / `DELETE` | L671 `DELETE` `DELETE FROM exploration_nodes WHERE id=$1 AND kind='finding'` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.setFindingCol` · [근거](evidence:db-pg-access-exploration-nodes-642d5e2f77) | `write` / `UPDATE` | L728 `UPDATE` `source fragment: UPDATE exploration_nodes SET payload=jsonb_set(payload, '{<matching trusted json key>}', to_jsonb($1::text)) WHERE id=$2 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-exploration-nodes-cd4bdba419) | `read,write` / `INSERT,JOIN` | L382 `JOIN` `SELECT n.id FROM findings f JOIN tasks t ON t.id=f.task_id JOIN exploration_nodes n ON n.id=f.node_id AND n.exploration_id=t.exploration_id WHERE f.id=$1 AND f.node_id=$2 AND t.exploration_id=$3 AND n.kind='finding' FOR SHARE OF f, t, n`<br>L429 `INSERT` `INSERT INTO exploration_nodes(exploration_id,kind,payload,priority,state,origin) VALUES ($1,'intent',$2,10,'open','human') RETURNING id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/intent_admission.go::ExplorationStore.DiscardOpenIntent` · [근거](evidence:db-pg-access-exploration-nodes-6e9acab90e) | `write` / `DELETE` | L19 `DELETE` `DELETE FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='intent' AND state='open'` | [`feature-task-admission`](../../features/task-exploration.md#admission) |
| `db/side_questions.go::lockSideParent` · [근거](evidence:db-pg-access-exploration-nodes-b6cbb6ada7) | `read` / `FROM` | L27 `FROM` `SELECT id FROM exploration_nodes WHERE id=$1 AND exploration_id=$2 AND kind='intent' AND state<>'stopped' FOR SHARE` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-exploration-nodes-23d5e526fc) | `read` / `FROM,JOIN` | L580 `FROM` `source fragment: SELECT * FROM exploration_nodes WHERE exploration_id=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L582 `JOIN` `source fragment: SELECT anchor.* FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$1 ORDER BY node_id,asset_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetIDsQuery` · [근거](evidence:db-pg-access-exploration-nodes-73ee4ed5d8) | `read` / `JOIN` | L529 `JOIN` `…asset_links link WHERE link.task_id=$1 UNION SELECT anchor.asset_id FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$2 UNION SELECT value::bigint FROM findings finding CROSS JOIN LATERAL jsonb_array_elements_text( CASE WHEN jsonb_typeof(finding.asset_ids)='array' THEN finding.a…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetMetadata` · [근거](evidence:db-pg-access-exploration-nodes-3d946355b9) | `read` / `JOIN` | L682 `JOIN` `source fragment: WITH candidate AS (<archiveAssetIDsQuery helper composition>) SELECT asset.id FROM assets asset JOIN candidate ON candidate.id=asset.id WHERE <cross-task ownership and live-anchor exclusions> ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-exploration-nodes-f63769614e) | `read,write` / `DELETE,JOIN` | L97 `DELETE` `DELETE FROM exploration_nodes WHERE exploration_id=$1`<br>L107 `JOIN` `… IS NULL AND task.id=ANY(asset.task_ids)) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id JOIN tasks task ON task.exploration_id=node.exploration_id WHERE anchor.asset_id=asset.id AND task.id<>$1 AND task.deleted_at IS NULL )` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-exploration-nodes-9f2aa43be3) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-exploration-nodes-2d8095d714) | `read` / `JOIN` | L375 `JOIN` `…在黑板中锚定该资产'), link.source_node_id, context.task_id, context.inherited FROM context JOIN exploration_nodes intent ON intent.exploration_id=context.exploration_id AND intent.kind='intent' JOIN exploration_anchors anchor ON anchor.node_id=intent.id JOIN assets asset ON asset.id=anchor.asset_id LEFT JOIN task_asset_links link O…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-exploration-nodes-0c1dd0c452) | `read` / `JOIN` | L202 `JOIN` `…t_tasks ctx WHERE ctx.task_id=ANY(a.task_ids)) UNION SELECT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id UNION SELECT DISTINCT a.id FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id=ts.company_id) OR (ts.kind='root…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-exploration-nodes-6dd02d4e13) | `read` / `JOIN` | L170 `JOIN` `…app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fac…`<br>L177 `JOIN` `…app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fac…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-exploration-nodes-f08f896542) | `read` / `JOIN` | L127 `JOIN` `…app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fac…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_context.go::ExplorationStore.ReopenIntentsByBlockedReason` · [근거](evidence:db-pg-access-exploration-nodes-4dd0047815) | `write` / `UPDATE` | L570 `UPDATE` `UPDATE exploration_nodes SET state='open', blocked_reason=NULL, completed_at=NULL WHERE exploration_id=$1 AND kind='intent' AND state='blocked' AND blocked_reason=$2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_context.go::ExplorationStore.SetIntentBlockedReason` · [근거](evidence:db-pg-access-exploration-nodes-51cd9bfd51) | `write` / `UPDATE` | L563 `UPDATE` `UPDATE exploration_nodes SET state='blocked', blocked_reason=NULLIF($1,''), completed_at=now() WHERE id=$2 AND exploration_id=$3 AND kind='intent'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-exploration-nodes-36117988d4) | `read` / `JOIN` | L428 `JOIN` `…app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fac…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_scope.go::AssetStore.ListUntestedAssets` · [근거](evidence:db-pg-access-exploration-nodes-2492aca0a0) | `read` / `JOIN` | L622 `JOIN` `…', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT count(*) FROM target t WHERE t.id NOT IN (SELECT asset_id FROM tested) AND t.type = $3`<br>L627 `JOIN` `…', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT t.id, t.type, t.label FROM target t WHERE t.id NOT IN (SELECT asset_id FROM tested) AND t.type = $3 ORDER BY t.id LIMIT $ OFFSET $` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/task_scope.go::AssetStore.TaskCoverage` · [근거](evidence:db-pg-access-exploration-nodes-0353afaaa2) | `read` / `JOIN` | L331 `JOIN` `…', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT t.type, count(*) AS total, count(*) FILTER (WHERE t.id IN (SELECT asset_id FROM tested)) AS tested FROM target t GROUP BY t.type ORDER …` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/tasks.go::DB.CreateTaskWithOptions` · [근거](evidence:db-pg-access-exploration-nodes-3571e6f425) | `write` / `INSERT` | L191 `INSERT` `INSERT INTO exploration_nodes(exploration_id, kind, payload, priority, state, origin) VALUES ($1, 'fact', $2, 0, 'origin', 'system')` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-exploration-nodes-f22b29e5cd) | `read` / `JOIN` | L595 `JOIN` `…SELECT id FROM assets WHERE $1 = ANY(task_ids) UNION SELECT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id WHERE n.exploration_id=$2 ), deletable AS ( SELECT a.id FROM assets a JOIN candidate_assets c ON c.id=a.id WHERE NOT EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=A…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/triggers.go::DB.MetGoals` · [근거](evidence:db-pg-access-exploration-nodes-4cfc48ba13) | `read` / `FROM` | L273 `FROM` `SELECT n.id, t.id, t.description, t.goal, n.payload FROM exploration_nodes n JOIN tasks t ON t.exploration_id = n.exploration_id WHERE n.kind='goal' AND n.state='met' AND t.deleted_at IS NULL ORDER BY n.id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.NewFindingsSince` · [근거](evidence:db-pg-access-exploration-nodes-b88407dcf9) | `read` / `FROM` | L168 `FROM` `SELECT n.id, t.id, t.description, t.goal, n.payload FROM exploration_nodes n JOIN tasks t ON t.exploration_id = n.exploration_id WHERE n.kind='finding' AND n.id > $1 AND t.deleted_at IS NULL ORDER BY n.id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |

**처분** · located production table-symbol binding 74개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-exploration-edges"></a>
## `exploration_edges`

[exploration_edges 물리 객체](task-exploration.md#table-exploration-edges) · [field 의미](semantic-catalog.md#semantic-exploration-edges)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/digest.go::ExplorationStore.AddDigest` · [근거](evidence:db-pg-access-exploration-edges-81bd2096a6) | `write` / `INSERT` | L140 `INSERT` `INSERT INTO exploration_edges(exploration_id, src_id, rel, dst_id) VALUES ($1,$2,$3,$4) ON CONFLICT (exploration_id, src_id, rel, dst_id) DO NOTHING` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.CoveredMembers` · [근거](evidence:db-pg-access-exploration-edges-015f60f999) | `read` / `FROM` | L154 `FROM` `SELECT e.dst_id, e.src_id FROM exploration_edges e JOIN exploration_nodes d ON d.id=e.src_id AND d.exploration_id=e.exploration_id WHERE e.exploration_id=$1 AND e.rel=$2 AND d.kind=$3 AND d.state=$4 ORDER BY e.src_id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.DigestMembers` · [근거](evidence:db-pg-access-exploration-edges-9223b53392) | `read` / `FROM` | L179 `FROM` `SELECT dst_id FROM exploration_edges WHERE exploration_id=$1 AND src_id=$2 AND rel=$3` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/digest.go::ExplorationStore.SupersedeDigests` · [근거](evidence:db-pg-access-exploration-edges-8224e1bd48) | `write` / `DELETE` | L211 `DELETE` `DELETE FROM exploration_edges WHERE exploration_id=$1 AND src_id=$2 AND rel=$3` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.CancelIntent` · [근거](evidence:db-pg-access-exploration-edges-76b94df119) | `read` / `FROM` | L478 `FROM` `SELECT src_id, rel, dst_id FROM exploration_edges WHERE exploration_id=$1` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.Edges` · [근거](evidence:db-pg-access-exploration-edges-9ebe84819c) | `read` / `FROM` | L986 `FROM` `SELECT src_id, rel, dst_id FROM exploration_edges WHERE exploration_id=$1 LIMIT $2` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.EdgesTouching` · [근거](evidence:db-pg-access-exploration-edges-c4d236d501) | `read` / `FROM` | L957 `FROM` `SELECT src_id, rel, dst_id FROM exploration_edges WHERE exploration_id=$1 AND (src_id IN (<runtime-expanded placeholders>) OR dst_id IN (<runtime-expanded placeholders>))` · runtime fragment A/U | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FactsYielded` · [근거](evidence:db-pg-access-exploration-edges-8d33d00bf4) | `read` / `FROM` | L1007 `FROM` `SELECT n.id FROM exploration_edges e JOIN exploration_nodes n ON n.id=e.dst_id AND n.exploration_id=e.exploration_id WHERE e.exploration_id=$1 AND e.src_id=$2 AND e.rel=$3 AND n.kind=$4 ORDER BY n.id` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingIntents` · [근거](evidence:db-pg-access-exploration-edges-917a32807b) | `read` / `FROM` | L1091 `FROM` `SELECT e.dst_id, e.src_id FROM exploration_edges e JOIN exploration_nodes n ON n.id = e.dst_id AND n.exploration_id = e.exploration_id WHERE e.exploration_id=$1 AND e.rel=$2 AND n.kind='finding'` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingIntentsTerminal` · [근거](evidence:db-pg-access-exploration-edges-447406e91e) | `read` / `FROM` | L1114 `FROM` `SELECT e.dst_id, e.src_id FROM exploration_edges e JOIN exploration_nodes finding ON finding.id=e.dst_id AND finding.exploration_id=e.exploration_id JOIN exploration_nodes intent ON intent.id=e.src_id AND intent.exploration_id=e.exploration_id WHERE e.exploration_id=$…` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.FindingLineage` · [근거](evidence:db-pg-access-exploration-edges-9c53251fb5) | `read` / `FROM` | L1034 `FROM` `WITH RECURSIVE anc(id) AS ( SELECT $2::bigint UNION SELECT e.src_id FROM exploration_edges e JOIN anc ON e.dst_id = anc.id WHERE e.exploration_id = $1 ) SELECT id, kind, payload, priority, state, COALESCE(origin,''), COALESCE(owner,''), COALESCE(blocked_reason,''), COALESCE(delete_reason,''), created_at FROM …`<br>L1058 `FROM` `WITH RECURSIVE anc(id) AS ( SELECT $2::bigint UNION SELECT e.src_id FROM exploration_edges e JOIN anc ON e.dst_id = anc.id WHERE e.exploration_id = $1 ) SELECT src_id, rel, dst_id FROM exploration_edges WHERE exploration_id = $1 AND src_id IN (SELECT id FROM anc) AND dst_id IN (SELECT id FROM anc)` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/exploration.go::ExplorationStore.Link` · [근거](evidence:db-pg-access-exploration-edges-4a837468d6) | `write` / `INSERT` | L260 `INSERT` `INSERT INTO exploration_edges(exploration_id, src_id, rel, dst_id) VALUES ($1,$2,$3,$4) ON CONFLICT (exploration_id, src_id, rel, dst_id) DO NOTHING` | [`feature-task-feedback`](../../features/task-exploration.md#feedback-loop) |
| `db/finding_traffic.go::RecordFindingTx` · [근거](evidence:db-pg-access-exploration-edges-d307a68e3d) | `write` / `INSERT` | L376 `INSERT` `INSERT INTO exploration_edges(exploration_id,src_id,rel,dst_id) VALUES($1,$2,$3,$4)` | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-exploration-edges-a5f6b5b826) | `write` / `INSERT` | L438 `INSERT` `INSERT INTO exploration_edges(exploration_id,src_id,rel,dst_id) VALUES ($1,$2,$3,$4)` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-exploration-edges-7848b19d51) | `read` / `FROM` | L581 `FROM` `source fragment: SELECT * FROM exploration_edges WHERE exploration_id=$1 ORDER BY src_id,dst_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-exploration-edges-3370ec36d7) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 16개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-exploration-anchors"></a>
## `exploration_anchors`

[exploration_anchors 물리 객체](task-exploration.md#table-exploration-anchors) · [field 의미](semantic-catalog.md#semantic-exploration-anchors)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/assets.go::hostsForTaskDeletion` · [근거](evidence:db-pg-access-exploration-anchors-5a27ac6eca) | `read` / `FROM` | L1286 `FROM` `…ROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) OR EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WHERE ea.asset_id=a.id AND t.id<>$1 AND t.deleted_at IS NULL ) ) SELECT COALESCE(a.domain,''), COALESCE(a.ip,''), COALESCE…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/digest.go::ExplorationStore.NodeAssets` · [근거](evidence:db-pg-access-exploration-anchors-cddd26dae2) | `read` / `FROM` | L237 `FROM` `SELECT a.node_id, a.asset_id FROM exploration_anchors a JOIN exploration_nodes n ON n.id=a.node_id WHERE n.exploration_id=$1 AND a.node_id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/exploration.go::ExplorationStore.AddNode` · [근거](evidence:db-pg-access-exploration-anchors-834586a2d0) | `write` / `INSERT` | L212 `INSERT` `INSERT INTO exploration_anchors(node_id, asset_id) VALUES ($1,$2) ON CONFLICT DO NOTHING` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/exploration.go::ExplorationStore.Anchor` · [근거](evidence:db-pg-access-exploration-anchors-f5ce264565) | `write` / `INSERT` | L254 `INSERT` `INSERT INTO exploration_anchors(node_id, asset_id) VALUES ($1,$2) ON CONFLICT DO NOTHING` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/exploration.go::ExplorationStore.AssetRefs` · [근거](evidence:db-pg-access-exploration-anchors-a45cbd8b32) | `read` / `FROM` | L1896 `FROM` `SELECT en.id, en.kind, en.state, en.payload FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE ea.asset_id = $1 AND en.exploration_id = $2 AND en.kind IN ('intent','fact','finding') ORDER BY en.id DESC` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/finding_traffic.go::RecordFindingTx` · [근거](evidence:db-pg-access-exploration-anchors-0bdf8724cf) | `write` / `INSERT` | L371 `INSERT` `INSERT INTO exploration_anchors(node_id,asset_id) VALUES($1,$2) ON CONFLICT DO NOTHING` | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-exploration-anchors-1f6ef5ecee) | `read,write` / `FROM,INSERT` | L396 `FROM` `SELECT asset_id FROM exploration_anchors WHERE node_id=$1 ORDER BY asset_id`<br>L433 `FROM` `INSERT INTO exploration_anchors(node_id,asset_id) SELECT $1, asset_id FROM exploration_anchors WHERE node_id=$2 ON CONFLICT DO NOTHING`<br>L433 `INSERT` `INSERT INTO exploration_anchors(node_id,asset_id) SELECT $1, asset_id FROM exploration_anchors WHERE node_id=$2 ON CONFLICT DO NOTHING` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-exploration-anchors-be474215d0) | `read` / `FROM` | L582 `FROM` `source fragment: SELECT anchor.* FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$1 ORDER BY node_id,asset_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetIDsQuery` · [근거](evidence:db-pg-access-exploration-anchors-05cdec3c1d) | `read` / `FROM` | L529 `FROM` `… SELECT link.asset_id FROM task_asset_links link WHERE link.task_id=$1 UNION SELECT anchor.asset_id FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$2 UNION SELECT value::bigint FROM findings finding CROSS JOIN LATERAL jsonb_array_elements_text( CASE WHEN jsonb_typeof(finding.ass…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetMetadata` · [근거](evidence:db-pg-access-exploration-anchors-fa433a48a2) | `read` / `FROM` | L682 `FROM` `source fragment: WITH candidate AS (<archiveAssetIDsQuery helper composition>) SELECT asset.id FROM assets asset JOIN candidate ON candidate.id=asset.id WHERE <cross-task ownership and live-anchor exclusions> ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-exploration-anchors-a71aa2d014) | `lock,read` / `FROM,LOCK` | L64 `LOCK` `LOCK TABLE assets, exploration_anchors IN SHARE ROW EXCLUSIVE MODE`<br>L107 `FROM` `… task.id<>$1 AND task.deleted_at IS NULL AND task.id=ANY(asset.task_ids)) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id JOIN tasks task ON task.exploration_id=node.exploration_id WHERE anchor.asset_id=asset.id AND task.id<>$1 AND task.deleted_at IS NULL )` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-exploration-anchors-fe5a2c95b9) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-exploration-anchors-8a1db68a70) | `read` / `JOIN` | L375 `JOIN` `…N exploration_nodes intent ON intent.exploration_id=context.exploration_id AND intent.kind='intent' JOIN exploration_anchors anchor ON anchor.node_id=intent.id JOIN assets asset ON asset.id=anchor.asset_id LEFT JOIN task_asset_links link ON link.task_id=context.task_id AND link.asset_id=asset.id WHERE NOT context.inherited OR intent.state IN …` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-exploration-anchors-6bdbe05e5c) | `read` / `FROM` | L202 `FROM` `…EXISTS (SELECT 1 FROM context_tasks ctx WHERE ctx.task_id=ANY(a.task_ids)) UNION SELECT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id UNION SELECT DISTINCT a.id FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id=ts.com…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-exploration-anchors-94dc4ab10f) | `read` / `FROM,JOIN` | L170 `FROM` `…ontext_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fact' JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ) SELECT count(*) FROM target WHERE target.id NOT IN (SELECT asset_id FROM tested) AND t…`<br>L170 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration…`<br>L177 `FROM` `…ontext_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fact' JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ) SELECT target.id, target.type, target.label FROM target WHERE target.id NOT IN (SELECT…`<br>L177 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-exploration-anchors-ef2bc724eb) | `read` / `FROM,JOIN` | L127 `FROM` `…ontext_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fact' JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ) SELECT target.type, count(*) AS total, count(*) FILTER (WHERE target.id IN (SELECT ass…`<br>L127 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-exploration-anchors-a6e404bec9) | `read` / `FROM,JOIN` | L428 `FROM` `…ontext_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id=ea.node_id AND en.kind='fact' JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ) SELECT a.id, a.type, COALESCE(a.company_id,0), COALESCE(a.domain,''), COALESCE(a.root_…`<br>L428 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN exploration_anchors ea ON ea.asset_id=a.id JOIN exploration_nodes en ON en.id=ea.node_id JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_scope.go::AssetStore.ListUntestedAssets` · [근거](evidence:db-pg-access-exploration-anchors-386313636a) | `read` / `FROM` | L622 `FROM` `…a.app_icp,''), '[[:space:]]+', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT count(*) FROM target t WHERE t.id NOT IN (SELECT asset_id FROM tested) AND t.type = $3`<br>L627 `FROM` `…a.app_icp,''), '[[:space:]]+', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT t.id, t.type, t.label FROM target t WHERE t.id NOT IN (SELECT asset_id FROM tested) AND t.type = $3 ORDER BY …` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/task_scope.go::AssetStore.TaskCoverage` · [근거](evidence:db-pg-access-exploration-anchors-8e3b76a0f7) | `read` / `FROM` | L331 `FROM` `…a.app_icp,''), '[[:space:]]+', '', 'g')) = ts.value )) ) ), tested AS ( SELECT DISTINCT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes en ON en.id = ea.node_id WHERE en.exploration_id = $2 AND en.kind = 'fact' ) SELECT t.type, count(*) AS total, count(*) FILTER (WHERE t.id IN (SELECT asset_id FROM tested)) AS tested FROM targe…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-exploration-anchors-fc3554358c) | `lock,read` / `FROM,LOCK` | L574 `LOCK` `LOCK TABLE assets, exploration_anchors IN SHARE ROW EXCLUSIVE MODE`<br>L595 `FROM` `WITH candidate_assets AS ( SELECT id FROM assets WHERE $1 = ANY(task_ids) UNION SELECT ea.asset_id FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id WHERE n.exploration_id=$2 ), deletable AS ( SELECT a.id FROM assets a JOIN candidate_assets c ON c.id=a.id WHERE NOT EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.del…` | [`feature-coverage`](../../features/assets-scope.md#coverage) |

**처분** · located production table-symbol binding 20개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-constraints"></a>
## `task_constraints`

[task_constraints 물리 객체](task-exploration.md#table-task-constraints) · [field 의미](semantic-catalog.md#semantic-task-constraints)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/constraints.go::ExplorationStore.AddConstraint` · [근거](evidence:db-pg-access-task-constraints-d43b115d37) | `write` / `INSERT` | L50 `INSERT` `INSERT INTO task_constraints(exploration_id, kind, text, origin) VALUES ($1, $2, $3, $4) RETURNING id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/constraints.go::ExplorationStore.DeleteConstraint` · [근거](evidence:db-pg-access-task-constraints-e7c316fe99) | `write` / `DELETE` | L77 `DELETE` `DELETE FROM task_constraints WHERE id=$1 AND exploration_id=$2` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/constraints.go::ExplorationStore.ListConstraints` · [근거](evidence:db-pg-access-task-constraints-1966fa44c7) | `read` / `FROM` | L22 `FROM` `SELECT id, kind, text, COALESCE(origin,''), created_at FROM task_constraints WHERE exploration_id=$1 ORDER BY (kind='deny'), id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/constraints.go::ExplorationStore.UpdateConstraint` · [근거](evidence:db-pg-access-task-constraints-9d935e4a11) | `write` / `UPDATE` | L62 `UPDATE` `UPDATE task_constraints SET kind=$1, text=$2, updated_at=now() WHERE id=$3 AND exploration_id=$4` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-task-constraints-7ade884b9f) | `read` / `FROM` | L85 `FROM` `…ids @> to_jsonb(ARRAY[a.id])), '[]'::jsonb), 'constraints', COALESCE((SELECT jsonb_agg(to_jsonb(c)) FROM task_constraints c JOIN tasks t ON t.exploration_id=c.exploration_id WHERE t.id=f.task_id), '[]'::jsonb)) FROM findings f WHERE f.id=$1 FOR UPDATE OF f` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-task-constraints-91f41f4c8e) | `read` / `FROM` | L583 `FROM` `source fragment: SELECT * FROM task_constraints WHERE exploration_id=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-constraints-ac6211dfde) | `write` / `DELETE` | L95 `DELETE` `DELETE FROM task_constraints WHERE exploration_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-task-constraints-b779165144) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 8개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-activity"></a>
## `activity`

[activity 물리 객체](task-exploration.md#table-activity) · [field 의미](semantic-catalog.md#semantic-activity)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/commands.go::DB.ListCommands` · [근거](evidence:db-pg-access-activity-e60a1bb046) | `read` / `FROM,JOIN` | L96 `FROM` `source fragment: SELECT COUNT(*) FROM activity u <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L102 `FROM` `source fragment: …u.tool,''), COALESCE(u.detail,''), COALESCE(r.detail,''), COALESCE(r.is_error, false), u.created_at FROM activity u LEFT JOIN activity r ON r.tool_use_id = u.tool_use_id AND r.kind = 'tool_result' <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L102 `JOIN` `source fragment: …u.detail,''), COALESCE(r.detail,''), COALESCE(r.is_error, false), u.created_at FROM activity u LEFT JOIN activity r ON r.tool_use_id = u.tool_use_id AND r.kind = 'tool_result' <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/commands.go::DB.ToolStats` · [근거](evidence:db-pg-access-activity-72ffb7dbac) | `read` / `FROM,JOIN` | L56 `FROM` `source fragment: …l,''),'-') AS tool, COUNT(*) AS total, COUNT(*) FILTER (WHERE COALESCE(r.is_error,false)) AS errors FROM activity u LEFT JOIN activity r ON r.tool_use_id = u.tool_use_id AND r.kind = 'tool_result' GROUP BY 1 ORDER BY total DESC, tool ASC <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L56 `JOIN` `source fragment: …OUNT(*) AS total, COUNT(*) FILTER (WHERE COALESCE(r.is_error,false)) AS errors FROM activity u LEFT JOIN activity r ON r.tool_use_id = u.tool_use_id AND r.kind = 'tool_result' GROUP BY 1 ORDER BY total DESC, tool ASC <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/exploration.go::DB.LastActivityAll` · [근거](evidence:db-pg-access-activity-06873ea5ba) | `read` / `FROM` | L1277 `FROM` `SELECT exploration_id, EXTRACT(EPOCH FROM MAX(created_at))::bigint FROM activity GROUP BY exploration_id` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::DB.TaskListMetricsAll` · [근거](evidence:db-pg-access-activity-5bad9011aa) | `read` / `FROM` | L1313 `FROM` `…_tokens, SUM(cache_read_tokens) AS cache_read_tokens, SUM(cache_write_tokens) AS cache_write_tokens FROM activity WHERE exploration_id=task.exploration_id AND kind='result' ) token_metrics ON true LEFT JOIN LATERAL ( SELECT EXTRACT(EPOCH FROM created_at)::bigint AS created_at FROM activity WHERE exploration_id=task.exploration_id O…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::DB.TokenDailyAll` · [근거](evidence:db-pg-access-activity-3a8fbeae9a) | `read` / `FROM` | L146 `FROM` `…OALESCE(SUM(input_tokens), 0), COALESCE(SUM(output_tokens), 0), COALESCE(SUM(cache_read_tokens), 0) FROM activity WHERE kind = 'result' AND created_at >= NOW() - ($1 * INTERVAL '1 day') GROUP BY day ORDER BY day` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::DB.TokenTotalsAll` · [근거](evidence:db-pg-access-activity-5667024f17) | `read` / `FROM` | L1252 `FROM` `…ESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read_tokens),0), COALESCE(SUM(cache_write_tokens),0) FROM activity WHERE kind='result' GROUP BY exploration_id` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityByIDs` · [근거](evidence:db-pg-access-activity-b8a7471493) | `read` / `FROM` | L1963 `FROM` `SELECT id, node_id, COALESCE(kind,''), COALESCE(tool,''), is_error, COALESCE(detail,'') FROM activity WHERE exploration_id=$1 AND kind<>'thinking' AND id IN (<runtime-expanded placeholders>) ORDER BY id` · runtime fragment A/U | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityByIDsForTerminalIntents` · [근거](evidence:db-pg-access-activity-c6ab40468d) | `read` / `FROM` | L1995 `FROM` `SELECT a.id, a.node_id, COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.detail,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.kind NOT IN ('thinking','usage') AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopp…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityDetail` · [근거](evidence:db-pg-access-activity-8dee84ba63) | `read` / `FROM` | L1746 `FROM` `SELECT detail FROM activity WHERE id=$1 AND exploration_id=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityList` · [근거](evidence:db-pg-access-activity-cdc07f17b4) | `read` / `FROM` | L1487 `FROM` `… metadata, created_at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, main_seg FROM activity WHERE exploration_id=$1 AND node_id=$2 AND id>$3 ORDER BY id LIMIT $4`<br>L1490 `FROM` `… metadata, created_at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, main_seg FROM activity WHERE exploration_id=$1 AND id>$2 ORDER BY id LIMIT $3` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityListForTerminalIntent` · [근거](evidence:db-pg-access-activity-ee8260e4b6) | `read` / `FROM` | L1521 `FROM` `…mmary,''), a.created_at, a.input_tokens, a.output_tokens, a.cache_read_tokens, a.cache_write_tokens FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND a.id>$3 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityMaxID` · [근거](evidence:db-pg-access-activity-16be78d8ef) | `read` / `FROM` | L1685 `FROM` `SELECT MAX(id) FROM activity WHERE exploration_id=$1` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityPage` · [근거](evidence:db-pg-access-activity-0d669b74a9) | `read` / `FROM` | L1603 `FROM` `FROM activity WHERE exploration_id=$1%s AND ($%d <= 0 OR id < $%d) ORDER BY id DESC LIMIT $%d` · runtime fragment A/U | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityPageForTerminalIntent` · [근거](evidence:db-pg-access-activity-614aa5e140) | `read` / `FROM` | L1642 `FROM` `…mmary,''), a.created_at, a.input_tokens, a.output_tokens, a.cache_read_tokens, a.cache_write_tokens FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTrace` · [근거](evidence:db-pg-access-activity-01e7477130) | `read` / `FROM` | L1778 `FROM` `… node_id, COALESCE(worker,''), COALESCE(kind,''), COALESCE(tool,''), is_error, COALESCE(summary,'') FROM activity WHERE exploration_id=$1 AND node_id=$2 AND kind NOT IN ('thinking','usage') ORDER BY id LIMIT $3` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTraceForTerminalIntent` · [근거](evidence:db-pg-access-activity-04de768c7d) | `read` / `FROM` | L1794 `FROM` `…COALESCE(a.worker,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearch` · [근거](evidence:db-pg-access-activity-6906efe726) | `read` / `FROM` | L1820 `FROM` `… node_id, COALESCE(worker,''), COALESCE(kind,''), COALESCE(tool,''), is_error, COALESCE(summary,'') FROM activity WHERE exploration_id=$1 AND node_id=$2 AND kind NOT IN ('thinking','usage') AND (summary ILIKE $3 OR detail ILIKE $3) ORDER BY id LIMIT $4`<br>L1824 `FROM` `… node_id, COALESCE(worker,''), COALESCE(kind,''), COALESCE(tool,''), is_error, COALESCE(summary,'') FROM activity WHERE exploration_id=$1 AND node_id IS NOT NULL AND kind NOT IN ('thinking','usage') AND (summary ILIKE $2 OR detail ILIKE $2) ORDER BY id LIMIT $3` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearchExcluding` · [근거](evidence:db-pg-access-activity-a7b6b38455) | `read` / `FROM` | L1938 `FROM` `… node_id, COALESCE(worker,''), COALESCE(kind,''), COALESCE(tool,''), is_error, COALESCE(summary,'') FROM activity WHERE exploration_id=$1 AND node_id IS NOT NULL AND node_id <> $2 AND kind NOT IN ('thinking','usage') AND (summary ILIKE $3 OR detail ILIKE $3) ORDER BY id LIMIT $4` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearchForTerminalIntent` · [근거](evidence:db-pg-access-activity-3cba83cb26) | `read` / `FROM` | L1842 `FROM` `…COALESCE(a.worker,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND a.node_id=$2 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.ActivityTraceSearchTerminalIntents` · [근거](evidence:db-pg-access-activity-463f0ca1de) | `read` / `FROM` | L1864 `FROM` `…COALESCE(a.worker,''), COALESCE(a.kind,''), COALESCE(a.tool,''), a.is_error, COALESCE(a.summary,'') FROM activity a JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id WHERE a.exploration_id=$1 AND n.kind='intent' AND n.state IN ('done','blocked','exhausted','stopped') AND a.kind NOT IN ('thinking','usa…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.AppendActivity` · [근거](evidence:db-pg-access-activity-fcba803edd) | `write` / `INSERT` | L1211 `INSERT` `INSERT INTO activity(exploration_id, node_id, worker, kind, tool, tool_use_id, is_error, summary, detail, metadata, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, main_seg) VALUES ($1,$2,NULLIF($3,''),NULLIF($4,''),NULL…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.CancelIntent` · [근거](evidence:db-pg-access-activity-b51fa97fd0) | `write` / `DELETE,INSERT` | L547 `DELETE` `DELETE FROM activity WHERE exploration_id=$1 AND node_id=$2`<br>L560 `INSERT` `INSERT INTO activity( exploration_id, worker, kind, summary, metadata, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, created_at) VALUES ($1,'token-ledger','result',$2,$3,$4,$5,$6,$7,$8)` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.TokenStatsBySession` · [근거](evidence:db-pg-access-activity-3c8b33d651) | `read` / `FROM` | L1446 `FROM` `…UM(a.output_tokens),0), COALESCE(SUM(a.cache_read_tokens),0), COALESCE(SUM(a.cache_write_tokens),0) FROM activity a LEFT JOIN exploration_nodes n ON n.id=a.node_id AND n.exploration_id=a.exploration_id AND n.kind='intent' WHERE a.exploration_id=$1 AND a.kind='result' AND (COALESCE(a.worker,'') IN ('mainagent','planner') OR n.id IS …` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.TokenStatsByWorker` · [근거](evidence:db-pg-access-activity-4798d96f03) | `read` / `FROM` | L1422 `FROM` `…ESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read_tokens),0), COALESCE(SUM(cache_write_tokens),0) FROM activity WHERE exploration_id=$1 AND kind='result' GROUP BY worker ORDER BY worker` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::ExplorationStore.TokenTotal` · [근거](evidence:db-pg-access-activity-511cbb267f) | `read` / `FROM` | L1240 `FROM` `…ESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read_tokens),0), COALESCE(SUM(cache_write_tokens),0) FROM activity WHERE exploration_id=$1 AND kind='result'` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/exploration.go::intentTokenRollup` · [근거](evidence:db-pg-access-activity-db5d149f27) | `read` / `FROM` | L610 `FROM` `SELECT kind, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, created_at FROM activity WHERE exploration_id=$1 AND node_id=$2 AND kind IN ('usage','result') ORDER BY id` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-activity-e9d0dcc600) | `write` / `INSERT` | L453 `INSERT` `INSERT INTO activity(exploration_id, node_id, worker, kind, tool, tool_use_id, is_error, summary, detail, metadata, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens) VALUES ($1,$2,NULLIF($3,''),NULLIF($4,''),NULLIF($5,''),…` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/intent_admission.go::ExplorationStore.DiscardOpenIntent` · [근거](evidence:db-pg-access-activity-2799bfe0df) | `write` / `DELETE` | L16 `DELETE` `DELETE FROM activity WHERE exploration_id=$1 AND node_id=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/intercept_execution.go::DB.GetInterceptExecution` · [근거](evidence:db-pg-access-activity-d1733afaac) | `read` / `FROM` | L51 `FROM` `…ker,''), kind, COALESCE(tool,''), tool_use_id, is_error, COALESCE(summary,''), created_at, main_seg FROM activity WHERE exploration_id=(SELECT exploration_id FROM tasks WHERE id=$1 AND archived_at IS NULL AND deleted_at IS NULL)`<br>L56 `FROM` `…ker,''), kind, COALESCE(tool,''), tool_use_id, is_error, COALESCE(summary,''), created_at, main_seg FROM activity WHERE exploration_id=(SELECT exploration_id FROM tasks WHERE id=$1 AND archived_at IS NULL AND deleted_at IS NULL) AND tool_use_id=$2 AND kind IN ('tool_use','tool_result') ORDER BY id LIMIT 3` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-activity-36e48e8d45) | `read` / `FROM` | L584 `FROM` `source fragment: SELECT * FROM activity WHERE exploration_id=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-activity-66abc87251) | `write` / `DELETE` | L96 `DELETE` `DELETE FROM activity WHERE exploration_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-activity-90da0128e3) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/triggers.go::DB.NewToolCallsSince` · [근거](evidence:db-pg-access-activity-44974d0f5e) | `read` / `FROM,JOIN` | L248 `FROM` `…r.id, t.id, t.description, t.goal, r.tool, COALESCE(u.detail,''), COALESCE(r.detail,''), r.is_error FROM activity r JOIN tasks t ON t.exploration_id = r.exploration_id LEFT JOIN activity u ON u.exploration_id = r.exploration_id AND u.tool_use_id = r.tool_use_id AND u.kind='tool_use' WHERE r.kind='tool_result' AND r.id > $1 AND r.to…`<br>L248 `JOIN` `…E(r.detail,''), r.is_error FROM activity r JOIN tasks t ON t.exploration_id = r.exploration_id LEFT JOIN activity u ON u.exploration_id = r.exploration_id AND u.tool_use_id = r.tool_use_id AND u.kind='tool_use' WHERE r.kind='tool_result' AND r.id > $1 AND r.tool <> '' AND t.deleted_at IS NULL ORDER BY r.id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |

**처분** · located production table-symbol binding 33개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-main-sessions"></a>
## `main_sessions`

[main_sessions 물리 객체](task-exploration.md#table-main-sessions) · [field 의미](semantic-catalog.md#semantic-main-sessions)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/exploration.go::ExplorationStore.CurrentMainSeg` · [근거](evidence:db-pg-access-main-sessions-2d68551366) | `read` / `FROM` | L1704 `FROM` `SELECT COALESCE(MAX(seq),0) FROM main_sessions WHERE exploration_id=$1` | [`feature-main-agent`](../../features/human-control.md#main-agent) |
| `db/exploration.go::ExplorationStore.ListMainSessions` · [근거](evidence:db-pg-access-main-sessions-c3b14e96fc) | `read` / `FROM` | L1711 `FROM` `SELECT seq, created_at FROM main_sessions WHERE exploration_id=$1 ORDER BY seq DESC` | [`feature-main-agent`](../../features/human-control.md#main-agent) |
| `db/exploration.go::ExplorationStore.NewMainSession` · [근거](evidence:db-pg-access-main-sessions-a1f2093b65) | `read,write` / `FROM,INSERT` | L1736 `FROM` `INSERT INTO main_sessions(exploration_id, seq) VALUES ($1, COALESCE((SELECT MAX(seq) FROM main_sessions WHERE exploration_id=$1),0)+1) RETURNING seq, created_at`<br>L1736 `INSERT` `INSERT INTO main_sessions(exploration_id, seq) VALUES ($1, COALESCE((SELECT MAX(seq) FROM main_sessions WHERE exploration_id=$1),0)+1) RETURNING seq, created_at` | [`feature-main-agent`](../../features/human-control.md#main-agent) |

**처분** · located production table-symbol binding 3개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-settings"></a>
## `settings`

[settings 물리 객체](findings-operations.md#table-settings) · [field 의미](semantic-catalog.md#semantic-settings)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/settings.go::DB.GetSetting` · [근거](evidence:db-pg-access-settings-244498fc06) | `read` / `FROM` | L10 `FROM` `SELECT value FROM settings WHERE key=$1` | [`module-storage-manager`](../../modules/storage-runtime.md#manager-lifecycle) |
| `db/settings.go::DB.SetSetting` · [근거](evidence:db-pg-access-settings-18f2c4aada) | `write` / `INSERT` | L22 `INSERT` `INSERT INTO settings(key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()` | [`module-storage-manager`](../../modules/storage-runtime.md#manager-lifecycle) |
| `server/finding_retests.go::Server.seedFindingRetester` · [근거](evidence:db-pg-access-settings-f47899da10) | `read,write` / `FROM,INSERT` | L213 `FROM` `SELECT value FROM settings WHERE key=$1`<br>L237 `INSERT` `INSERT INTO settings(key,value) VALUES ($1,'true') ON CONFLICT(key) DO UPDATE SET value='true'` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 3개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-llm-profiles"></a>
## `llm_profiles`

[llm_profiles 물리 객체](agent-runtime.md#table-llm-profiles) · [field 의미](semantic-catalog.md#semantic-llm-profiles)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.ActiveProfile` · [근거](evidence:db-pg-access-llm-profiles-eaec5da39c) | `read` / `FROM` | L117 `FROM` `…E(retry_empty_interval_ms,0),COALESCE(retry_stream_attempts,0),COALESCE(retry_stream_interval_ms,0) FROM llm_profiles WHERE is_default LIMIT 1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.ListProfiles` · [근거](evidence:db-pg-access-llm-profiles-3fcac6dc00) | `read` / `FROM` | L98 `FROM` `…E(retry_empty_interval_ms,0),COALESCE(retry_stream_attempts,0),COALESCE(retry_stream_interval_ms,0) FROM llm_profiles ORDER BY id` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.PoolProfiles` · [근거](evidence:db-pg-access-llm-profiles-f4364ceaa1) | `read` / `FROM` | L141 `FROM` `…E(retry_empty_interval_ms,0),COALESCE(retry_stream_attempts,0),COALESCE(retry_stream_interval_ms,0) FROM llm_profiles WHERE COALESCE(api_key,'') <> '' AND (is_default OR NOT pool_exclude) ORDER BY is_default DESC, priority DESC, id ASC` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.ProfileByID` · [근거](evidence:db-pg-access-llm-profiles-b958272071) | `read` / `FROM` | L128 `FROM` `…E(retry_empty_interval_ms,0),COALESCE(retry_stream_attempts,0),COALESCE(retry_stream_interval_ms,0) FROM llm_profiles WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.SaveProfile` · [근거](evidence:db-pg-access-llm-profiles-dfee149965) | `write` / `INSERT,UPDATE` | L168 `INSERT` `INSERT INTO llm_profiles(name,format,base_url,proxy,model,api_key,api_key_hint,rate_per_second,rate_per_minute,context_window_k,reasoning_effort,priority,pool_exclude,thinking_type,streaming,max_tokens,max_tokens_field,session_header_key,retry_…`<br>L175 `UPDATE` `UPDATE llm_profiles SET name=$1,format=$2,base_url=NULLIF($3,''),proxy=NULLIF($4,''),model=$5,rate_per_second=$6,rate_per_minute=$7,context_window_k=$8,reasoning_effort=$9,priority=$10,pool_exclude=$11,thinking_type=$12,streaming=$13,max_t…`<br>L180 `UPDATE` `UPDATE llm_profiles SET name=$1,format=$2,base_url=NULLIF($3,''),proxy=NULLIF($4,''),model=$5,api_key=$6,api_key_hint=$7,rate_per_second=$8,rate_per_minute=$9,context_window_k=$10,reasoning_effort=$11,priority=$12,pool_exclude=$13,thinking…` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.SetActiveProfile` · [근거](evidence:db-pg-access-llm-profiles-5d1d592ee5) | `write` / `UPDATE` | L425 `UPDATE` `UPDATE llm_profiles SET is_default=false WHERE is_default`<br>L428 `UPDATE` `UPDATE llm_profiles SET is_default=true WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.deleteProfile` · [근거](evidence:db-pg-access-llm-profiles-880cbddcb0) | `read,write` / `DELETE,FROM` | L261 `FROM` `SELECT is_default FROM llm_profiles WHERE id=$1 FOR UPDATE`<br>L354 `DELETE` `DELETE FROM llm_profiles WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::lockLLMProfileForReference` · [근거](evidence:db-pg-access-llm-profiles-9d5f2d7cbf) | `read` / `FROM` | L629 `FROM` `SELECT id FROM llm_profiles WHERE id=$1 FOR KEY SHARE` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_archives_restore.go::rowExists` · [근거](evidence:db-pg-access-llm-profiles-2302429399) | `read` / `FROM` | L360 `FROM` `SELECT EXISTS(SELECT 1 FROM <allowlisted table> WHERE id=$1)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 9개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-llm-profile-health"></a>
## `llm_profile_health`

[llm_profile_health 물리 객체](agent-runtime.md#table-llm-profile-health) · [field 의미](semantic-catalog.md#semantic-llm-profile-health)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/llmhealth.go::DB.ClearLLMHealth` · [근거](evidence:db-pg-access-llm-profile-health-ec65e5a507) | `write` / `DELETE` | L55 `DELETE` `DELETE FROM llm_profile_health WHERE profile_id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llmhealth.go::DB.LoadLLMHealth` · [근거](evidence:db-pg-access-llm-profile-health-ce50ed16a5) | `read` / `FROM` | L24 `FROM` `SELECT profile_id,fails,trips,open_until,COALESCE(last_error,''),last_at FROM llm_profile_health WHERE open_until IS NOT NULL AND open_until > now()` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llmhealth.go::DB.SaveLLMHealth` · [근거](evidence:db-pg-access-llm-profile-health-f52b5efe5f) | `write` / `INSERT` | L43 `INSERT` `INSERT INTO llm_profile_health(profile_id,fails,trips,open_until,last_error,last_at) VALUES ($1,$2,$3,$4,$5,now()) ON CONFLICT (profile_id) DO UPDATE SET fails=EXCLUDED.fails, trips=EXCLUDED.trips, open_until=EXCLUDED.open_until, last_error=EXCLUDED.…` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |

**처분** · located production table-symbol binding 3개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-categories"></a>
## `task_categories`

[task_categories 물리 객체](task-exploration.md#table-task-categories) · [field 의미](semantic-catalog.md#semantic-task-categories)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/task_archives.go::DB.QueueTaskArchive` · [근거](evidence:db-pg-access-task-categories-1268f5e175) | `read` / `JOIN` | L230 `JOIN` `…, t.status, t.category_id, COALESCE(c.name,''), t.paused, t.queued, t.deadline_at FROM tasks t LEFT JOIN task_categories c ON c.id=t.category_id WHERE t.id=$1 AND t.deleted_at IS NULL FOR UPDATE OF t` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::rowExists` · [근거](evidence:db-pg-access-task-categories-7a889cb87a) | `read` / `FROM` | L360 `FROM` `SELECT EXISTS(SELECT 1 FROM <allowlisted table> WHERE id=$1)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_categories.go::DB.CreateTaskCategory` · [근거](evidence:db-pg-access-task-categories-5f5c62108f) | `write` / `INSERT` | L68 `INSERT` `WITH inserted AS ( INSERT INTO task_categories(name, nkey) VALUES ($1,$2) ON CONFLICT (nkey) DO NOTHING RETURNING * ) SELECT inserted.id, inserted.name, inserted.nkey, 0, inserted.created_at, inserted.updated_at FROM inserted` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.DeleteTaskCategory` · [근거](evidence:db-pg-access-task-categories-5039981c71) | `write` / `DELETE` | L152 `DELETE` `DELETE FROM task_categories WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.GetTaskCategory` · [근거](evidence:db-pg-access-task-categories-e4397f0b2b) | `read` / `FROM` | L109 `FROM` `…ey, count(task.id) FILTER (WHERE task.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id`<br>L110 `FROM` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.ListTaskCategories` · [근거](evidence:db-pg-access-task-categories-13b86938bc) | `read` / `FROM` | L87 `FROM` `…ey, count(task.id) FILTER (WHERE task.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id GROUP BY category.id ORDER BY category.name, category.id`<br>L88 `FROM` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id GROUP BY category.id ORDER BY category.name, category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.RenameTaskCategory` · [근거](evidence:db-pg-access-task-categories-9b40170af7) | `write` / `UPDATE` | L129 `UPDATE` `WITH updated AS ( UPDATE task_categories SET name=$2, nkey=$3 WHERE id=$1 RETURNING * ) SELECT updated.id, updated.name, updated.nkey, (SELECT count(*) FROM tasks WHERE category_id=updated.id AND deleted_at IS NULL), updated.created_at, updated.updated_at FROM…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.SetTaskCategory` · [근거](evidence:db-pg-access-task-categories-2b61f93d04) | `read` / `FROM` | L179 `FROM` `WITH selected AS ( SELECT * FROM task_categories WHERE id=$2 ), updated AS ( UPDATE tasks SET category_id=$2 WHERE id=$1 AND deleted_at IS NULL AND EXISTS (SELECT 1 FROM selected) RETURNING id ) SELECT selected.id, selected.name, selected.nkey, (SELECT count(*) FROM t…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.SetTasksCategory` · [근거](evidence:db-pg-access-task-categories-20d6932241) | `read` / `FROM` | L237 `FROM` `SELECT EXISTS(SELECT 1 FROM task_categories WHERE id=$1)`<br>L267 `FROM` `…ey, count(task.id) FILTER (WHERE task.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id`<br>L268 `FROM` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.CreateTaskWithOptions` · [근거](evidence:db-pg-access-task-categories-efec7c8eca) | `read` / `FROM` | L206 `FROM` `SELECT name FROM task_categories WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.GetTask` · [근거](evidence:db-pg-access-task-categories-a8eac8736c) | `read` / `FROM` | L420 `FROM` `SELECT id, COALESCE(name,''), category_id, COALESCE((SELECT category.name FROM task_categories category WHERE category.id=tasks.category_id),''), description, goal, exploration_id, status, paused, queued, queued_at, COALESCE(queue_mode,''), llm_profile_id, active_llm_profile_id, COALESCE(parent_ref,''), pinned_at…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.ListTasks` · [근거](evidence:db-pg-access-task-categories-861bb451e0) | `read` / `FROM` | L367 `FROM` `SELECT id, COALESCE(name,''), category_id, COALESCE((SELECT category.name FROM task_categories category WHERE category.id=tasks.category_id),''), description, goal, exploration_id, status, paused, queued, queued_at, COALESCE(queue_mode,''), llm_profile_id, active_llm_profile_id, COALESCE(parent_ref,''), pinned_at…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.UpdateTask` · [근거](evidence:db-pg-access-task-categories-863a216fc0) | `read` / `FROM` | L400 `FROM` `…AND deleted_at IS NULL RETURNING id, COALESCE(name,''), category_id, COALESCE((SELECT category.name FROM task_categories category WHERE category.id=tasks.category_id),''), description, goal, exploration_id, status, paused, queued, queued_at, COALESCE(queue_mode,''), llm_profile_id, active_llm_profile_id, COALESCE(parent_ref,''), pinned_at…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |

**처분** · located production table-symbol binding 13개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-tasks"></a>
## `tasks`

[tasks 물리 객체](task-exploration.md#table-tasks) · [field 의미](semantic-catalog.md#semantic-tasks)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/asset_dsl.go::AssetStore.GetByIDsInScope` · [근거](evidence:db-pg-access-tasks-082ddb7a18) | `read` / `FROM` | L624 `FROM` `scopeTargetCTE context_tasks reads current/source live tasks` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/asset_dsl.go::AssetStore.QueryDSLInScope` · [근거](evidence:db-pg-access-tasks-ad016247fc) | `read` / `FROM` | L588 `FROM` `source fragment: scopeTargetCTE context_tasks reads current/source live tasks <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/assets.go::hostsForTaskDeletion` · [근거](evidence:db-pg-access-tasks-d66aa3ecdf) | `read` / `FROM,JOIN` | L1286 `FROM` `…n.exploration_id=$2 ), other_assets AS ( SELECT DISTINCT a.id FROM assets a WHERE EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) OR EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WHERE e…`<br>L1286 `JOIN` `…ids) ) OR EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WHERE ea.asset_id=a.id AND t.id<>$1 AND t.deleted_at IS NULL ) ) SELECT COALESCE(a.domain,''), COALESCE(a.ip,''), COALESCE(a.url,''), true FROM assets a JOIN current_assets c ON c.…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/config.go::DB.deleteProfile` · [근거](evidence:db-pg-access-tasks-f552395a40) | `read,write` / `FROM,JOIN,UPDATE` | L232 `FROM` `SELECT t.id FROM tasks t WHERE t.llm_profile_id=$1 OR t.active_llm_profile_id=$1 OR EXISTS ( SELECT 1 FROM task_llm_profiles x WHERE x.task_id=t.id AND x.profile_id=$1 ) ORDER BY t.id FOR UPDATE OF t`<br>L281 `FROM` `SELECT ref_kind, ref_id FROM ( SELECT 'task'::text AS ref_kind, t.id AS ref_id FROM tasks t WHERE t.llm_profile_id=$1 OR t.active_llm_profile_id=$1 OR EXISTS ( SELECT 1 FROM task_llm_profiles x WHERE x.task_id=t.id AND x.profile_id=$1 ) UNION ALL SELECT 'agent', a.id FROM agents a WHERE a.llm_profile_id=$1 U…`<br>L330 `JOIN` `SELECT x.task_id, x.position, COALESCE(t.active_llm_profile_id=$1, false) FROM task_llm_profiles x JOIN tasks t ON t.id=x.task_id WHERE x.profile_id=$1 ORDER BY x.task_id`<br>L362 `UPDATE` `UPDATE tasks SET llm_chain_revision=llm_chain_revision+1 WHERE id=$1`<br>L379 `UPDATE` `UPDATE tasks SET active_llm_profile_id=NULL, llm_profile_id=NULL, llm_chain_revision=llm_chain_revision+1 WHERE id=$1`<br>L386 `UPDATE` `UPDATE tasks SET active_llm_profile_id=$2, llm_profile_id=$2, llm_chain_revision=llm_chain_revision+1 WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/exploration.go::DB.ExplorationDiag` · [근거](evidence:db-pg-access-tasks-b78a0ff81d) | `read` / `FROM` | L1229 `FROM` `SELECT EXISTS(SELECT 1 FROM explorations WHERE id=$1), (SELECT COUNT(*) FROM tasks WHERE exploration_id=$1), COALESCE((SELECT MAX(id) FROM explorations),0)` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration.go::DB.TaskListMetricsAll` · [근거](evidence:db-pg-access-tasks-1ebf46408f) | `read` / `FROM` | L1313 `FROM` `…ALESCE(finding_metrics.high,0), COALESCE(finding_metrics.medium,0), COALESCE(finding_metrics.low,0) FROM tasks task LEFT JOIN LATERAL ( SELECT SUM(input_tokens) AS input_tokens, SUM(output_tokens) AS output_tokens, SUM(cache_read_tokens) AS cache_read_tokens, SUM(cache_write_tokens) AS cache_write_tokens FROM activity WHERE expl…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration_sources.go::ExplorationStore.DirectSourceStores` · [근거](evidence:db-pg-access-tasks-a783b00be6) | `read` / `FROM,JOIN` | L21 `FROM` `SELECT source.id, source.exploration_id, source.description, source.goal, source.status FROM tasks owner JOIN task_relations relation ON relation.task_id=owner.id JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE owner.exploration_id=$1 AND owner.deleted_at IS NULL ORDER BY re…`<br>L21 `JOIN` `…urce.goal, source.status FROM tasks owner JOIN task_relations relation ON relation.task_id=owner.id JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE owner.exploration_id=$1 AND owner.deleted_at IS NULL ORDER BY relation.created_at, source.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration_sources.go::ExplorationStore.TaskID` · [근거](evidence:db-pg-access-tasks-8ffa4ed35f) | `read` / `FROM` | L47 `FROM` `SELECT id FROM tasks WHERE exploration_id=$1 AND deleted_at IS NULL` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/finding_assets.go::DB.buildFindingAssetTree` · [근거](evidence:db-pg-access-tasks-51d90c8c39) | `read` / `JOIN` | L143 `JOIN` `SELECT COALESCE(f.severity,''), f.created_at, COALESCE(f.asset_ids::text,'[]') FROM findings f LEFT JOIN tasks t ON f.task_id = t.id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-tasks-285686da7d) | `read` / `JOIN` | L85 `JOIN` `…id])), '[]'::jsonb), 'constraints', COALESCE((SELECT jsonb_agg(to_jsonb(c)) FROM task_constraints c JOIN tasks t ON t.exploration_id=c.exploration_id WHERE t.id=f.task_id), '[]'::jsonb)) FROM findings f WHERE f.id=$1 FOR UPDATE OF f` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_traffic.go::LockTaskEvidenceTx` · [근거](evidence:db-pg-access-tasks-66fca018a0) | `read` / `FROM` | L146 `FROM` `SELECT deleted_at FROM tasks WHERE id=$1 FOR UPDATE` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::RecordFindingTx` · [근거](evidence:db-pg-access-tasks-238786c0cf) | `read` / `FROM` | L348 `FROM` `SELECT exploration_id FROM tasks WHERE id=$1` | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::DB.FindingStats` · [근거](evidence:db-pg-access-tasks-c4bd1d9850) | `read` / `JOIN` | L580 `JOIN` `SELECT f.task_id, COALESCE(t.name, ''), COALESCE(t.description, ''), COUNT(*) FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.task_id IS NOT NULL GROUP BY f.task_id, t.name, t.description ORDER BY MAX(f.created_at) DESC` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.GetFinding` · [근거](evidence:db-pg-access-tasks-a87ac240c2) | `read` / `JOIN` | L636 `JOIN` `…OM finding_traffic_bindings b WHERE b.finding_id=f.id), COALESCE(f.report, '') FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.id = $1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingGroups` · [근거](evidence:db-pg-access-tasks-8caabeef48) | `read` / `JOIN` | L311 `JOIN` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id=t.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindings` · [근거](evidence:db-pg-access-tasks-acb75322e7) | `read` / `JOIN` | L136 `JOIN` `…ion, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id) FROM findings f LEFT JOIN tasks t ON f.task_id = t.id ORDER BY f.created_at DESC LIMIT $1`<br>L137 `JOIN` `FROM findings f LEFT JOIN tasks t ON f.task_id = t.id ORDER BY f.created_at DESC LIMIT $1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingsForExport` · [근거](evidence:db-pg-access-tasks-cb09df0b12) | `read` / `JOIN` | L484 `JOIN` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.id IN ( <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L495 `JOIN` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id = t.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingsPage` · [근거](evidence:db-pg-access-tasks-2e37a25486) | `read` / `JOIN` | L250 `JOIN` `source fragment: SELECT COUNT(*) FROM findings f LEFT JOIN tasks t ON f.task_id=t.id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L265 `JOIN` `source fragment: SELECT %s FROM findings f LEFT JOIN tasks t ON f.task_id = t.id%s ORDER BY %s LIMIT $%d OFFSET $%d <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-tasks-94e899c2d9) | `read` / `JOIN` | L382 `JOIN` `SELECT n.id FROM findings f JOIN tasks t ON t.id=f.task_id JOIN exploration_nodes n ON n.id=f.node_id AND n.exploration_id=t.exploration_id WHERE f.id=$1 AND f.node_id=$2 AND t.exploration_id=$3 AND n.kind='finding' FOR SHARE OF f, t, n` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/intercept_execution.go::DB.GetInterceptExecution` · [근거](evidence:db-pg-access-tasks-823cf1ab14) | `read` / `FROM` | L44 `FROM` `SELECT EXISTS(SELECT 1 FROM tasks WHERE id=$1 AND archived_at IS NULL AND deleted_at IS NULL)`<br>L51 `FROM` `…OALESCE(summary,''), created_at, main_seg FROM activity WHERE exploration_id=(SELECT exploration_id FROM tasks WHERE id=$1 AND archived_at IS NULL AND deleted_at IS NULL)`<br>L56 `FROM` `…OALESCE(summary,''), created_at, main_seg FROM activity WHERE exploration_id=(SELECT exploration_id FROM tasks WHERE id=$1 AND archived_at IS NULL AND deleted_at IS NULL) AND tool_use_id=$2 AND kind IN ('tool_use','tool_result') ORDER BY id LIMIT 3` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/side_questions.go::lockSideParent` · [근거](evidence:db-pg-access-tasks-d1c6ac536d) | `read` / `FROM` | L25 `FROM` `SELECT id FROM tasks WHERE id=$1 AND exploration_id=$2 AND deleted_at IS NULL AND archived_at IS NULL FOR SHARE` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/task_archives.go::DB.IsTaskArchiveRestored` · [근거](evidence:db-pg-access-tasks-a258fa1c09) | `read` / `JOIN` | L418 `JOIN` `SELECT task.deleted_at IS NULL AND task.archived_at IS NULL FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.QueueTaskArchive` · [근거](evidence:db-pg-access-tasks-86e858b2d2) | `read` / `FROM,JOIN` | L230 `FROM` `…escription, t.goal, t.status, t.category_id, COALESCE(c.name,''), t.paused, t.queued, t.deadline_at FROM tasks t LEFT JOIN task_categories c ON c.id=t.category_id WHERE t.id=$1 AND t.deleted_at IS NULL FOR UPDATE OF t`<br>L249 `JOIN` `SELECT child.id FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE relation.source_task_id=$1 AND (pending.id IS NULL OR pending.state NOT IN ('archive_queu…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.TaskArchiveBlockers` · [근거](evidence:db-pg-access-tasks-bce6f349e4) | `read` / `JOIN` | L86 `JOIN` `SELECT relation.source_task_id, MIN(child.id) FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE pending.id IS NULL OR pending.state NOT IN ('archive_queued','archiving') GROUP BY relati…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-tasks-bf13420619) | `read` / `FROM` | L566 `FROM` `source fragment: SELECT exploration_id FROM tasks WHERE id=$1 AND deleted_at IS NULL <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L578 `FROM` `source fragment: SELECT * FROM tasks WHERE id=$1 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetMetadata` · [근거](evidence:db-pg-access-tasks-8780d3ae20) | `read` / `FROM,JOIN` | L682 `FROM` `source fragment: WITH candidate AS (<archiveAssetIDsQuery helper composition>) SELECT asset.id FROM assets asset JOIN candidate ON candidate.id=asset.id WHERE <cross-task ownership and live-anchor exclusions> ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L682 `JOIN` `source fragment: WITH candidate AS (<archiveAssetIDsQuery helper composition>) SELECT asset.id FROM assets asset JOIN candidate ON candidate.id=asset.id WHERE <cross-task ownership and live-anchor exclusions> ORDER BY asset.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.ArchivedAggregateStats` · [근거](evidence:db-pg-access-tasks-a24f5ae001) | `read` / `JOIN` | L776 `JOIN` `SELECT archive.aggregate_stats FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE task.archived_at IS NOT NULL` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-tasks-a535f79192) | `read,write` / `FROM,JOIN,UPDATE` | L45 `JOIN` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task`<br>L54 `JOIN` `SELECT child.id FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL WHERE relation.source_task_id=$1 LIMIT 1`<br>L107 `FROM` `…assets asset WHERE asset.id=ANY($2::bigint[]) AND asset.company_id IS NULL AND NOT EXISTS (SELECT 1 FROM tasks task WHERE task.id<>$1 AND task.deleted_at IS NULL AND task.id=ANY(asset.task_ids)) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id JOIN tasks task ON task…`<br>L107 `JOIN` `…TS ( SELECT 1 FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id JOIN tasks task ON task.exploration_id=node.exploration_id WHERE anchor.asset_id=asset.id AND task.id<>$1 AND task.deleted_at IS NULL )`<br>L121 `UPDATE` `UPDATE tasks SET name='',category_id=NULL,description='',goal='',paused=true,queued=false,queued_at=NULL,queue_mode='', llm_profile_id=NULL,active_llm_profile_id=NULL,llm_chain_revision=llm_chain_revision+1, company_id=NULL,parent_r…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.DeleteTaskArchiveStub` · [근거](evidence:db-pg-access-tasks-daf6800154) | `read,write` / `DELETE,JOIN` | L748 `JOIN` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task`<br>L764 `DELETE` `DELETE FROM tasks WHERE id=$1 AND archived_at IS NOT NULL` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.restoreTaskArchive` · [근거](evidence:db-pg-access-tasks-27c6ab021c) | `read` / `JOIN` | L189 `JOIN` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::liveTaskExists` · [근거](evidence:db-pg-access-tasks-7548bd98bc) | `read` / `FROM` | L709 `FROM` `SELECT EXISTS(SELECT 1 FROM tasks WHERE id=$1 AND deleted_at IS NULL)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreTaskStub` · [근거](evidence:db-pg-access-tasks-9968d6ad75) | `write` / `UPDATE` | L318 `UPDATE` `UPDATE tasks current SET name=archived.name,category_id=archived.category_id,description=archived.description,goal=archived.goal, status=archived.status,paused=archived.paused,queued=false,queued_at=NULL,queue_mode='', llm_profile_i…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::rowExists` · [근거](evidence:db-pg-access-tasks-25085d9fcb) | `read` / `FROM` | L360 `FROM` `SELECT EXISTS(SELECT 1 FROM <allowlisted table> WHERE id=$1)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.AttachAssetsToTask` · [근거](evidence:db-pg-access-tasks-16de64d10e) | `read` / `FROM` | L276 `FROM` `SELECT EXISTS(SELECT 1 FROM tasks WHERE id=$1 AND deleted_at IS NULL)` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-tasks-be683256d2) | `read` / `FROM,JOIN` | L375 `FROM` `WITH context AS ( SELECT task.id AS task_id, task.exploration_id, false AS inherited FROM tasks task WHERE task.id=$1 AND task.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id, true FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL…`<br>L375 `JOIN` `…ted_at IS NULL UNION ALL SELECT source.id, source.exploration_id, true FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT intent.id, asset.id, asset.type, CASE asset.type WHEN 'root_domain' THEN COALESCE(asset.domain,'') WHEN 'subdo…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets.go::AssetStore.RegisterTaskAssetScopes` · [근거](evidence:db-pg-access-tasks-2ca07e02ce) | `read` / `FROM` | L165 `FROM` `SELECT EXISTS(SELECT 1 FROM tasks WHERE id=$1 AND deleted_at IS NULL)` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets.go::AssetStore.SetTaskAssetSource` · [근거](evidence:db-pg-access-tasks-6e199db471) | `read` / `FROM` | L101 `FROM` `…nks(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_sum…`<br>L113 `FROM` `…nks(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_sum…`<br>L115 `FROM` `…nks(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NULL ON CONFLICT (task_id, asset_id) DO UPDATE SET source=EXCLUDED.source, source_summary=EXCLUDED.source_sum…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-tasks-ee3e318216) | `read` / `FROM,JOIN` | L202 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L202 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), context_assets AS ( SELECT DISTINCT a.id FROM assets a WHERE EXISTS (SELECT 1 FROM context_tasks ctx WHERE ctx.task_…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.ListTaskScopeWithSources` · [근거](evidence:db-pg-access-tasks-fd61c8099e) | `read` / `FROM,JOIN` | L94 `FROM` `source fragment: WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation… <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L94 `JOIN` `source fragment: …t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT ts.id, ts.task_id, ts.kind, COALESCE(ts.company_id,0), COALESCE(c.name,''), COALESCE(ts.domain,''), COALESCE(t… <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-tasks-389b085ad4) | `read` / `FROM,JOIN` | L170 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L170 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FR…`<br>L177 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L177 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FR…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-tasks-d5cc808761) | `read` / `FROM,JOIN` | L125 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L125 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT count(*) FROM task_scope ts JOIN context_tasks ctx ON ctx.task_id=ts.task_id`<br>L127 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L127 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FR…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.GetTaskCategory` · [근거](evidence:db-pg-access-tasks-8c021898d6) | `read` / `JOIN` | L109 `JOIN` `…sk.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id`<br>L110 `JOIN` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.ListTaskCategories` · [근거](evidence:db-pg-access-tasks-67c49edeec) | `read` / `JOIN` | L87 `JOIN` `…sk.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id GROUP BY category.id ORDER BY category.name, category.id`<br>L88 `JOIN` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id GROUP BY category.id ORDER BY category.name, category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.RenameTaskCategory` · [근거](evidence:db-pg-access-tasks-3adf94a2ce) | `read` / `FROM` | L129 `FROM` `…, nkey=$3 WHERE id=$1 RETURNING * ) SELECT updated.id, updated.name, updated.nkey, (SELECT count(*) FROM tasks WHERE category_id=updated.id AND deleted_at IS NULL), updated.created_at, updated.updated_at FROM updated` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.SetTaskCategory` · [근거](evidence:db-pg-access-tasks-fb40a4c990) | `read,write` / `FROM,UPDATE` | L163 `UPDATE` `UPDATE tasks SET category_id=NULL WHERE id=$1 AND deleted_at IS NULL`<br>L179 `FROM` `… 1 FROM selected) RETURNING id ) SELECT selected.id, selected.name, selected.nkey, (SELECT count(*) FROM tasks WHERE category_id=selected.id AND deleted_at IS NULL), selected.created_at, selected.updated_at FROM selected, updated`<br>L179 `UPDATE` `WITH selected AS ( SELECT * FROM task_categories WHERE id=$2 ), updated AS ( UPDATE tasks SET category_id=$2 WHERE id=$1 AND deleted_at IS NULL AND EXISTS (SELECT 1 FROM selected) RETURNING id ) SELECT selected.id, selected.name, selected.nkey, (SELECT count(*) FROM tasks WHERE category_id=selected.id AND de…`<br>L193 `FROM` `SELECT EXISTS(SELECT 1 FROM tasks WHERE id=$1 AND deleted_at IS NULL)` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_categories.go::DB.SetTasksCategory` · [근거](evidence:db-pg-access-tasks-239b123626) | `read,write` / `JOIN,UPDATE` | L244 `UPDATE` `UPDATE tasks SET category_id=$2 WHERE id=ANY($1::bigint[]) AND deleted_at IS NULL RETURNING id`<br>L267 `JOIN` `…sk.deleted_at IS NULL), category.created_at, category.updated_at FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id`<br>L268 `JOIN` `FROM task_categories category LEFT JOIN tasks task ON task.category_id=category.id WHERE category.id=$1 GROUP BY category.id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.ReplaceTaskLLMProfiles` · [근거](evidence:db-pg-access-tasks-530db8c688) | `read,write` / `FROM,UPDATE` | L417 `FROM` `SELECT id FROM tasks WHERE id=$1 AND deleted_at IS NULL FOR UPDATE`<br>L447 `UPDATE` `UPDATE tasks SET active_llm_profile_id=$2, llm_profile_id=$2, llm_chain_revision=llm_chain_revision+1 WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.TaskSources` · [근거](evidence:db-pg-access-tasks-4520f8c9cf) | `read` / `JOIN` | L363 `JOIN` `SELECT t.id, t.exploration_id, t.description, t.goal, t.status FROM task_relations r JOIN tasks t ON t.id=r.source_task_id AND t.deleted_at IS NULL WHERE r.task_id=$1 ORDER BY r.created_at, r.source_task_id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.hydrateTasksContext` · [근거](evidence:db-pg-access-tasks-169672238e) | `read` / `FROM` | L138 `FROM` `…t.llm_chain_revision, p.profile_id, p.position, p.status, COALESCE(p.last_error,''), p.exhausted_at FROM tasks t LEFT JOIN task_llm_profiles p ON p.task_id=t.id WHERE t.id=ANY($1::bigint[]) ORDER BY t.id, p.position NULLS LAST` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.markTaskLLMProfileQuotaExhausted` · [근거](evidence:db-pg-access-tasks-6fd7255485) | `read,write` / `FROM,UPDATE` | L479 `FROM` `SELECT active_llm_profile_id, llm_chain_revision FROM tasks WHERE id=$1 FOR UPDATE`<br>L528 `UPDATE` `UPDATE tasks SET active_llm_profile_id=$2, llm_profile_id=$2, llm_chain_revision=llm_chain_revision+1 WHERE id=$1`<br>L536 `UPDATE` `UPDATE tasks SET active_llm_profile_id=NULL, llm_profile_id=NULL, llm_chain_revision=llm_chain_revision+1 WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.taskLLMContext` · [근거](evidence:db-pg-access-tasks-62adc688f8) | `read` / `FROM` | L261 `FROM` `…t.llm_chain_revision, p.profile_id, p.position, p.status, COALESCE(p.last_error,''), p.exhausted_at FROM tasks t LEFT JOIN task_llm_profiles p ON p.task_id=t.id WHERE t.id=$1 ORDER BY p.position NULLS LAST` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-tasks-8da3043006) | `read` / `FROM,JOIN` | L428 `FROM` `WITH context_tasks AS ( SELECT t.id AS task_id, t.exploration_id FROM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation…`<br>L428 `JOIN` `…t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FR…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_scope.go::AssetStore.CoverageEnabled` · [근거](evidence:db-pg-access-tasks-43ca5ea2c9) | `read` / `FROM` | L296 `FROM` `SELECT COALESCE(coverage_enabled,true) FROM tasks WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.CreateTaskWithOptions` · [근거](evidence:db-pg-access-tasks-9857397f13) | `write` / `INSERT` | L228 `INSERT` `INSERT INTO tasks(name, category_id, description, goal, exploration_id, llm_profile_id, active_llm_profile_id, timeout_seconds, plan_heartbeat_seconds, coverage_enabled) VALUES ($1,$2,$3,$4,$5,$6,$6,$7,$8,$9) RETURNING id, status, paused…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-tasks-57cae4cf7e) | `read,write` / `DELETE,FROM,JOIN` | L562 `FROM` `SELECT exploration_id FROM tasks WHERE id=$1 FOR UPDATE`<br>L595 `FROM` `…ble AS ( SELECT a.id FROM assets a JOIN candidate_assets c ON c.id=a.id WHERE NOT EXISTS ( SELECT 1 FROM tasks t WHERE t.id<>$1 AND t.deleted_at IS NULL AND t.id=ANY(a.task_ids) ) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WH…`<br>L595 `JOIN` `…) AND NOT EXISTS ( SELECT 1 FROM exploration_anchors ea JOIN exploration_nodes n ON n.id=ea.node_id JOIN tasks t ON t.exploration_id=n.exploration_id WHERE ea.asset_id=a.id AND t.id<>$1 AND t.deleted_at IS NULL ) ) DELETE FROM assets a USING deletable d WHERE a.id=d.id`<br>L647 `DELETE` `DELETE FROM tasks WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.Dequeue` · [근거](evidence:db-pg-access-tasks-63ac846350) | `write` / `UPDATE` | L459 `UPDATE` `UPDATE tasks SET queued=false, queued_at=NULL, queue_mode=CASE WHEN $2 THEN '' ELSE queue_mode END WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.Enqueue` · [근거](evidence:db-pg-access-tasks-644bdbe575) | `write` / `UPDATE` | L445 `UPDATE` `UPDATE tasks SET queued=true, queued_at=CASE WHEN queued THEN COALESCE(queued_at, now()) ELSE now() END, queue_mode=CASE WHEN queue_mode='bootstrap' OR $2='bootstrap' THEN 'bootstrap' ELSE 'resume' END WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.GetTask` · [근거](evidence:db-pg-access-tasks-4a928fa293) | `read` / `FROM` | L420 `FROM` `…), COALESCE(plan_heartbeat_seconds,300), COALESCE(coverage_enabled,true), first_run_at, deadline_at FROM tasks WHERE id=$1 AND deleted_at IS NULL` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.ListTasks` · [근거](evidence:db-pg-access-tasks-65d521c111) | `read` / `FROM` | L367 `FROM` `…), COALESCE(plan_heartbeat_seconds,300), COALESCE(coverage_enabled,true), first_run_at, deadline_at FROM tasks WHERE deleted_at IS NULL ORDER BY (pinned_at IS NOT NULL) DESC, pinned_at DESC NULLS LAST, id DESC` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.SetParentRef` · [근거](evidence:db-pg-access-tasks-9432c2263f) | `write` / `UPDATE` | L360 `UPDATE` `UPDATE tasks SET parent_ref=NULLIF($2,'') WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.SetPaused` · [근거](evidence:db-pg-access-tasks-f4077b39a2) | `write` / `UPDATE` | L435 `UPDATE` `UPDATE tasks SET paused=$1 WHERE id=$2` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.SetStatus` · [근거](evidence:db-pg-access-tasks-49a557bbce) | `write` / `UPDATE` | L481 `UPDATE` `UPDATE tasks SET status = $1, completed_at = CASE WHEN $1 IN ('done','failed','timeout') THEN COALESCE(completed_at, now()) ELSE NULL END WHERE id = $2` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.SetTerminalStatusGuarded` · [근거](evidence:db-pg-access-tasks-7c3c56d040) | `write` / `UPDATE` | L494 `UPDATE` `UPDATE tasks SET status = $1, completed_at = COALESCE(completed_at, now()) WHERE id = $2 AND status NOT IN ('done','failed','timeout')` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.StampFirstRun` · [근거](evidence:db-pg-access-tasks-e121890883) | `write` / `UPDATE` | L512 `UPDATE` `UPDATE tasks SET first_run_at = COALESCE(first_run_at, now()), deadline_at = CASE WHEN first_run_at IS NOT NULL THEN deadline_at -- 已盖过章：不动 WHEN $2 > 0 THEN now() + make_interval(secs => $2) ELSE NULL END WHERE id = $1…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::DB.UpdateTask` · [근거](evidence:db-pg-access-tasks-15a2889c12) | `write` / `UPDATE` | L400 `UPDATE` `UPDATE tasks SET name = CASE WHEN $2::boolean THEN $3 ELSE name END, pinned_at = CASE WHEN $4::boolean IS NULL THEN pinned_at WHEN $4::boolean THEN COALESCE(pinned_at, now()) ELSE NULL END WHERE id=$1 AND deleted_at IS NULL RETURNIN…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::insertTaskRelations` · [근거](evidence:db-pg-access-tasks-a1dc99d2be) | `read` / `FROM` | L319 `FROM` `INSERT INTO task_relations(task_id, source_task_id) SELECT $1, id FROM tasks WHERE id=$2 AND deleted_at IS NULL` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/triggers.go::DB.MetGoals` · [근거](evidence:db-pg-access-tasks-fcd04a1917) | `read` / `JOIN` | L273 `JOIN` `SELECT n.id, t.id, t.description, t.goal, n.payload FROM exploration_nodes n JOIN tasks t ON t.exploration_id = n.exploration_id WHERE n.kind='goal' AND n.state='met' AND t.deleted_at IS NULL ORDER BY n.id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.NewFindingsSince` · [근거](evidence:db-pg-access-tasks-b62fdd7c0a) | `read` / `JOIN` | L168 `JOIN` `SELECT n.id, t.id, t.description, t.goal, n.payload FROM exploration_nodes n JOIN tasks t ON t.exploration_id = n.exploration_id WHERE n.kind='finding' AND n.id > $1 AND t.deleted_at IS NULL ORDER BY n.id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.NewTasksSince` · [근거](evidence:db-pg-access-tasks-c789c9fa36) | `read` / `FROM` | L220 `FROM` `SELECT id, description, goal FROM tasks WHERE deleted_at IS NULL AND id > $1 ORDER BY id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.NewToolCallsSince` · [근거](evidence:db-pg-access-tasks-617cfacb9c) | `read` / `JOIN` | L248 `JOIN` `…scription, t.goal, r.tool, COALESCE(u.detail,''), COALESCE(r.detail,''), r.is_error FROM activity r JOIN tasks t ON t.exploration_id = r.exploration_id LEFT JOIN activity u ON u.exploration_id = r.exploration_id AND u.tool_use_id = r.tool_use_id AND u.kind='tool_use' WHERE r.kind='tool_result' AND r.id > $1 AND r.tool <> '' AND …` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.TimedOutTasksSince` · [근거](evidence:db-pg-access-tasks-9f83ca08f3) | `read` / `FROM` | L195 `FROM` `SELECT id, description, goal FROM tasks WHERE status='timeout' AND deleted_at IS NULL AND id > $1 ORDER BY id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `server/manager.go::Manager.ApplyTaskAdmission` · [근거](evidence:db-pg-access-tasks-102eda9f17) | `write` / `UPDATE` | L1166 `UPDATE` `UPDATE tasks SET status=$2, completed_at=CASE WHEN $2 IN ('done','failed','timeout') THEN COALESCE(completed_at, now()) ELSE NULL END, paused=false, queued=$3, queued_at=CASE WHEN NOT $3 THEN NULL WHEN $5 AND queued THEN COALESCE(qu…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `server/manager.go::Manager.ApplyTaskPause` · [근거](evidence:db-pg-access-tasks-53c393734c) | `write` / `UPDATE` | L1243 `UPDATE` `UPDATE tasks SET paused=true, queued=false, queued_at=NULL WHERE id=$1 AND deleted_at IS NULL AND paused=false AND status NOT IN ('done','failed','timeout') RETURNING COALESCE(queue_mode,'')` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `server/manager.go::Manager.EnqueueTask` · [근거](evidence:db-pg-access-tasks-aa5f830b72) | `write` / `UPDATE` | L1280 `UPDATE` `UPDATE tasks SET queued=true, queued_at=CASE WHEN queued THEN COALESCE(queued_at, now()) ELSE now() END, queue_mode=CASE WHEN queue_mode='bootstrap' OR $2='bootstrap' THEN 'bootstrap' ELSE 'resume' END WHERE id=$1 AND deleted_at IS …` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |

**처분** · located production table-symbol binding 74개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-archives"></a>
## `task_archives`

[task_archives 물리 객체](findings-operations.md#table-task-archives) · [field 의미](semantic-catalog.md#semantic-task-archives)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/finding_traffic.go::LockTaskEvidenceTx` · [근거](evidence:db-pg-access-task-archives-46a518e5eb) | `read` / `FROM` | L153 `FROM` `SELECT state FROM task_archives WHERE task_id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/task_archives.go::DB.AppendTaskArchiveWarning` · [근거](evidence:db-pg-access-task-archives-1d4aedee48) | `write` / `UPDATE` | L412 `UPDATE` `UPDATE task_archives SET warnings=warnings \|\| jsonb_build_array($2::text) WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.ClaimTaskArchiveJob` · [근거](evidence:db-pg-access-task-archives-bcd920f8ce) | `read,write` / `FROM,UPDATE` | L379 `FROM` `SELECT id,state FROM task_archives WHERE state IN ('archive_queued','restore_queued','delete_queued') ORDER BY requested_at,id FOR UPDATE SKIP LOCKED LIMIT 1`<br>L389 `UPDATE` `UPDATE task_archives SET state=$2,phase='starting',progress=1,error='' WHERE id=$1 RETURNING id, task_id, state, phase, progress, COALESCE(error,''), warnings, format_version, COALESCE(archive_path,''), COALESCE(sha256,''), original_size, c…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.FailTaskArchiveJob` · [근거](evidence:db-pg-access-task-archives-a72bb87396) | `write` / `UPDATE` | L435 `UPDATE` `UPDATE task_archives SET state=$2,phase='failed',error=$3 WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.GetTaskArchive` · [근거](evidence:db-pg-access-task-archives-bb4a4fa0cb) | `read` / `FROM` | L171 `FROM` `…ng_timeout_seconds, data_counts, aggregate_stats, archived_at, requested_at, created_at, updated_at FROM task_archives WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.GetTaskArchiveByTask` · [근거](evidence:db-pg-access-task-archives-8db7402369) | `read` / `FROM` | L179 `FROM` `…ng_timeout_seconds, data_counts, aggregate_stats, archived_at, requested_at, created_at, updated_at FROM task_archives WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.IsTaskArchiveRestored` · [근거](evidence:db-pg-access-task-archives-b349280073) | `read` / `FROM` | L418 `FROM` `SELECT task.deleted_at IS NULL AND task.archived_at IS NULL FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.ListTaskArchives` · [근거](evidence:db-pg-access-task-archives-3e2f0aaac8) | `read` / `FROM` | L199 `FROM` `SELECT count(*) FROM task_archives WHERE ($1='' OR task_id::text ILIKE '%'\|\|$1\|\|'%' OR task_name ILIKE '%'\|\|$1\|\|'%' OR task_description ILIKE '%'\|\|$1\|\|'%') AND ($2='' OR state=$2)`<br>L202 `FROM` `…ng_timeout_seconds, data_counts, aggregate_stats, archived_at, requested_at, created_at, updated_at FROM task_archives WHERE ($1='' OR task_id::text ILIKE '%'\|\|$1\|\|'%' OR task_name ILIKE '%'\|\|$1\|\|'%' OR task_description ILIKE '%'\|\|$1\|\|'%') AND ($2='' OR state=$2) ORDER BY COALESCE(archived_at, requested_at) DESC, id DESC LIMIT $3 OFFSET…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.QueueTaskArchive` · [근거](evidence:db-pg-access-task-archives-bf408c8aa2) | `read,write` / `FROM,INSERT,JOIN` | L249 `JOIN` `…_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE relation.source_task_id=$1 AND (pending.id IS NULL OR pending.state NOT IN ('archive_queued','archiving')) LIMIT 1`<br>L287 `INSERT` `INSERT INTO task_archives( task_id,state,phase,progress,error,warnings,format_version,task_name, task_description,task_goal,original_status,category_id_snapshot, category_name_snapshot,source_task_ids,remaining_timeout_seconds,requested_at) VALU…`<br>L304 `FROM` `…ng_timeout_seconds, data_counts, aggregate_stats, archived_at, requested_at, created_at, updated_at FROM task_archives WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.QueueTaskArchiveDelete` · [근거](evidence:db-pg-access-task-archives-ac239c3cfb) | `read,write` / `FROM,UPDATE` | L331 `FROM` `SELECT task_id FROM task_archives WHERE id=$1 AND state IN ('ready','delete_failed') FOR UPDATE`<br>L338 `FROM` `SELECT task_id FROM task_archives WHERE id<>$1 AND $2=ANY(source_task_ids) AND state NOT IN ('delete_queued','deleting') LIMIT 1`<br>L346 `UPDATE` `UPDATE task_archives SET state=$2, phase='queued', progress=0, error='', requested_at=now() WHERE id=$1 RETURNING id, task_id, state, phase, progress, COALESCE(error,''), warnings, format_version, COALESCE(archive_path,''), COALESCE(sha256,…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.QueueTaskArchiveRestore` · [근거](evidence:db-pg-access-task-archives-0e94b8026f) | `write` / `UPDATE` | L315 `UPDATE` `UPDATE task_archives SET state=$2, phase='queued', progress=0, error='', requested_at=now() WHERE id=$1 AND state IN ('ready','restore_failed') RETURNING id, task_id, state, phase, progress, COALESCE(error,''), warnings, format_version, COA…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.RecoverTaskArchiveJobs` · [근거](evidence:db-pg-access-task-archives-fb5a0b1c08) | `write` / `UPDATE` | L359 `UPDATE` `UPDATE task_archives SET state=CASE state WHEN 'archiving' THEN 'archive_failed' WHEN 'restoring' THEN 'restore_queued' WHEN 'deleting' THEN 'delete_queued' ELSE state END, phase='interrupted', error=CASE WHEN state='archiving' THEN '上次…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.TaskArchiveBlockers` · [근거](evidence:db-pg-access-task-archives-aa7060d4f8) | `read` / `JOIN` | L86 `JOIN` `…_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE pending.id IS NULL OR pending.state NOT IN ('archive_queued','archiving') GROUP BY relation.source_task_id` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.UpdateTaskArchiveProgress` · [근거](evidence:db-pg-access-task-archives-3512ba58cb) | `write` / `UPDATE` | L404 `UPDATE` `UPDATE task_archives SET phase=$2,progress=$3 WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.ArchivedAggregateStats` · [근거](evidence:db-pg-access-task-archives-55a2c514f5) | `read` / `FROM` | L776 `FROM` `SELECT archive.aggregate_stats FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE task.archived_at IS NOT NULL` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-archives-4a9623c4f7) | `read,write` / `FROM,UPDATE` | L45 `FROM` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task`<br>L129 `UPDATE` `UPDATE task_archives SET state=$2,phase='ready',progress=100,error='',archive_path=$3,sha256=$4, original_size=$5,compressed_size=$6,data_counts=$7,aggregate_stats=$8, format_version=$9,archived_at=now(),warnings='[]' WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchiveRestore` · [근거](evidence:db-pg-access-task-archives-73da1ef42e) | `write` / `DELETE` | L723 `DELETE` `DELETE FROM task_archives archive USING tasks task WHERE archive.id=$1 AND archive.task_id=task.id AND task.deleted_at IS NULL AND task.archived_at IS NULL` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.DeleteTaskArchiveStub` · [근거](evidence:db-pg-access-task-archives-c1df948da6) | `read` / `FROM` | L748 `FROM` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task`<br>L757 `FROM` `SELECT task_id FROM task_archives WHERE id<>$1 AND $2=ANY(source_task_ids) LIMIT 1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.restoreTaskArchive` · [근거](evidence:db-pg-access-task-archives-790681674e) | `read,write` / `FROM,UPDATE` | L189 `FROM` `SELECT archive.task_id,task.exploration_id,archive.state FROM task_archives archive JOIN tasks task ON task.id=archive.task_id WHERE archive.id=$1 FOR UPDATE OF archive,task`<br>L298 `UPDATE` `UPDATE task_archives SET warnings=$2,phase='database_restored',progress=85,error='' WHERE id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 19개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-templates"></a>
## `task_templates`

[task_templates 물리 객체](task-exploration.md#table-task-templates) · [field 의미](semantic-catalog.md#semantic-task-templates)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/task_templates.go::DB.CreateTaskTemplate` · [근거](evidence:db-pg-access-task-templates-06536e50c1) | `write` / `INSERT` | L173 `INSERT` `INSERT INTO task_templates(name, nkey, description, goal, category_id, intercept_rules) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (nkey) DO NOTHING RETURNING id, name, nkey, description, goal, category_id, intercept_rules, created_at, updated_at` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_templates.go::DB.DeleteTaskTemplate` · [근거](evidence:db-pg-access-task-templates-7c04ed6ce4) | `write` / `DELETE` | L270 `DELETE` `DELETE FROM task_templates WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_templates.go::DB.GetTaskTemplate` · [근거](evidence:db-pg-access-task-templates-4d3f9d6b53) | `read` / `FROM` | L207 `FROM` `SELECT id, name, nkey, description, goal, category_id, intercept_rules, created_at, updated_at FROM task_templates WHERE id=$1` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_templates.go::DB.ListTaskTemplates` · [근거](evidence:db-pg-access-task-templates-544047bc2c) | `read` / `FROM` | L189 `FROM` `SELECT id, name, nkey, description, goal, category_id, intercept_rules, created_at, updated_at FROM task_templates ORDER BY updated_at DESC, id DESC` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_templates.go::DB.PatchTaskTemplate` · [근거](evidence:db-pg-access-task-templates-63621524a5) | `write` / `UPDATE` | L240 `UPDATE` `UPDATE task_templates SET name=CASE WHEN $2 THEN $3::text ELSE name END, nkey=CASE WHEN $2 THEN $4::text ELSE nkey END, description=CASE WHEN $5 THEN $6::text ELSE description END, goal=CASE WHEN $7 THEN $8::text ELSE goal END, category_id=C…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |

**처분** · located production table-symbol binding 5개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-relations"></a>
## `task_relations`

[task_relations 물리 객체](task-exploration.md#table-task-relations) · [field 의미](semantic-catalog.md#semantic-task-relations)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/asset_dsl.go::AssetStore.GetByIDsInScope` · [근거](evidence:db-pg-access-task-relations-fc0739399a) | `read` / `FROM` | L624 `FROM` `scopeTargetCTE context_tasks reads direct source-task relations` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/asset_dsl.go::AssetStore.QueryDSLInScope` · [근거](evidence:db-pg-access-task-relations-d6b7cacb96) | `read` / `FROM` | L588 `FROM` `source fragment: scopeTargetCTE context_tasks reads direct source-task relations <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/exploration_sources.go::ExplorationStore.DirectSourceStores` · [근거](evidence:db-pg-access-task-relations-c78896528c) | `read` / `JOIN` | L21 `JOIN` `…T source.id, source.exploration_id, source.description, source.goal, source.status FROM tasks owner JOIN task_relations relation ON relation.task_id=owner.id JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE owner.exploration_id=$1 AND owner.deleted_at IS NULL ORDER BY relation.created_at, source.…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_archives.go::DB.QueueTaskArchive` · [근거](evidence:db-pg-access-task-relations-4204004634) | `read` / `FROM` | L249 `FROM` `SELECT child.id FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE relation.source_task_id=$1 AND (pending.id IS NULL OR pending.state N…`<br>L262 `FROM` `SELECT source_task_id FROM task_relations WHERE task_id=$1 ORDER BY created_at, source_task_id` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.TaskArchiveBlockers` · [근거](evidence:db-pg-access-task-relations-bcd7bf888b) | `read` / `FROM` | L86 `FROM` `SELECT relation.source_task_id, MIN(child.id) FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL LEFT JOIN task_archives pending ON pending.task_id=child.id WHERE pending.id IS NULL OR pending.state NOT IN ('archive_queued','archivi…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-task-relations-d4dd843674) | `read` / `FROM` | L585 `FROM` `source fragment: SELECT * FROM task_relations WHERE task_id=$1 ORDER BY created_at,source_task_id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L628 `FROM` `source fragment: SELECT source_task_id FROM task_relations WHERE task_id=$1 ORDER BY created_at,source_task_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-relations-17a9fa6cfc) | `read,write` / `DELETE,FROM` | L54 `FROM` `SELECT child.id FROM task_relations relation JOIN tasks child ON child.id=relation.task_id AND child.deleted_at IS NULL WHERE relation.source_task_id=$1 LIMIT 1`<br>L91 `DELETE` `DELETE FROM task_relations WHERE task_id=$1 OR source_task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreTaskRelations` · [근거](evidence:db-pg-access-task-relations-9ed25a7ca3) | `write` / `INSERT` | L610 `INSERT` `INSERT INTO task_relations(task_id,source_task_id,created_at) VALUES($1,$2,COALESCE($3::timestamptz,now())) ON CONFLICT DO NOTHING` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-task-relations-e4cba26040) | `read` / `FROM` | L375 `FROM` `…HERE task.id=$1 AND task.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id, true FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT intent.id, asset.id, asset.type, CASE asset.type WHEN 'root_domain' THEN COALESCE(asset.do…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-task-relations-2253a6eef8) | `read` / `FROM` | L202 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), context_assets AS ( SELECT DISTINCT a.id FROM assets a WHERE EXISTS (SELECT 1 FROM context_tasks…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.ListTaskScopeWithSources` · [근거](evidence:db-pg-access-task-relations-f795b2d481) | `read` / `FROM` | L94 `FROM` `source fragment: …OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT ts.id, ts.task_id, ts.kind, COALESCE(ts.company_id,0), COALESCE(c.name,''), COALESCE(ts.do… <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-task-relations-1e4cb6ca17) | `read` / `FROM` | L170 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_dom…`<br>L177 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_dom…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-task-relations-53f3016317) | `read` / `FROM` | L125 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT count(*) FROM task_scope ts JOIN context_tasks ctx ON ctx.task_id=ts.task_id`<br>L127 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_dom…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.TaskSourceIDs` · [근거](evidence:db-pg-access-task-relations-e914b0805b) | `read` / `FROM` | L324 `FROM` `SELECT source_task_id FROM task_relations WHERE task_id=$1 ORDER BY created_at, source_task_id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.TaskSources` · [근거](evidence:db-pg-access-task-relations-b90594ba7d) | `read` / `FROM` | L363 `FROM` `SELECT t.id, t.exploration_id, t.description, t.goal, t.status FROM task_relations r JOIN tasks t ON t.id=r.source_task_id AND t.deleted_at IS NULL WHERE r.task_id=$1 ORDER BY r.created_at, r.source_task_id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_context.go::DB.hydrateTasksContext` · [근거](evidence:db-pg-access-task-relations-94aa196e22) | `read` / `FROM` | L193 `FROM` `SELECT task_id, source_task_id FROM task_relations WHERE task_id=ANY($1::bigint[]) ORDER BY task_id, created_at, source_task_id` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-task-relations-e0f81ca749) | `read` / `FROM` | L428 `FROM` `…OM tasks t WHERE t.id=$1 AND t.deleted_at IS NULL UNION ALL SELECT source.id, source.exploration_id FROM task_relations relation JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ), target AS ( SELECT DISTINCT a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_dom…` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |
| `db/tasks.go::insertTaskRelations` · [근거](evidence:db-pg-access-task-relations-8545d44a48) | `write` / `INSERT` | L319 `INSERT` `INSERT INTO task_relations(task_id, source_task_id) SELECT $1, id FROM tasks WHERE id=$2 AND deleted_at IS NULL` | [`feature-task-bootstrap`](../../features/task-exploration.md#bootstrap) |

**처분** · located production table-symbol binding 18개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-asset-links"></a>
## `task_asset_links`

[task_asset_links 물리 객체](task-exploration.md#table-task-asset-links) · [field 의미](semantic-catalog.md#semantic-task-asset-links)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-task-asset-links-8fdbe1bf14) | `read` / `FROM` | L586 `FROM` `source fragment: SELECT * FROM task_asset_links WHERE task_id=$1 ORDER BY asset_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetIDsQuery` · [근거](evidence:db-pg-access-task-asset-links-845cf63947) | `read` / `FROM` | L529 `FROM` `SELECT id FROM assets WHERE $1=ANY(task_ids) UNION SELECT link.asset_id FROM task_asset_links link WHERE link.task_id=$1 UNION SELECT anchor.asset_id FROM exploration_anchors anchor JOIN exploration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$2 UNION SELECT value::bigint FROM findings finding…` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-asset-links-1da1eb7080) | `write` / `DELETE` | L92 `DELETE` `DELETE FROM task_asset_links WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-task-asset-links-b7665de9b5) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets.go::AssetStore.AttachAssetsToTask` · [근거](evidence:db-pg-access-task-asset-links-0ea29c2581) | `write` / `INSERT` | L301 `INSERT` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary) SELECT $1, id, 'manual', $3 FROM assets WHERE id=ANY($2::bigint[]) ON CONFLICT (task_id, asset_id) DO UPDATE SET source='manual', source_summary=EXCLUDED.source_summary, source…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.IntentAssets` · [근거](evidence:db-pg-access-task-asset-links-13253489dd) | `read` / `JOIN` | L375 `JOIN` `…ation_anchors anchor ON anchor.node_id=intent.id JOIN assets asset ON asset.id=anchor.asset_id LEFT JOIN task_asset_links link ON link.task_id=context.task_id AND link.asset_id=asset.id WHERE NOT context.inherited OR intent.state IN ('done','blocked','exhausted','stopped') ORDER BY context.inherited, intent.id DESC, asset.id` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.SetTaskAssetSource` · [근거](evidence:db-pg-access-task-asset-links-49ecbd9233) | `write` / `INSERT` | L101 `INSERT` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NU…`<br>L113 `INSERT` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NU…`<br>L115 `INSERT` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary, source_node_id) SELECT task.id, asset.id, $3, $4, $5 FROM tasks task JOIN assets asset ON asset.id=$2 AND task.id=ANY(asset.task_ids) WHERE task.id=$1 AND task.deleted_at IS NU…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/task_assets.go::AssetStore.hydrateTaskAssetSources` · [근거](evidence:db-pg-access-task-asset-links-ce059baee2) | `read` / `FROM` | L344 `FROM` `SELECT asset_id, source, source_summary, source_node_id FROM task_asset_links WHERE task_id=$1 AND asset_id=ANY($2::bigint[])` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |
| `db/tasks.go::insertTaskCompanies` · [근거](evidence:db-pg-access-task-asset-links-5a2f3376f0) | `write` / `INSERT` | L296 `INSERT` `INSERT INTO task_asset_links(task_id, asset_id, source, source_summary) SELECT $1, asset.id, $3, '任务创建时关联企业：' \|\| company.name FROM assets asset JOIN companies company ON company.id=asset.company_id WHERE asset.company_id=ANY($2:…` | [`feature-asset-write`](../../features/assets-scope.md#asset-write) |

**처분** · located production table-symbol binding 9개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-llm-profiles"></a>
## `task_llm_profiles`

[task_llm_profiles 물리 객체](task-exploration.md#table-task-llm-profiles) · [field 의미](semantic-catalog.md#semantic-task-llm-profiles)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.deleteProfile` · [근거](evidence:db-pg-access-task-llm-profiles-0d9ee1601d) | `read,write` / `DELETE,FROM` | L232 `FROM` `…LECT t.id FROM tasks t WHERE t.llm_profile_id=$1 OR t.active_llm_profile_id=$1 OR EXISTS ( SELECT 1 FROM task_llm_profiles x WHERE x.task_id=t.id AND x.profile_id=$1 ) ORDER BY t.id FOR UPDATE OF t`<br>L281 `FROM` `…AS ref_id FROM tasks t WHERE t.llm_profile_id=$1 OR t.active_llm_profile_id=$1 OR EXISTS ( SELECT 1 FROM task_llm_profiles x WHERE x.task_id=t.id AND x.profile_id=$1 ) UNION ALL SELECT 'agent', a.id FROM agents a WHERE a.llm_profile_id=$1 UNION ALL SELECT 'conversation', c.id FROM conversations c WHERE c.llm_profile_id=$1 ) refs ORDER BY re…`<br>L330 `FROM` `SELECT x.task_id, x.position, COALESCE(t.active_llm_profile_id=$1, false) FROM task_llm_profiles x JOIN tasks t ON t.id=x.task_id WHERE x.profile_id=$1 ORDER BY x.task_id`<br>L368 `FROM` `SELECT profile_id FROM task_llm_profiles WHERE task_id=$1 AND position>$2 AND status='ready' ORDER BY position LIMIT 1`<br>L376 `DELETE` `DELETE FROM task_llm_profiles WHERE task_id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-task-llm-profiles-31a774dab0) | `read` / `FROM` | L587 `FROM` `source fragment: SELECT * FROM task_llm_profiles WHERE task_id=$1 ORDER BY position <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-llm-profiles-39289b56b8) | `write` / `DELETE` | L93 `DELETE` `DELETE FROM task_llm_profiles WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreTaskLLMProfiles` · [근거](evidence:db-pg-access-task-llm-profiles-125e1281e9) | `write` / `INSERT` | L658 `INSERT` `INSERT INTO task_llm_profiles(task_id,profile_id,position,status,last_error,exhausted_at,created_at,updated_at) VALUES($1,$2,$3,$4,NULLIF($5,''),$6::timestamptz,COALESCE($7::timestamptz,now()),COALESCE($8::timestamptz,now())) ON CONFLICT DO NOTHING` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_context.go::DB.ReplaceTaskLLMProfiles` · [근거](evidence:db-pg-access-task-llm-profiles-511b963d68) | `write` / `DELETE` | L423 `DELETE` `DELETE FROM task_llm_profiles WHERE task_id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.TaskLLMProfiles` · [근거](evidence:db-pg-access-task-llm-profiles-9891428a2e) | `read` / `FROM` | L385 `FROM` `SELECT profile_id, position, status, COALESCE(last_error,''), exhausted_at FROM task_llm_profiles WHERE task_id=$1 ORDER BY position` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.hydrateTasksContext` · [근거](evidence:db-pg-access-task-llm-profiles-3454e63b94) | `read` / `JOIN` | L138 `JOIN` `…on, p.profile_id, p.position, p.status, COALESCE(p.last_error,''), p.exhausted_at FROM tasks t LEFT JOIN task_llm_profiles p ON p.task_id=t.id WHERE t.id=ANY($1::bigint[]) ORDER BY t.id, p.position NULLS LAST` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.markTaskLLMProfileQuotaExhausted` · [근거](evidence:db-pg-access-task-llm-profiles-89576d006e) | `read,write` / `FROM,UPDATE` | L491 `FROM` `SELECT position, status FROM task_llm_profiles WHERE task_id=$1 AND profile_id=$2`<br>L509 `UPDATE` `UPDATE task_llm_profiles SET status='quota_exhausted', last_error=$3, exhausted_at=now() WHERE task_id=$1 AND profile_id=$2`<br>L521 `FROM` `SELECT profile_id FROM task_llm_profiles WHERE task_id=$1 AND position>$2 AND status='ready' ORDER BY position LIMIT 1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_context.go::DB.taskLLMContext` · [근거](evidence:db-pg-access-task-llm-profiles-6ec5c4a784) | `read` / `JOIN` | L261 `JOIN` `…on, p.profile_id, p.position, p.status, COALESCE(p.last_error,''), p.exhausted_at FROM tasks t LEFT JOIN task_llm_profiles p ON p.task_id=t.id WHERE t.id=$1 ORDER BY p.position NULLS LAST` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/tasks.go::insertTaskLLMProfiles` · [근거](evidence:db-pg-access-task-llm-profiles-d62d6248f4) | `write` / `INSERT` | L338 `INSERT` `INSERT INTO task_llm_profiles(task_id, profile_id, position) VALUES ($1,$2,$3)` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |

**처분** · located production table-symbol binding 10개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-scope"></a>
## `task_scope`

[task_scope 물리 객체](task-exploration.md#table-task-scope) · [field 의미](semantic-catalog.md#semantic-task-scope)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/asset_dsl.go::AssetStore.GetByIDsInScope` · [근거](evidence:db-pg-access-task-scope-d270c90e96) | `read` / `JOIN` | L624 `JOIN` `scopeTargetCTE joins declared task scope; ip/cidr branches call try_inet` · runtime fragment A/U | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/asset_dsl.go::AssetStore.QueryDSLInScope` · [근거](evidence:db-pg-access-task-scope-2050f94c23) | `read` / `JOIN` | L588 `JOIN` `source fragment: scopeTargetCTE joins declared task scope; ip/cidr branches call try_inet <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-task-scope-508d51a85a) | `read` / `FROM` | L588 `FROM` `source fragment: SELECT * FROM task_scope WHERE task_id=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-task-scope-be504fc9c1) | `write` / `DELETE` | L94 `DELETE` `DELETE FROM task_scope WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreTaskScopes` · [근거](evidence:db-pg-access-task-scope-0488ce89d1) | `write` / `INSERT` | L635 `INSERT` `INSERT INTO task_scope SELECT * FROM json_populate_recordset(NULL::task_scope,$1::json) ON CONFLICT DO NOTHING` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_assets_context.go::AssetStore.HostsByTaskWithSources` · [근거](evidence:db-pg-access-task-scope-e03dcb28ba) | `read` / `JOIN` | L202 `JOIN` `… context_tasks ctx ON ctx.exploration_id=en.exploration_id UNION SELECT DISTINCT a.id FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id=ts.company_id) OR (ts.kind='root_domain' AND a.root_domain=ts.domain) OR (ts.kind='subdomain' AND a.domain=ts.domain) OR (ts.kind IN ('ip','cidr') AND ts.net >>= try_inet(a.ip…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_assets_context.go::AssetStore.ListTaskScopeWithSources` · [근거](evidence:db-pg-access-task-scope-205ddab78f) | `read` / `FROM` | L94 `FROM` `source fragment: …(ts.domain,''), COALESCE(ts.net::text,''), COALESCE(ts.value,''), ts.source, COALESCE(ts.reason,'') FROM task_scope ts JOIN context_tasks ctx ON ctx.task_id=ts.task_id LEFT JOIN companies c ON c.id=ts.company_id ORDER BY CASE WHEN ts.task_id=$1 THEN 0 ELSE 1 END, ts.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_assets_context.go::AssetStore.ListUntestedAssetsWithSources` · [근거](evidence:db-pg-access-task-scope-00288db9f0) | `read` / `JOIN` | L170 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AND ts.net >>= try_ine…`<br>L177 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AND ts.net >>= try_ine…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_assets_context.go::AssetStore.TaskCoverageWithSources` · [근거](evidence:db-pg-access-task-scope-bb64288ddc) | `read` / `FROM,JOIN` | L125 `FROM` `…d=relation.source_task_id AND source.deleted_at IS NULL WHERE relation.task_id=$1 ) SELECT count(*) FROM task_scope ts JOIN context_tasks ctx ON ctx.task_id=ts.task_id`<br>L127 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AND ts.net >>= try_ine…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_context.go::DB.TaskCompanyIDs` · [근거](evidence:db-pg-access-task-scope-f3d7ab74f1) | `read` / `FROM` | L343 `FROM` `SELECT company_id FROM task_scope WHERE task_id=$1 AND kind='company' AND company_id IS NOT NULL ORDER BY id` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_context.go::DB.hydrateTasksContext` · [근거](evidence:db-pg-access-task-scope-4663d5f3d5) | `read` / `FROM` | L217 `FROM` `SELECT task_id, company_id FROM task_scope WHERE task_id=ANY($1::bigint[]) AND kind='company' AND company_id IS NOT NULL ORDER BY task_id, id` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.BuildCoverageGraph` · [근거](evidence:db-pg-access-task-scope-3038821322) | `read` / `JOIN` | L428 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AND ts.net >>= try_ine…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.DeleteTaskScope` · [근거](evidence:db-pg-access-task-scope-d4523a62f2) | `write` / `DELETE` | L226 `DELETE` `DELETE FROM task_scope WHERE id=$1 AND task_id=$2` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.ListTaskScope` · [근거](evidence:db-pg-access-task-scope-a749a30b74) | `read` / `FROM` | L236 `FROM` `…(ts.domain,''), COALESCE(ts.net::text,''), COALESCE(ts.value,''), ts.source, COALESCE(ts.reason,'') FROM task_scope ts LEFT JOIN companies c ON c.id=ts.company_id WHERE ts.task_id=$1 ORDER BY ts.id` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.ListUntestedAssets` · [근거](evidence:db-pg-access-task-scope-d824d02d68) | `read` / `JOIN` | L622 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AN…`<br>L627 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AN…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.TaskCoverage` · [근거](evidence:db-pg-access-task-scope-c99ebf71ad) | `read` / `FROM,JOIN` | L330 `FROM` `SELECT count(*) FROM task_scope WHERE task_id=$1`<br>L331 `JOIN` `…a.id, a.type, COALESCE(a.url, a.domain, a.ip, a.app_name, a.root_domain, '') AS label FROM assets a JOIN task_scope ts ON ts.task_id = $1 AND ( (ts.kind='company' AND a.company_id = ts.company_id) OR (ts.kind='root_domain' AND a.root_domain = ts.domain) OR (ts.kind='subdomain' AND a.domain = ts.domain) OR (ts.kind IN ('ip','cidr') AN…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/task_scope.go::AssetStore.upsertTaskScopeResult` · [근거](evidence:db-pg-access-task-scope-6fe50806ec) | `write` / `INSERT` | L79 `INSERT` `INSERT INTO task_scope(task_id, kind, company_id, domain, net, value, source, reason) VALUES ($1,$2,$3,$4,$5::cidr,$6,$7,NULLIF($8,'')) ON CONFLICT DO NOTHING`<br>L88 `INSERT` `INSERT INTO task_scope(task_id, kind, company_id, domain, net, value, source, reason) VALUES ($1,$2,$3,$4,$5::cidr,$6,$7,NULLIF($8,'')) ON CONFLICT DO NOTHING`<br>L90 `INSERT` `INSERT INTO task_scope(task_id, kind, company_id, domain, net, value, source, reason) VALUES ($1,$2,$3,$4,$5::cidr,$6,$7,NULLIF($8,'')) ON CONFLICT DO NOTHING` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |
| `db/tasks.go::insertTaskCompanies` · [근거](evidence:db-pg-access-task-scope-8ffdf9a4ad) | `write` / `INSERT` | L264 `INSERT` `…ition FROM unnest($2::bigint[]) WITH ORDINALITY AS requested(company_id, position) ), inserted AS ( INSERT INTO task_scope(task_id, kind, company_id, source, reason) SELECT $1, 'company', companies.id, 'manual', '任务创建时关联企业' FROM requested JOIN companies ON companies.id=requested.company_id ORDER BY requested.position RETUR…` | [`feature-scope-model`](../../features/assets-scope.md#scope-model) |

**처분** · located production table-symbol binding 18개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agents"></a>
## `agents`

[agents 물리 객체](agent-runtime.md#table-agents) · [field 의미](semantic-catalog.md#semantic-agents)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.CreateAgent` · [근거](evidence:db-pg-access-agents-2c284773a1) | `write` / `INSERT` | L559 `INSERT` `INSERT INTO agents(key, name, description, role, builtin, enabled) VALUES ($1, $2, NULLIF($3,''), 'assistant', false, true) RETURNING id,key,name,COALESCE(description,''),role,builtin,enabled,COALESCE(max_turns,0),COALESCE(run_seconds,600…` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.CurrentPrompt` · [근거](evidence:db-pg-access-agents-c2bf78d332) | `read` / `FROM` | L732 `FROM` `SELECT p.template_text FROM agents a JOIN agent_prompts p ON p.id=a.current_prompt_id WHERE a.id=$1` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.DeleteAgent` · [근거](evidence:db-pg-access-agents-f9ae139553) | `write` / `DELETE` | L580 `DELETE` `DELETE FROM agents WHERE key=$1 AND builtin=false` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.GetAgentByKey` · [근거](evidence:db-pg-access-agents-4b59fc5a5e) | `read` / `FROM` | L498 `FROM` `…n_mode,'serial'),COALESCE(trigger_merge_mode,'all'),COALESCE(trigger_max_parallel,5),llm_profile_id FROM agents WHERE key=$1` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.ListAgents` · [근거](evidence:db-pg-access-agents-9fddeb0f2c) | `read` / `FROM` | L481 `FROM` `…n_mode,'serial'),COALESCE(trigger_merge_mode,'all'),COALESCE(trigger_max_parallel,5),llm_profile_id FROM agents ORDER BY id` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SavePrompt` · [근거](evidence:db-pg-access-agents-0a71e429d2) | `write` / `UPDATE` | L777 `UPDATE` `UPDATE agents SET current_prompt_id=$1 WHERE id=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SeedPromptIfEmpty` · [근거](evidence:db-pg-access-agents-77eea5cf6c) | `read` / `FROM` | L745 `FROM` `SELECT current_prompt_id FROM agents WHERE id=$1` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentInteractiveShell` · [근거](evidence:db-pg-access-agents-983020c62e) | `write` / `UPDATE` | L648 `UPDATE` `UPDATE agents SET interactive_shell=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentLLMProfile` · [근거](evidence:db-pg-access-agents-9fd4bd5238) | `read,write` / `FROM,UPDATE` | L606 `FROM` `SELECT id FROM agents WHERE key=$1 FOR UPDATE`<br>L616 `UPDATE` `UPDATE agents SET llm_profile_id=$1 WHERE id=$2` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/config.go::DB.SetAgentMaxTurns` · [근거](evidence:db-pg-access-agents-cc8b6daccc) | `write` / `UPDATE` | L589 `UPDATE` `UPDATE agents SET max_turns=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentRunSeconds` · [근거](evidence:db-pg-access-agents-e55b0b44a3) | `write` / `UPDATE` | L679 `UPDATE` `UPDATE agents SET run_seconds=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentTaskTimeoutWrapup` · [근거](evidence:db-pg-access-agents-219ad7a5cb) | `write` / `UPDATE` | L670 `UPDATE` `UPDATE agents SET task_timeout_wrapup_prompt=$1, task_timeout_wrapup_max_turns=$2 WHERE key=$3` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentTriggerBehavior` · [근거](evidence:db-pg-access-agents-5dcb3a4fbf) | `write` / `UPDATE` | L700 `UPDATE` `UPDATE agents SET trigger_run_mode=$1, trigger_merge_mode=$2, trigger_max_parallel=$3 WHERE key=$4` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/config.go::DB.SetAgentWebSearch` · [근거](evidence:db-pg-access-agents-974caa7851) | `write` / `UPDATE` | L641 `UPDATE` `UPDATE agents SET web_search=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentWrapupMaxTurns` · [근거](evidence:db-pg-access-agents-a253d0b0c9) | `write` / `UPDATE` | L662 `UPDATE` `UPDATE agents SET wrapup_max_turns=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SetAgentWrapupPrompt` · [근거](evidence:db-pg-access-agents-16ef29d2ab) | `write` / `UPDATE` | L655 `UPDATE` `UPDATE agents SET wrapup_prompt=$1 WHERE key=$2` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.UpdateAgentMeta` · [근거](evidence:db-pg-access-agents-61e77a4c94) | `write` / `UPDATE` | L572 `UPDATE` `UPDATE agents SET name=$2, description=NULLIF($3,'') WHERE key=$1 AND builtin=false` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.deleteProfile` · [근거](evidence:db-pg-access-agents-83239d7785) | `read` / `FROM` | L245 `FROM` `SELECT id FROM agents WHERE llm_profile_id=$1 ORDER BY id FOR UPDATE`<br>L281 `FROM` `… FROM task_llm_profiles x WHERE x.task_id=t.id AND x.profile_id=$1 ) UNION ALL SELECT 'agent', a.id FROM agents a WHERE a.llm_profile_id=$1 UNION ALL SELECT 'conversation', c.id FROM conversations c WHERE c.llm_profile_id=$1 ) refs ORDER BY ref_kind, ref_id` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/db.go::DB.seedBuiltinSkillVisibility` · [근거](evidence:db-pg-access-agents-dd10946574) | `read` / `FROM` | L319 `FROM` `INSERT INTO agent_skill_visibility(agent_id, skill_name, enabled) SELECT id, $2, true FROM agents WHERE key=$1 ON CONFLICT (agent_id, skill_name) DO NOTHING` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/db.go::DB.seedBuiltins` · [근거](evidence:db-pg-access-agents-3a3635b6f6) | `write` / `INSERT,UPDATE` | L205 `INSERT` `INSERT INTO agents(key, name, description, role, builtin, enabled, interactive_shell, run_seconds) VALUES ($1, $2, NULLIF($3,''), $4, true, true, $5, COALESCE($6, 1200)) ON CONFLICT (key) DO UPDATE SET name = EXCLUDED.name, description = …`<br>L235 `UPDATE` `UPDATE agents SET interactive_shell=true WHERE key IN ('planner','worker','mainagent','auto')` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `server/finding_retests.go::Server.seedFindingRetester` · [근거](evidence:db-pg-access-agents-b57863a261) | `write` / `INSERT,UPDATE` | L221 `INSERT` `INSERT INTO agents(key,name,description,role,builtin,enabled) VALUES ($1,'漏洞复测','从漏洞详情手动启动，读取原证据并保存独立复测结论。','assistant',false,true) ON CONFLICT (key) DO NOTHING RETURNING id`<br>L233 `UPDATE` `UPDATE agents SET current_prompt_id=$1 WHERE id=$2` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 21개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agent-prompts"></a>
## `agent_prompts`

[agent_prompts 물리 객체](agent-runtime.md#table-agent-prompts) · [field 의미](semantic-catalog.md#semantic-agent-prompts)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.CurrentPrompt` · [근거](evidence:db-pg-access-agent-prompts-a685c1232c) | `read` / `JOIN` | L732 `JOIN` `SELECT p.template_text FROM agents a JOIN agent_prompts p ON p.id=a.current_prompt_id WHERE a.id=$1` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.ListPromptVersions` · [근거](evidence:db-pg-access-agent-prompts-8df6bbcbcf) | `read` / `FROM` | L791 `FROM` `SELECT version,template_text,COALESCE(note,''),created_at FROM agent_prompts WHERE agent_id=$1 ORDER BY version DESC` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/config.go::DB.SavePrompt` · [근거](evidence:db-pg-access-agent-prompts-8c714086b3) | `read,write` / `FROM,INSERT` | L769 `FROM` `SELECT COALESCE(max(version),0)+1 FROM agent_prompts WHERE agent_id=$1`<br>L773 `INSERT` `INSERT INTO agent_prompts(agent_id,version,template_text,note,updated_by) VALUES ($1,$2,$3,NULLIF($4,''),NULLIF($5,'')) RETURNING id` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `server/finding_retests.go::Server.seedFindingRetester` · [근거](evidence:db-pg-access-agent-prompts-5f54e84682) | `write` / `INSERT` | L229 `INSERT` `INSERT INTO agent_prompts(agent_id,version,template_text,note,updated_by) VALUES ($1,1,$2,'内置默认','system') RETURNING id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 4개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agent-prompt-vars"></a>
## `agent_prompt_vars`

[agent_prompt_vars 물리 객체](agent-runtime.md#table-agent-prompt-vars) · [field 의미](semantic-catalog.md#semantic-agent-prompt-vars)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.PromptVars` · [근거](evidence:db-pg-access-agent-prompt-vars-c7e87c2bdd) | `read` / `FROM` | L713 `FROM` `SELECT var_name,COALESCE(description,''),COALESCE(example,''),source FROM agent_prompt_vars WHERE agent_id=$1 ORDER BY var_name` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |
| `db/db.go::DB.seedBuiltins` · [근거](evidence:db-pg-access-agent-prompt-vars-af868cc140) | `write` / `DELETE,INSERT` | L214 `INSERT` `INSERT INTO agent_prompt_vars(agent_id, var_name, description, example, source) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (agent_id, var_name) DO UPDATE SET description = EXCLUDED.description, example = EXCLUDED.example, source = EXCLUDED.source`<br>L228 `DELETE` `DELETE FROM agent_prompt_vars WHERE var_name IN ('EngagementTitle', 'CoverageGaps', 'Now')` | [`module-agent-context`](../../modules/agent-runtime.md#context-memory) |

**처분** · located production table-symbol binding 2개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-mcp-servers"></a>
## `mcp_servers`

[mcp_servers 물리 객체](agent-runtime.md#table-mcp-servers) · [field 의미](semantic-catalog.md#semantic-mcp-servers)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.DeleteMCP` · [근거](evidence:db-pg-access-mcp-servers-f15e8cec3a) | `write` / `DELETE` | L939 `DELETE` `DELETE FROM mcp_servers WHERE id=$1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.ListMCP` · [근거](evidence:db-pg-access-mcp-servers-84800c4c4d) | `read` / `FROM` | L823 `FROM` `SELECT id,name,transport,COALESCE(command,''),args,env,COALESCE(url,''),enabled,insecure FROM mcp_servers ORDER BY id` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.SaveMCP` · [근거](evidence:db-pg-access-mcp-servers-61e6c5ce4a) | `write` / `INSERT,UPDATE` | L921 `INSERT` `INSERT INTO mcp_servers(name,transport,command,args,env,url,enabled,insecure) VALUES ($1,$2,NULLIF($3,''),$4,$5,NULLIF($6,''),$7,$8) RETURNING id`<br>L925 `UPDATE` `UPDATE mcp_servers SET name=$1,transport=$2,command=NULLIF($3,''),args=$4,env=$5,url=NULLIF($6,''),enabled=$7,insecure=$8 WHERE id=$9` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/db.go::DB.seedBuiltins` · [근거](evidence:db-pg-access-mcp-servers-35214faf02) | `write` / `INSERT` | L245 `INSERT` `INSERT INTO mcp_servers(name, transport, command, args, env, enabled) VALUES ('browser', 'stdio', 'npx', $1, '{}', false) ON CONFLICT (name) DO NOTHING` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |

**처분** · located production table-symbol binding 4개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-mcp-tools-cache"></a>
## `mcp_tools_cache`

[mcp_tools_cache 물리 객체](agent-runtime.md#table-mcp-tools-cache) · [field 의미](semantic-catalog.md#semantic-mcp-tools-cache)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.MCPToolNames` · [근거](evidence:db-pg-access-mcp-tools-cache-2aa10feb7d) | `read` / `FROM` | L852 `FROM` `SELECT tool_name FROM mcp_tools_cache WHERE server_id=$1 ORDER BY tool_name` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.MCPToolsDetailed` · [근거](evidence:db-pg-access-mcp-tools-cache-4c7e318619) | `read` / `FROM` | L876 `FROM` `SELECT tool_name, COALESCE(description,'') FROM mcp_tools_cache WHERE server_id=$1 ORDER BY tool_name` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.SaveMCPTools` · [근거](evidence:db-pg-access-mcp-tools-cache-9879c7473c) | `write` / `DELETE,INSERT` | L899 `DELETE` `DELETE FROM mcp_tools_cache WHERE server_id=$1`<br>L903 `INSERT` `INSERT INTO mcp_tools_cache(server_id, tool_name, description) VALUES ($1,$2,$3) ON CONFLICT (server_id, tool_name) DO UPDATE SET description=EXCLUDED.description` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |

**처분** · located production table-symbol binding 3개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agent-visibility"></a>
## `agent_visibility`

[agent_visibility 물리 객체](agent-runtime.md#table-agent-visibility) · [field 의미](semantic-catalog.md#semantic-agent-visibility)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.AgentBindingCounts` · [근거](evidence:db-pg-access-agent-visibility-c6d44c1faf) | `read` / `FROM` | L530 `FROM` `SELECT agent_id, count(DISTINCT resource_id) FROM agent_visibility WHERE resource_kind='mcp' AND enabled GROUP BY agent_id` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.AgentVisible` · [근거](evidence:db-pg-access-agent-visibility-e262281a79) | `read` / `FROM` | L1023 `FROM` `SELECT resource_id FROM agent_visibility WHERE agent_id=$1 AND resource_kind=$2 AND enabled` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.DeleteMCP` · [근거](evidence:db-pg-access-agent-visibility-5804b15194) | `write` / `DELETE` | L936 `DELETE` `DELETE FROM agent_visibility WHERE resource_kind='mcp' AND resource_id=$1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.ResourceAgents` · [근거](evidence:db-pg-access-agent-visibility-96acd3b356) | `read` / `FROM` | L1041 `FROM` `SELECT agent_id FROM agent_visibility WHERE resource_kind=$1 AND resource_id=$2 AND enabled` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.SetAgentVisibilityKind` · [근거](evidence:db-pg-access-agent-visibility-183ce54e27) | `write` / `DELETE,INSERT` | L1066 `DELETE` `DELETE FROM agent_visibility WHERE agent_id=$1 AND resource_kind=$2`<br>L1070 `INSERT` `INSERT INTO agent_visibility(agent_id,resource_kind,resource_id,enabled) VALUES ($1,$2,$3,true) ON CONFLICT (agent_id,resource_kind,resource_id,mcp_tool_name) DO UPDATE SET enabled=true` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.ToggleVisibility` · [근거](evidence:db-pg-access-agent-visibility-3ff56d1a8f) | `write` / `DELETE,INSERT` | L1081 `INSERT` `INSERT INTO agent_visibility(agent_id,resource_kind,resource_id,enabled) VALUES ($1,$2,$3,true) ON CONFLICT (agent_id,resource_kind,resource_id,mcp_tool_name) DO UPDATE SET enabled=true`<br>L1085 `DELETE` `DELETE FROM agent_visibility WHERE agent_id=$1 AND resource_kind=$2 AND resource_id=$3` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agent-skill-visibility"></a>
## `agent_skill_visibility`

[agent_skill_visibility 물리 객체](agent-runtime.md#table-agent-skill-visibility) · [field 의미](semantic-catalog.md#semantic-agent-skill-visibility)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.AgentBindingCounts` · [근거](evidence:db-pg-access-agent-skill-visibility-fcdfad0799) | `read` / `FROM` | L533 `FROM` `SELECT agent_id, count(*) FROM agent_skill_visibility WHERE enabled GROUP BY agent_id` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.AgentSkillNames` · [근거](evidence:db-pg-access-agent-skill-visibility-e620ecb222) | `read` / `FROM` | L949 `FROM` `SELECT skill_name FROM agent_skill_visibility WHERE agent_id=$1 AND enabled ORDER BY skill_name` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.DeleteSkillVisibility` · [근거](evidence:db-pg-access-agent-skill-visibility-21ca693b0e) | `write` / `DELETE` | L1015 `DELETE` `DELETE FROM agent_skill_visibility WHERE skill_name=$1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.SetAgentSkillVisibility` · [근거](evidence:db-pg-access-agent-skill-visibility-6e53f992b0) | `write` / `DELETE,INSERT` | L990 `DELETE` `DELETE FROM agent_skill_visibility WHERE agent_id=$1`<br>L994 `INSERT` `INSERT INTO agent_skill_visibility(agent_id,skill_name,enabled) VALUES ($1,$2,true) ON CONFLICT (agent_id,skill_name) DO UPDATE SET enabled=true` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.SkillAgents` · [근거](evidence:db-pg-access-agent-skill-visibility-a06c6fc981) | `read` / `FROM` | L967 `FROM` `SELECT agent_id FROM agent_skill_visibility WHERE skill_name=$1 AND enabled` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/config.go::DB.ToggleSkillVisibility` · [근거](evidence:db-pg-access-agent-skill-visibility-c22cf0e580) | `write` / `DELETE,INSERT` | L1005 `INSERT` `INSERT INTO agent_skill_visibility(agent_id,skill_name,enabled) VALUES ($1,$2,true) ON CONFLICT (agent_id,skill_name) DO UPDATE SET enabled=true`<br>L1009 `DELETE` `DELETE FROM agent_skill_visibility WHERE agent_id=$1 AND skill_name=$2` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/db.go::DB.seedBuiltinSkillVisibility` · [근거](evidence:db-pg-access-agent-skill-visibility-5e4f7d22b0) | `write` / `INSERT` | L319 `INSERT` `INSERT INTO agent_skill_visibility(agent_id, skill_name, enabled) SELECT id, $2, true FROM agents WHERE key=$1 ON CONFLICT (agent_id, skill_name) DO NOTHING` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |

**처분** · located production table-symbol binding 7개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-skill-usage"></a>
## `skill_usage`

[skill_usage 물리 객체](agent-runtime.md#table-skill-usage) · [field 의미](semantic-catalog.md#semantic-skill-usage)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/skill_usage.go::DB.InsertSkillUsage` · [근거](evidence:db-pg-access-skill-usage-1fd6c292b8) | `write` / `INSERT` | L31 `INSERT` `INSERT INTO skill_usage(skill, agent_key, task_id, exploration_id, intent_id, session_id, args_len, found) VALUES ($1, NULLIF($2,''), $3, $4, $5, NULLIF($6,''), $7, $8)` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/skill_usage.go::DB.MissingSkillStats` · [근거](evidence:db-pg-access-skill-usage-9afe4d9466) | `read` / `FROM` | L110 `FROM` `…OUNT(*) AS calls, COALESCE(STRING_AGG(DISTINCT agent_key, ','), '') AS agents, MAX(ts) AS last_used FROM skill_usage WHERE NOT found GROUP BY skill ORDER BY COUNT(*) DESC, skill` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/skill_usage.go::DB.RecentSkillCalls` · [근거](evidence:db-pg-access-skill-usage-4ad66db7ad) | `read` / `FROM` | L168 `FROM` `SELECT ts, COALESCE(agent_key,''), COALESCE(task_id,0), COALESCE(session_id,''), args_len FROM skill_usage WHERE skill = $1 AND found ORDER BY ts DESC LIMIT $2` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/skill_usage.go::DB.SkillCallsByTask` · [근거](evidence:db-pg-access-skill-usage-d96e8cc76f) | `read` / `FROM` | L192 `FROM` `SELECT skill, COUNT(*) AS calls, MAX(ts) AS last_used FROM skill_usage WHERE task_id = $1 AND found GROUP BY skill ORDER BY COUNT(*) DESC, skill` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/skill_usage.go::DB.SkillStats` · [근거](evidence:db-pg-access-skill-usage-cceb80949c) | `read` / `FROM` | L62 `FROM` `…ask_id) AS tasks, COALESCE(STRING_AGG(DISTINCT agent_key, ','), '') AS agents, MAX(ts) AS last_used FROM skill_usage WHERE found GROUP BY skill ORDER BY COUNT(*) DESC, skill` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-skill-usage-7142046787) | `read` / `FROM` | L594 `FROM` `source fragment: SELECT * FROM skill_usage WHERE task_id=$1 OR exploration_id=$2 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::taskArchiveAggregates` · [근거](evidence:db-pg-access-skill-usage-1bf74722f9) | `read` / `FROM` | L741 `FROM` `SELECT COALESCE(jsonb_object_agg(name,n),'{}'::jsonb) FROM (SELECT skill name,count(*) n FROM skill_usage WHERE (task_id=$1 OR exploration_id=$2) AND found GROUP BY skill) x`<br>L742 `FROM` `…DISTINCT agent_key) FILTER (WHERE agent_key IS NOT NULL),ARRAY[]::text[]) agents, max(ts) last_used FROM skill_usage WHERE (task_id=$1 OR exploration_id=$2) AND found GROUP BY skill) x`<br>L747 `FROM` `…DISTINCT agent_key) FILTER (WHERE agent_key IS NOT NULL),ARRAY[]::text[]) agents, max(ts) last_used FROM skill_usage WHERE (task_id=$1 OR exploration_id=$2) AND NOT found GROUP BY skill) x` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.RestoreTaskArchive` · [근거](evidence:db-pg-access-skill-usage-ff4bfd830a) | `write` / `DELETE` | L77 `DELETE` `DELETE FROM <skill_usage\|tool_usage> WHERE task_id=$1 OR exploration_id=$2` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-skill-usage-7d2fb6f50a) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 9개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-tool-usage"></a>
## `tool_usage`

[tool_usage 물리 객체](agent-runtime.md#table-tool-usage) · [field 의미](semantic-catalog.md#semantic-tool-usage)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-tool-usage-56d5c6b947) | `read` / `FROM` | L595 `FROM` `source fragment: SELECT * FROM tool_usage WHERE task_id=$1 OR exploration_id=$2 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::taskArchiveAggregates` · [근거](evidence:db-pg-access-tool-usage-65a68b398c) | `read` / `FROM` | L752 `FROM` `SELECT COALESCE(jsonb_object_agg(name,n),'{}'::jsonb) FROM (SELECT tool_key name,count(*) n FROM tool_usage WHERE task_id=$1 OR exploration_id=$2 GROUP BY tool_key) x` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.RestoreTaskArchive` · [근거](evidence:db-pg-access-tool-usage-21bb9443cc) | `write` / `DELETE` | L77 `DELETE` `DELETE FROM <skill_usage\|tool_usage> WHERE task_id=$1 OR exploration_id=$2` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-tool-usage-899e58268b) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/tool_usage.go::DB.InsertToolUsage` · [근거](evidence:db-pg-access-tool-usage-a5f65b1eef) | `write` / `INSERT` | L17 `INSERT` `INSERT INTO tool_usage(tool_key, agent_key, task_id, exploration_id, intent_id, session_id) VALUES ($1, NULLIF($2,''), $3, $4, $5, NULLIF($6,''))` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tool_usage.go::DB.ToolUsageCounts` · [근거](evidence:db-pg-access-tool-usage-f1f6e995a1) | `read` / `FROM` | L28 `FROM` `SELECT tool_key, COUNT(*) FROM tool_usage GROUP BY tool_key` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-tools"></a>
## `tools`

[tools 물리 객체](agent-runtime.md#table-tools) · [field 의미](semantic-catalog.md#semantic-tools)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.AgentBindingCounts` · [근거](evidence:db-pg-access-tools-07d82f89d6) | `read` / `FROM` | L536 `FROM` `SELECT elem, count(*) FROM tools, jsonb_array_elements_text(agents) AS elem GROUP BY elem` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.AddAgentToToolBinding` · [근거](evidence:db-pg-access-tools-838d1b0c28) | `write` / `UPDATE` | L50 `UPDATE` `UPDATE tools SET agents = agents \|\| to_jsonb($1::text) WHERE key=$2 AND NOT (agents ? $1)` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.CreateCustomTool` · [근거](evidence:db-pg-access-tools-d2bad554a2) | `write` / `INSERT` | L165 `INSERT` `INSERT INTO tools(key, system, description, schema, agents, enabled, kind, exec, deferred) VALUES ($1, false, $2, $3, $4, $5, $6, $7, $8)` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.DeleteCustomTool` · [근거](evidence:db-pg-access-tools-7aaef9c286) | `write` / `DELETE` | L196 `DELETE` `DELETE FROM tools WHERE key=$1 AND system=false` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.GetTool` · [근거](evidence:db-pg-access-tools-91bb934a0c) | `read` / `FROM` | L142 `FROM` `SELECT key, system, description, schema, agents, enabled, kind, exec, deferred FROM tools WHERE key=$1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.ListCustomTools` · [근거](evidence:db-pg-access-tools-d23945e7cb) | `read` / `FROM` | L202 `FROM` `SELECT key, system, description, schema, agents, enabled, kind, exec, deferred FROM tools WHERE system=false ORDER BY key` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.ListTools` · [근거](evidence:db-pg-access-tools-de24823dd2) | `read` / `FROM` | L124 `FROM` `SELECT key, system, description, schema, agents, enabled, kind, exec, deferred FROM tools ORDER BY key` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.RefreshToolDefaults` · [근거](evidence:db-pg-access-tools-fc94031a33) | `write` / `UPDATE` | L103 `UPDATE` `UPDATE tools SET description=$2, schema=$3, updated_at=now() WHERE key=$1 AND system` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.RemoveAgentFromTool` · [근거](evidence:db-pg-access-tools-599432dfc9) | `write` / `UPDATE` | L69 `UPDATE` `UPDATE tools SET agents = agents - $1 WHERE key=$2 AND agents ? $1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.RemoveAgentFromToolBindings` · [근거](evidence:db-pg-access-tools-67c2c85faa) | `write` / `UPDATE` | L61 `UPDATE` `UPDATE tools SET agents = agents - $1 WHERE agents ? $1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.SeedTool` · [근거](evidence:db-pg-access-tools-8272961e1a) | `write` / `INSERT` | L38 `INSERT` `INSERT INTO tools(key, system, description, schema, agents, enabled) VALUES ($1, true, $2, $3, $4, true) ON CONFLICT (key) DO NOTHING` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.UpdateCustomTool` · [근거](evidence:db-pg-access-tools-51e3843ba7) | `write` / `UPDATE` | L187 `UPDATE` `UPDATE tools SET description=$2, schema=$3, agents=$4, enabled=$5, kind=$6, exec=$7, deferred=$8 WHERE key=$1 AND system=false` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.UpdateTool` · [근거](evidence:db-pg-access-tools-7922588986) | `write` / `UPDATE` | L228 `UPDATE` `UPDATE tools SET description=$2, schema=$3, agents=$4, enabled=$5 WHERE key=$1` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `db/tools.go::DB.UpsertToolForce` · [근거](evidence:db-pg-access-tools-2cbf2d4e27) | `write` / `INSERT` | L83 `INSERT` `INSERT INTO tools(key, system, description, schema, agents, enabled) VALUES ($1, true, $2, $3, $4, true) ON CONFLICT (key) DO UPDATE SET description = EXCLUDED.description, schema = EXCLUDED.schema, agents = EXCLUDED.agents, enabled = tr…` | [`module-tool-policy`](../../modules/tool-policy.md#tool-policy) |
| `server/finding_traffic.go::Server.seedFindingTrafficTools` · [근거](evidence:db-pg-access-tools-ff749a71a4) | `write` / `UPDATE` | L67 `UPDATE` `UPDATE tools SET schema=jsonb_set(schema,ARRAY['properties',$2::text],$3::jsonb,true),updated_at=now() WHERE key=$1 AND system AND NOT(COALESCE(schema->'properties','{}'::jsonb) ? $2)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `server/finding_workflow.go::Server.seedFindingWorkflowTools` · [근거](evidence:db-pg-access-tools-c7498246c6) | `write` / `UPDATE` | L23 `UPDATE` `UPDATE tools SET description=$1,updated_at=now() WHERE key='traffic_search' AND system AND description=$2`<br>L79 `UPDATE` `UPDATE tools SET schema=$2::jsonb,updated_at=now() WHERE key=$1 AND system AND schema=$3::jsonb`<br>L92 `UPDATE` `UPDATE tools SET agents=$2::jsonb WHERE key=$1 AND system AND (agents='["worker"]'::jsonb OR (agents @> '["worker","planner","mainagent","auto","pentest"]'::jsonb AND jsonb_array_length(agents)=5))`<br>L96 `UPDATE` `UPDATE tools SET agents=$1::jsonb WHERE key='get_finding_traffic' AND system AND agents @> '["auto","reporter"]'::jsonb AND jsonb_array_length(agents)=2`<br>L100 `UPDATE` `UPDATE tools SET agents='["reporter"]'::jsonb WHERE key='bind_finding_traffic' AND system AND agents @> '["worker","planner","mainagent","auto","pentest"]'::jsonb AND jsonb_array_length(agents)=5` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 16개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-conversations"></a>
## `conversations`

[conversations 물리 객체](agent-runtime.md#table-conversations) · [field 의미](semantic-catalog.md#semantic-conversations)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/config.go::DB.deleteProfile` · [근거](evidence:db-pg-access-conversations-b5c436d5a0) | `read` / `FROM` | L252 `FROM` `SELECT id FROM conversations WHERE llm_profile_id=$1 ORDER BY id FOR UPDATE`<br>L281 `FROM` `… SELECT 'agent', a.id FROM agents a WHERE a.llm_profile_id=$1 UNION ALL SELECT 'conversation', c.id FROM conversations c WHERE c.llm_profile_id=$1 ) refs ORDER BY ref_kind, ref_id` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ConversationTokenSummaries` · [근거](evidence:db-pg-access-conversations-26c6f843da) | `read` / `FROM` | L23 `FROM` `…ca.output_tokens),0), COALESCE(sum(ca.cache_read_tokens),0), COALESCE(sum(ca.cache_write_tokens),0) FROM conversations c LEFT JOIN conversation_activities ca ON ca.conversation_id = c.id AND ca.kind = 'result' GROUP BY c.id` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.CreateConversation` · [근거](evidence:db-pg-access-conversations-2e0d9a9cc1) | `write` / `INSERT,UPDATE` | L94 `INSERT` `INSERT INTO conversations(agent_key, title, llm_profile_id) VALUES ($1, $2, NULL) RETURNING id, agent_key, title, llm_profile_id, pinned_at, created_at, updated_at`<br>L104 `UPDATE` `UPDATE conversations SET llm_profile_id=$2 WHERE id=$1 RETURNING id, agent_key, title, llm_profile_id, pinned_at, created_at, updated_at` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.DeleteConversation` · [근거](evidence:db-pg-access-conversations-d417c9cf5e) | `write` / `DELETE` | L208 `DELETE` `DELETE FROM conversations WHERE id=$1` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.DeleteConversations` · [근거](evidence:db-pg-access-conversations-f5704eb599) | `write` / `DELETE` | L218 `DELETE` `DELETE FROM conversations WHERE id=ANY($1::bigint[]) RETURNING id` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.GetConversation` · [근거](evidence:db-pg-access-conversations-c1685f5ce7) | `read` / `FROM` | L162 `FROM` `SELECT id, agent_key, title, llm_profile_id, pinned_at, created_at, updated_at FROM conversations WHERE id=$1` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ListConversations` · [근거](evidence:db-pg-access-conversations-214467f5b3) | `read` / `FROM` | L143 `FROM` `SELECT id, agent_key, title, llm_profile_id, pinned_at, created_at, updated_at FROM conversations ORDER BY (pinned_at IS NOT NULL) DESC, pinned_at DESC NULLS LAST, updated_at DESC, id DESC` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.TouchConversation` · [근거](evidence:db-pg-access-conversations-4ec73135dc) | `write` / `UPDATE` | L202 `UPDATE` `UPDATE conversations SET updated_at=now() WHERE id=$1` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.UpdateConversation` · [근거](evidence:db-pg-access-conversations-6051c0ff45) | `write` / `UPDATE` | L175 `UPDATE` `UPDATE conversations SET title = CASE WHEN $2::boolean THEN $3 ELSE title END, pinned_at = CASE WHEN $4::boolean IS NULL THEN pinned_at WHEN $4::boolean THEN COALESCE(pinned_at, now()) ELSE NULL END WHERE id=$1 RETURNING id, agent_key, titl…` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.UpdateConversationProfile` · [근거](evidence:db-pg-access-conversations-59979d518a) | `read,write` / `FROM,UPDATE` | L125 `FROM` `SELECT id FROM conversations WHERE id=$1 FOR UPDATE`<br>L135 `UPDATE` `UPDATE conversations SET llm_profile_id=$2 WHERE id=$1` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-conversations-81cb174e25) | `write` / `INSERT` | L104 `INSERT` `INSERT INTO conversations(agent_key,title) VALUES ($1,$2) RETURNING id, agent_key, title, llm_profile_id, pinned_at, created_at, updated_at` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/intercept.go::DB.ListAllIntercepts` · [근거](evidence:db-pg-access-conversations-b25362de8d) | `read` / `JOIN` | L271 `JOIN` `…c.agent_key,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id ORDER BY ip.created_at DESC LIMIT $1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListTaskIntercepts` · [근거](evidence:db-pg-access-conversations-1a92e109bd) | `read` / `JOIN` | L301 `JOIN` `…c.agent_key,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.task_id=$1 ORDER BY ip.created_at DESC` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept_detail.go::DB.GetInterceptDetail` · [근거](evidence:db-pg-access-conversations-6abd6be28f) | `read` / `JOIN` | L55 `JOIN` `…y,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name, ip.audit FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/side_questions.go::lockSideParent` · [근거](evidence:db-pg-access-conversations-6d2a3c32c4) | `read` / `FROM` | L23 `FROM` `SELECT id FROM conversations WHERE id=$1 FOR SHARE` | [`feature-side-question`](../../features/human-control.md#side-question) |

**처분** · located production table-symbol binding 15개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-conversation-activities"></a>
## `conversation_activities`

[conversation_activities 물리 객체](agent-runtime.md#table-conversation-activities) · [field 의미](semantic-catalog.md#semantic-conversation-activities)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/conversation.go::DB.AppendConvActivity` · [근거](evidence:db-pg-access-conversation-activities-3f4eca7777) | `write` / `INSERT` | L239 `INSERT` `INSERT INTO conversation_activities(conversation_id, worker, kind, tool, tool_use_id, is_error, summary, detail, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens) VALUES ($1,NULLIF($2,''),NULLIF($3,''),NULLIF($4,''),NULLIF($5,''),$6,NULL…` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ConvActivityDetail` · [근거](evidence:db-pg-access-conversation-activities-45b2c82ce4) | `read` / `FROM` | L322 `FROM` `SELECT detail FROM conversation_activities WHERE id=$1 AND conversation_id=$2` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ConvActivityList` · [근거](evidence:db-pg-access-conversation-activities-9bb8fab700) | `read` / `FROM` | L254 `FROM` `…OALESCE(summary,''), created_at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens FROM conversation_activities WHERE conversation_id=$1 AND id>$2 ORDER BY id LIMIT $3` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ConvActivityPage` · [근거](evidence:db-pg-access-conversation-activities-09c880565f) | `read` / `FROM` | L287 `FROM` `…OALESCE(summary,''), created_at, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens FROM conversation_activities WHERE conversation_id=$1 AND ($2 <= 0 OR id < $2) ORDER BY id DESC LIMIT $3` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/conversation.go::DB.ConversationTokenSummaries` · [근거](evidence:db-pg-access-conversation-activities-fcdd10043e) | `read` / `JOIN` | L23 `JOIN` `…ESCE(sum(ca.cache_read_tokens),0), COALESCE(sum(ca.cache_write_tokens),0) FROM conversations c LEFT JOIN conversation_activities ca ON ca.conversation_id = c.id AND ca.kind = 'result' GROUP BY c.id` | [`feature-standalone-chat`](../../features/human-control.md#standalone-chat) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-conversation-activities-3edc66dd8f) | `write` / `INSERT` | L115 `INSERT` `INSERT INTO conversation_activities(conversation_id,worker,kind,summary,detail) VALUES ($1,$2,'user',$3,$4)` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/intercept_execution.go::DB.GetInterceptExecution` · [근거](evidence:db-pg-access-conversation-activities-92d657b267) | `read` / `FROM` | L37 `FROM` `…'), kind, COALESCE(tool,''), tool_use_id, is_error, COALESCE(summary,''), created_at, NULL::integer FROM conversation_activities WHERE conversation_id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |

**처분** · located production table-symbol binding 7개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-agent-triggers"></a>
## `agent_triggers`

[agent_triggers 물리 객체](agent-runtime.md#table-agent-triggers) · [field 의미](semantic-catalog.md#semantic-agent-triggers)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/triggers.go::DB.CreateTrigger` · [근거](evidence:db-pg-access-agent-triggers-e7cffdb6af) | `write` / `INSERT` | L69 `INSERT` `INSERT INTO agent_triggers(agent_key, enabled, interval_sec, on_finding, on_goal_met, on_task_timeout, on_tool_call, on_task_create, interval_message, finding_message, goal_message, task_timeout_message, tool_call_message, task_create_message, to…` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.DeleteTrigger` · [근거](evidence:db-pg-access-agent-triggers-4f1215e4e4) | `write` / `DELETE` | L87 `DELETE` `DELETE FROM agent_triggers WHERE id=$1` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.DeleteTriggersForAgent` · [근거](evidence:db-pg-access-agent-triggers-08c83ee12f) | `write` / `DELETE` | L126 `DELETE` `DELETE FROM agent_triggers WHERE agent_key=$1` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.ListEnabledTriggers` · [근거](evidence:db-pg-access-agent-triggers-f4f5758080) | `read` / `FROM` | L98 `FROM` `FROM agent_triggers WHERE enabled ORDER BY id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.ListTriggersFor` · [근거](evidence:db-pg-access-agent-triggers-2eac449fb3) | `read` / `FROM` | L93 `FROM` `FROM agent_triggers WHERE agent_key=$1 ORDER BY id` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.TouchTriggerFire` · [근거](evidence:db-pg-access-agent-triggers-3d5026e056) | `write` / `UPDATE` | L120 `UPDATE` `UPDATE agent_triggers SET last_fire=now() WHERE id=$1` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.UpdateTrigger` · [근거](evidence:db-pg-access-agent-triggers-6011431a2f) | `write` / `UPDATE` | L79 `UPDATE` `UPDATE agent_triggers SET enabled=$2, interval_sec=$3, on_finding=$4, on_goal_met=$5, on_task_timeout=$6, on_tool_call=$7, on_task_create=$8, interval_message=$9, finding_message=$10, goal_message=$11, task_timeout_message=$12, tool_call_mes…` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |

**처분** · located production table-symbol binding 7개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-scheduler-state"></a>
## `scheduler_state`

[scheduler_state 물리 객체](agent-runtime.md#table-scheduler-state) · [field 의미](semantic-catalog.md#semantic-scheduler-state)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/triggers.go::DB.GetSchedState` · [근거](evidence:db-pg-access-scheduler-state-cdc14b3c66) | `read` / `FROM` | L134 `FROM` `SELECT value FROM scheduler_state WHERE key=$1` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |
| `db/triggers.go::DB.SetSchedState` · [근거](evidence:db-pg-access-scheduler-state-63e24e7f23) | `write` / `INSERT` | L142 `INSERT` `INSERT INTO scheduler_state(key,value) VALUES ($1,$2) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value` | [`feature-agent-triggers`](../../features/human-control.md#agent-triggers) |

**처분** · located production table-symbol binding 2개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-intercept-rules"></a>
## `intercept_rules`

[intercept_rules 물리 객체](findings-operations.md#table-intercept-rules) · [field 의미](semantic-catalog.md#semantic-intercept-rules)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/db.go::DB.seedDefaultInterceptRules` · [근거](evidence:db-pg-access-intercept-rules-e8c17cb440) | `write` / `INSERT` | L509 `INSERT` `INSERT INTO intercept_rules(name, enabled, priority, match_target, match_type, pattern, action, message, timeout_enabled, timeout_seconds, timeout_action) VALUES ($1, true, $2, $3, $4, $5, $6, $7, false, 60, 'deny') ON CONFLICT DO NOTHING` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/db.go::DB.seedDefaultInterceptRulesV2` · [근거](evidence:db-pg-access-intercept-rules-0df7705bea) | `write` / `INSERT` | L558 `INSERT` `INSERT INTO intercept_rules(name, enabled, priority, match_target, match_type, pattern, action, message, timeout_enabled, timeout_seconds, timeout_action) VALUES ($1, $2, $3, 'tool_input', 'regex', $4, $5, $6, false, 60, 'deny') ON CONFLICT DO NOT…` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/db.go::DB.seedDefaultInterceptRulesV3` · [근거](evidence:db-pg-access-intercept-rules-f298b1fcb4) | `read,write` / `FROM,INSERT` | L591 `FROM` `…T $1, true, 80, 'tool_input', 'regex', $2, 'deny', $3, false, 60, 'deny' WHERE NOT EXISTS (SELECT 1 FROM intercept_rules WHERE name = $1)`<br>L591 `INSERT` `INSERT INTO intercept_rules(name, enabled, priority, match_target, match_type, pattern, action, message, timeout_enabled, timeout_seconds, timeout_action) SELECT $1, true, 80, 'tool_input', 'regex', $2, 'deny', $3, false, 60, 'deny' WHERE NOT EXIS…` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.CreateInterceptRule` · [근거](evidence:db-pg-access-intercept-rules-a79fbc6429) | `write` / `INSERT` | L76 `INSERT` `INSERT INTO intercept_rules(name, enabled, priority, match_target, match_type, pattern, action, message, timeout_enabled, timeout_seconds, timeout_action) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, name, enabled, priority,…` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.DeleteInterceptRule` · [근거](evidence:db-pg-access-intercept-rules-accf9f668f) | `write` / `DELETE` | L99 `DELETE` `DELETE FROM intercept_rules WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListAllIntercepts` · [근거](evidence:db-pg-access-intercept-rules-c7987f8723) | `read` / `JOIN` | L271 `JOIN` `… AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id ORDER BY ip.created_at DESC LIMIT $1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListInterceptRules` · [근거](evidence:db-pg-access-intercept-rules-4d227a0c05) | `read` / `FROM` | L58 `FROM` `… pattern, action, message, timeout_enabled, timeout_seconds, timeout_action, created_at, updated_at FROM intercept_rules ORDER BY priority DESC, id` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListTaskIntercepts` · [근거](evidence:db-pg-access-intercept-rules-b7dff7dc43) | `read` / `JOIN` | L301 `JOIN` `… AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.task_id=$1 ORDER BY ip.created_at DESC` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ToggleInterceptRule` · [근거](evidence:db-pg-access-intercept-rules-e0526c89b1) | `write` / `UPDATE` | L105 `UPDATE` `UPDATE intercept_rules SET enabled=$2 WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.UpdateInterceptRule` · [근거](evidence:db-pg-access-intercept-rules-4a0a98fe63) | `write` / `UPDATE` | L86 `UPDATE` `UPDATE intercept_rules SET name=$2, enabled=$3, priority=$4, match_target=$5, match_type=$6, pattern=$7, action=$8, message=$9, timeout_enabled=$10, timeout_seconds=$11, timeout_action=$12 WHERE id=$1 RETURNING id, name, enabled, priority, ma…` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept_detail.go::DB.GetInterceptDetail` · [근거](evidence:db-pg-access-intercept-rules-b4f161c3ec) | `read` / `JOIN` | L55 `JOIN` `…ame, ip.audit FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |

**처분** · located production table-symbol binding 11개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-intercept-pending"></a>
## `intercept_pending`

[intercept_pending 물리 객체](findings-operations.md#table-intercept-pending) · [field 의미](semantic-catalog.md#semantic-intercept-pending)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/intercept.go::DB.CreateDecidedIntercept` · [근거](evidence:db-pg-access-intercept-pending-bc8634fbe9) | `write` / `INSERT` | L167 `INSERT` `INSERT INTO intercept_pending(rule_id, conversation_id, task_id, agent_name, tool_name, tool_input, status, reason, decided_at, decision_source, audit) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), $9, $10) RETURNING id` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.CreateInterceptPending` · [근거](evidence:db-pg-access-intercept-pending-5c1782648d) | `write` / `INSERT` | L131 `INSERT` `INSERT INTO intercept_pending(rule_id, conversation_id, task_id, agent_name, tool_name, tool_input, reason, decision_source, audit) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.DecideInterceptPending` · [근거](evidence:db-pg-access-intercept-pending-081cfd8d26) | `write` / `UPDATE` | L140 `UPDATE` `UPDATE intercept_pending SET status=$2, decided_at=NOW() WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.GetInterceptPending` · [근거](evidence:db-pg-access-intercept-pending-0d5fe02916) | `read` / `FROM` | L203 `FROM` `…task_id, agent_name, tool_name, tool_input, status, reason, decided_at, created_at, decision_source FROM intercept_pending WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListAllIntercepts` · [근거](evidence:db-pg-access-intercept-pending-5320363648) | `read` / `FROM` | L271 `FROM` `…le,'') AS conv_title, COALESCE(c.agent_key,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id ORDER BY ip.created_at DESC LIMIT $1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListPendingIntercepts` · [근거](evidence:db-pg-access-intercept-pending-601e88ff73) | `read` / `FROM` | L183 `FROM` `…task_id, agent_name, tool_name, tool_input, status, reason, decided_at, created_at, decision_source FROM intercept_pending WHERE status='pending' ORDER BY created_at DESC` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.ListTaskIntercepts` · [근거](evidence:db-pg-access-intercept-pending-b596c420be) | `read` / `FROM` | L301 `FROM` `…le,'') AS conv_title, COALESCE(c.agent_key,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.task_id=$1 ORDER BY ip.created_at DESC` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept.go::DB.listInterceptsPage` · [근거](evidence:db-pg-access-intercept-pending-1e9d6804d6) | `read` / `FROM` | L350 `FROM` `SELECT COUNT(*) FROM intercept_pending ip` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept_detail.go::DB.CompleteIntercept` · [근거](evidence:db-pg-access-intercept-pending-ea60f9dc96) | `write` / `UPDATE` | L109 `UPDATE` `UPDATE intercept_pending SET audit=audit \|\| $4::jsonb WHERE id=$1 AND audit->>'run_id'=$2 AND audit->>'tool_use_id'=$3 AND audit->>'effective_action'='allow' AND audit->>'execution_status'='awaiting_result'` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept_detail.go::DB.GetInterceptDetail` · [근거](evidence:db-pg-access-intercept-pending-34a458a45b) | `read` / `FROM` | L55 `FROM` `…conv_title, COALESCE(c.agent_key,'') AS conv_agent_key, COALESCE(ir.name,'') AS rule_name, ip.audit FROM intercept_pending ip LEFT JOIN conversations c ON c.id = ip.conversation_id LEFT JOIN intercept_rules ir ON ir.id = ip.rule_id WHERE ip.id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/intercept_detail.go::DB.ResolveIntercept` · [근거](evidence:db-pg-access-intercept-pending-d03eb247c8) | `write` / `UPDATE` | L87 `UPDATE` `UPDATE intercept_pending SET status=$2, decided_at=NOW(), audit=CASE WHEN audit IS NULL THEN NULL ELSE audit \|\| $3::jsonb \|\| CASE WHEN $4='allow' AND audit->>'correlation' IS DISTINCT FROM 'exact' THEN '{"execution_status":"unknown"}'::jsonb EL…` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-intercept-pending-82c3ebdd3e) | `read` / `FROM` | L596 `FROM` `source fragment: SELECT * FROM intercept_pending WHERE COALESCE(task_id,'')=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-intercept-pending-9b2baa67ed) | `write` / `DELETE` | L67 `DELETE` `DELETE FROM intercept_pending WHERE COALESCE(task_id,'')=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::restoreInterceptRows` · [근거](evidence:db-pg-access-intercept-pending-5fc302ab64) | `write` / `INSERT` | L703 `INSERT` `INSERT INTO intercept_pending SELECT * FROM json_populate_recordset(NULL::intercept_pending,$1::json)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 14개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-findings"></a>
## `findings`

[findings 물리 객체](findings-operations.md#table-findings) · [field 의미](semantic-catalog.md#semantic-findings)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/chat_mentions.go::DB.SearchChatMentionsPage` · [근거](evidence:db-pg-access-findings-f291f39a91) | `read` / `FROM` | L69 `FROM` `…me,''), vulnclass) AS label, concat_ws(' · ', severity, status, left(summary, 160)) AS description FROM findings WHERE ($1='' OR $1='finding') AND ($2='' OR id::text=$2 OR concat_ws(' ',name,vulnclass,summary) ILIKE $3) AND ($4::bigint=0 OR (id::text=$2)<$6 OR ((id::text=$2)=$6 AND (id<$4 OR (id=$4 AND 'finding'>$5)))) ORDER BY (i…` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/exploration.go::DB.TaskListMetricsAll` · [근거](evidence:db-pg-access-findings-3260bd8afb) | `read` / `FROM` | L1313 `FROM` `… COUNT(*) FILTER (WHERE severity='medium') AS medium, COUNT(*) FILTER (WHERE severity='low') AS low FROM findings WHERE task_id=task.id ) finding_metrics ON true WHERE task.deleted_at IS NULL` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/exploration.go::ExplorationStore.CancelIntent` · [근거](evidence:db-pg-access-findings-03a3b0fd14) | `write` / `DELETE` | L577 `DELETE` `DELETE FROM findings WHERE node_id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_assets.go::DB.buildFindingAssetTree` · [근거](evidence:db-pg-access-findings-1448180e23) | `read` / `FROM` | L143 `FROM` `SELECT COALESCE(f.severity,''), f.created_at, COALESCE(f.asset_ids::text,'[]') FROM findings f LEFT JOIN tasks t ON f.task_id = t.id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-findings-e489fd8709) | `read` / `FROM` | L85 `FROM` `…onstraints c JOIN tasks t ON t.exploration_id=c.exploration_id WHERE t.id=f.task_id), '[]'::jsonb)) FROM findings f WHERE f.id=$1 FOR UPDATE OF f` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.FinishFindingRetest` · [근거](evidence:db-pg-access-findings-bc19beb437) | `read` / `FROM` | L221 `FROM` `SELECT f.id FROM findings f WHERE f.id=(SELECT finding_id FROM finding_retests WHERE id=$1) FOR UPDATE OF f` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_traffic.go::DB.FindingIDByNodeID` · [근거](evidence:db-pg-access-findings-0fed5e5c52) | `read` / `FROM` | L418 `FROM` `SELECT id FROM findings WHERE node_id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::DB.SetFindingReportVersionByNodeID` · [근거](evidence:db-pg-access-findings-4d5f2daace) | `read,write` / `FROM,UPDATE` | L459 `FROM` `SELECT id FROM findings WHERE node_id=$1`<br>L468 `UPDATE` `UPDATE findings SET report=$2,report_evidence_version=COALESCE($3::bigint,CASE WHEN evidence_version=0 THEN 0 ELSE -1 END) WHERE id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::ExplorationStore.PopulateFindingTrafficIDs` · [근거](evidence:db-pg-access-findings-c8b270380f) | `read` / `FROM` | L439 `FROM` `SELECT f.id,f.node_id,(SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id) FROM findings f WHERE f.node_id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::FindingTrafficTx` · [근거](evidence:db-pg-access-findings-87401ddbde) | `read` / `FROM` | L245 `FROM` `SELECT evidence_version,report_evidence_version FROM findings WHERE id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::LockFindingEvidenceTx` · [근거](evidence:db-pg-access-findings-6db51be95d) | `read` / `FROM` | L165 `FROM` `SELECT task_id FROM findings WHERE id=$1`<br>L175 `FROM` `SELECT evidence_version FROM findings WHERE id=$1 FOR UPDATE` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::RecordFindingTx` · [근거](evidence:db-pg-access-findings-7140513ea2) | `write` / `INSERT` | L385 `INSERT` `INSERT INTO findings(task_id,node_id,vulnclass,name,severity,summary,evidence,worker,asset_ids) VALUES(NULLIF($1,0),$2,$3,$4,$5,$6,$7,$8,$9) RETURNING id` | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/finding_traffic.go::bumpEvidenceVersionTx` · [근거](evidence:db-pg-access-findings-010d96436e) | `write` / `UPDATE` | L239 `UPDATE` `UPDATE findings SET evidence_version=evidence_version+1 WHERE id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic_archive.go::restoreFindingTrafficTx` · [근거](evidence:db-pg-access-findings-7071b5d232) | `read` / `FROM` | L55 `FROM` `SELECT EXISTS(SELECT 1 FROM findings WHERE id=$1 AND task_id=$2)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/findings.go::DB.AddFinding` · [근거](evidence:db-pg-access-findings-b70464a687) | `write` / `INSERT` | L96 `INSERT` `INSERT INTO findings (task_id, node_id, vulnclass, name, severity, summary, evidence, worker, asset_ids) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.DeleteFinding` · [근거](evidence:db-pg-access-findings-a128b54e11) | `write` / `DELETE` | L667 `DELETE` `DELETE FROM findings WHERE id=$1 RETURNING node_id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.DeleteFindingsByTask` · [근거](evidence:db-pg-access-findings-57d61c0f23) | `write` / `DELETE` | L685 `DELETE` `DELETE FROM findings WHERE task_id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.FindingMetaByNodeID` · [근거](evidence:db-pg-access-findings-fdeea392af) | `read` / `FROM` | L777 `FROM` `…ding'), asset_ids, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=findings.id) FROM findings WHERE task_id=$1 AND node_id IS NOT NULL` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.FindingStats` · [근거](evidence:db-pg-access-findings-4ed6d9e96d) | `read` / `FROM` | L552 `FROM` `…ty = 'high'), COUNT(*) FILTER (WHERE severity = 'medium'), COUNT(*) FILTER (WHERE severity = 'low') FROM findings`<br>L563 `FROM` `SELECT DISTINCT vulnclass FROM findings WHERE vulnclass <> '' ORDER BY vulnclass`<br>L580 `FROM` `SELECT f.task_id, COALESCE(t.name, ''), COALESCE(t.description, ''), COUNT(*) FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.task_id IS NOT NULL GROUP BY f.task_id, t.name, t.description ORDER BY MAX(f.created_at) DESC` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.GetFinding` · [근거](evidence:db-pg-access-findings-800bee206e) | `read` / `FROM` | L636 `FROM` `…, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id), COALESCE(f.report, '') FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.id = $1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingGroups` · [근거](evidence:db-pg-access-findings-eb44c224ac) | `read` / `FROM` | L311 `FROM` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id=t.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindings` · [근거](evidence:db-pg-access-findings-2f5cbab72c) | `read` / `FROM` | L136 `FROM` `….report_evidence_version, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id) FROM findings f LEFT JOIN tasks t ON f.task_id = t.id ORDER BY f.created_at DESC LIMIT $1`<br>L137 `FROM` `FROM findings f LEFT JOIN tasks t ON f.task_id = t.id ORDER BY f.created_at DESC LIMIT $1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingsForExport` · [근거](evidence:db-pg-access-findings-cf57444365) | `read` / `FROM` | L484 `FROM` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.id IN ( <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L495 `FROM` `source fragment: FROM findings f LEFT JOIN tasks t ON f.task_id = t.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.ListFindingsPage` · [근거](evidence:db-pg-access-findings-314660f4d9) | `read` / `FROM` | L250 `FROM` `source fragment: SELECT COUNT(*) FROM findings f LEFT JOIN tasks t ON f.task_id=t.id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L265 `FROM` `source fragment: SELECT %s FROM findings f LEFT JOIN tasks t ON f.task_id = t.id%s ORDER BY %s LIMIT $%d OFFSET $%d <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.SetFindingStatus` · [근거](evidence:db-pg-access-findings-26168954bb) | `write` / `UPDATE` | L698 `UPDATE` `UPDATE findings SET status=$1 WHERE id=$2` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/findings.go::DB.setFindingCol` · [근거](evidence:db-pg-access-findings-c57898f68d) | `write` / `UPDATE` | L720 `UPDATE` `source fragment: UPDATE findings SET <trusted allowlist: severity\|name\|vulnclass>=$1 WHERE id=$2 RETURNING node_id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-tx`](../../features/findings-evidence.md#finding-transaction) |
| `db/findings.go::ExplorationStore.AddFindingFollowUpIntent` · [근거](evidence:db-pg-access-findings-3beb305938) | `read` / `FROM` | L382 `FROM` `SELECT n.id FROM findings f JOIN tasks t ON t.id=f.task_id JOIN exploration_nodes n ON n.id=f.node_id AND n.exploration_id=t.exploration_id WHERE f.id=$1 AND f.node_id=$2 AND t.exploration_id=$3 AND n.kind='finding' FOR SHARE OF f, t, n` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::SetFindingStatusTx` · [근거](evidence:db-pg-access-findings-c7176e8663) | `read,write` / `FROM,UPDATE` | L489 `FROM` `SELECT vulnclass, name, severity, summary, task_id, asset_ids, status FROM findings WHERE id=$1 FOR UPDATE`<br>L504 `UPDATE` `UPDATE findings SET status=$2 WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-findings-a03f5a91cf) | `read` / `FROM,JOIN` | L589 `FROM` `source fragment: SELECT * FROM findings WHERE task_id=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L590 `JOIN` `source fragment: SELECT b.* FROM finding_traffic_bindings b JOIN findings f ON f.id=b.finding_id WHERE f.task_id=$1 ORDER BY b.finding_id,b.position,b.id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L591 `JOIN` `source fragment: SELECT s.* FROM traffic_evidence_snapshots s WHERE EXISTS(SELECT 1 FROM finding_traffic_bindings b JOIN findings f ON f.id=b.finding_id WHERE b.snapshot_id=s.id AND f.task_id=$1) ORDER BY s.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::archiveAssetIDsQuery` · [근거](evidence:db-pg-access-findings-b9b653ba29) | `read` / `FROM` | L529 `FROM` `…ration_nodes node ON node.id=anchor.node_id WHERE node.exploration_id=$2 UNION SELECT value::bigint FROM findings finding CROSS JOIN LATERAL jsonb_array_elements_text( CASE WHEN jsonb_typeof(finding.asset_ids)='array' THEN finding.asset_ids ELSE '[]'::jsonb END ) value WHERE finding.task_id=$1 AND value ~ '^[0-9]+$'` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::taskArchiveAggregates` · [근거](evidence:db-pg-access-findings-76d247fd15) | `read` / `FROM` | L753 `FROM` `…bject_agg(name,n),'{}'::jsonb) FROM (SELECT COALESCE(NULLIF(severity,''),'unknown') name,count(*) n FROM findings WHERE task_id=$1 GROUP BY severity) x`<br>L754 `FROM` `…'), 'vulnclasses',COALESCE(jsonb_agg(DISTINCT vulnclass) FILTER (WHERE vulnclass<>''),'[]'::jsonb)) FROM findings WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-findings-076101d0cc) | `write` / `DELETE` | L84 `DELETE` `DELETE FROM findings WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-findings-6741a035f8) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-findings-d36ee17ecc) | `write` / `DELETE` | L632 `DELETE` `DELETE FROM findings WHERE task_id = $1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `evidence/store.go::Store.StageFindingsExport` · [근거](evidence:db-pg-access-findings-ef093855e8) | `read` / `FROM` | L132 `FROM` `SELECT report FROM findings WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 35개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-finding-retests"></a>
## `finding_retests`

[finding_retests 물리 객체](findings-operations.md#table-finding-retests) · [field 의미](semantic-catalog.md#semantic-finding-retests)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/finding_retests.go::DB.CreateFindingRetest` · [근거](evidence:db-pg-access-finding-retests-298bb9a6ef) | `read,write` / `FROM,INSERT` | L93 `FROM` `…versation_id, status, verdict, notes, summary, evidence, error, created_at, started_at, finished_at FROM finding_retests WHERE finding_id=$1 AND status IN ('pending','running')`<br>L109 `INSERT` `INSERT INTO finding_retests(finding_id,conversation_id,notes,snapshot) VALUES ($1,$2,$3,$4) RETURNING id, finding_id, conversation_id, status, verdict, notes, summary, evidence, error, created_at, started_at, finished_at` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.FailPendingRetestForConversation` · [근거](evidence:db-pg-access-finding-retests-a5efabf7fd) | `write` / `UPDATE` | L167 `UPDATE` `UPDATE finding_retests SET status='failed', error=$2, finished_at=now() WHERE conversation_id=$1 AND status IN ('pending','running')` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.FindingRetestForConversation` · [근거](evidence:db-pg-access-finding-retests-9dbf54a7a4) | `read` / `FROM` | L152 `FROM` `…versation_id, status, verdict, notes, summary, evidence, error, created_at, started_at, finished_at FROM finding_retests WHERE conversation_id=$1`<br>L156 `FROM` `SELECT snapshot FROM finding_retests WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.FinishFindingRetest` · [근거](evidence:db-pg-access-finding-retests-fe65aab8c2) | `read,write` / `FROM,UPDATE` | L221 `FROM` `SELECT f.id FROM findings f WHERE f.id=(SELECT finding_id FROM finding_retests WHERE id=$1) FOR UPDATE OF f`<br>L229 `UPDATE` `UPDATE finding_retests SET status=CASE WHEN $2='completed' AND verdict='' THEN 'failed' ELSE $2 END, error=CASE WHEN $2='completed' AND verdict='' THEN 'Agent 未保存复测结论，请查看会话后重新复测' ELSE $3 END, finished_at=no…` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.ListActiveFindingRetests` · [근거](evidence:db-pg-access-finding-retests-bd3b2be0d1) | `read` / `FROM` | L47 `FROM` `SELECT id, finding_id, conversation_id, status FROM finding_retests WHERE status IN ('pending','running') AND conversation_id IS NOT NULL ORDER BY id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.ListFindingRetests` · [근거](evidence:db-pg-access-finding-retests-393582fb9c) | `read` / `FROM` | L135 `FROM` `…versation_id, status, verdict, notes, summary, evidence, error, created_at, started_at, finished_at FROM finding_retests WHERE finding_id=$1 ORDER BY id DESC` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.RecordFindingRetestResult` · [근거](evidence:db-pg-access-finding-retests-188dbd8971) | `write` / `UPDATE` | L194 `UPDATE` `UPDATE finding_retests SET verdict=$2,summary=$3,evidence=$4 WHERE conversation_id=$1 AND status='running' AND (verdict='' OR (verdict=$2 AND summary=$3 AND evidence=$4))` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.RecoverFindingRetests` · [근거](evidence:db-pg-access-finding-retests-06180af265) | `write` / `UPDATE` | L257 `UPDATE` `UPDATE finding_retests SET status='stopped', error='服务重启，复测已中断，请重新发起', finished_at=now() WHERE status IN ('pending','running')` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/finding_retests.go::DB.StartFindingRetest` · [근거](evidence:db-pg-access-finding-retests-c2e0c8aed6) | `write` / `UPDATE` | L173 `UPDATE` `UPDATE finding_retests SET status='running', started_at=now() WHERE id=$1 AND status='pending'` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 9개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-traffic-evidence-snapshots"></a>
## `traffic_evidence_snapshots`

[traffic_evidence_snapshots 물리 객체](findings-operations.md#table-traffic-evidence-snapshots) · [field 의미](semantic-catalog.md#semantic-traffic-evidence-snapshots)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/finding_traffic.go::AddFindingTrafficTx` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-440ef2360f) | `write` / `UPDATE` | L215 `UPDATE` `UPDATE traffic_evidence_snapshots SET unreferenced_at=NULL WHERE id=$1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::FindingTrafficTx` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-52431e10a6) | `read` / `JOIN` | L251 `JOIN` `…_id,b.snapshot_id,b.role,b.note,b.position,b.created_at,to_jsonb(s) FROM finding_traffic_bindings b JOIN traffic_evidence_snapshots s ON s.id=b.snapshot_id WHERE b.finding_id=$1 ORDER BY b.position,b.id` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::InsertEvidenceSnapshotTx` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-73a114ef04) | `write` / `INSERT` | L198 `INSERT` `INSERT INTO traffic_evidence_snapshots (id,source_traffic_id,captured_at,url,method,status,content_type,req_head,resp_head,req_hash,resp_hash,req_len,resp_len,created_at) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14) ON CONFLICT(id) DO NOTHING` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic_archive.go::restoreFindingTrafficTx` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-7c615da87f) | `write` / `UPDATE` | L67 `UPDATE` `UPDATE traffic_evidence_snapshots s SET unreferenced_at=NULL WHERE EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-282a93d25a) | `read` / `FROM` | L591 `FROM` `source fragment: SELECT s.* FROM traffic_evidence_snapshots s WHERE EXISTS(SELECT 1 FROM finding_traffic_bindings b JOIN findings f ON f.id=b.finding_id WHERE b.snapshot_id=s.id AND f.task_id=$1) ORDER BY s.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `evidence/store.go::Store.Collect` · [근거](evidence:db-pg-access-traffic-evidence-snapshots-364a62b0c1) | `read,write` / `DELETE,FROM,UPDATE` | L349 `UPDATE` `UPDATE traffic_evidence_snapshots s SET unreferenced_at=$1 WHERE unreferenced_at IS NULL AND NOT EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)`<br>L353 `DELETE` `DELETE FROM traffic_evidence_snapshots s WHERE unreferenced_at<$1 AND NOT EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)`<br>L357 `FROM` `SELECT req_hash FROM traffic_evidence_snapshots UNION SELECT resp_hash FROM traffic_evidence_snapshots` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-finding-traffic-bindings"></a>
## `finding_traffic_bindings`

[finding_traffic_bindings 물리 객체](findings-operations.md#table-finding-traffic-bindings) · [field 의미](semantic-catalog.md#semantic-finding-traffic-bindings)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/finding_traffic.go::AddFindingTrafficTx` · [근거](evidence:db-pg-access-finding-traffic-bindings-5728bd167b) | `read,write` / `FROM,INSERT` | L207 `FROM` `SELECT COALESCE(MAX(position)+1,0) FROM finding_traffic_bindings WHERE finding_id=$1`<br>L218 `INSERT` `INSERT INTO finding_traffic_bindings(finding_id,snapshot_id,role,note,position) VALUES($1,$2,$3,$4,$5) ON CONFLICT(finding_id,snapshot_id) DO NOTHING` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::DB.EditFindingTraffic` · [근거](evidence:db-pg-access-finding-traffic-bindings-e927eacd9e) | `write` / `DELETE,UPDATE` | L301 `UPDATE` `UPDATE finding_traffic_bindings SET position=$1 WHERE finding_id=$2 AND id=$3`<br>L309 `DELETE` `DELETE FROM finding_traffic_bindings WHERE finding_id=$1 AND id=$2`<br>L311 `UPDATE` `UPDATE finding_traffic_bindings SET role=COALESCE($3,role),note=COALESCE($4,note) WHERE finding_id=$1 AND id=$2` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::ExplorationStore.PopulateFindingTrafficIDs` · [근거](evidence:db-pg-access-finding-traffic-bindings-b832923bf8) | `read` / `FROM` | L439 `FROM` `SELECT f.id,f.node_id,(SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id) FROM findings f WHERE f.node_id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic.go::FindingTrafficTx` · [근거](evidence:db-pg-access-finding-traffic-bindings-57db4cbc9b) | `read` / `FROM` | L251 `FROM` `SELECT b.id,b.finding_id,b.snapshot_id,b.role,b.note,b.position,b.created_at,to_jsonb(s) FROM finding_traffic_bindings b JOIN traffic_evidence_snapshots s ON s.id=b.snapshot_id WHERE b.finding_id=$1 ORDER BY b.position,b.id` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/finding_traffic_archive.go::restoreFindingTrafficTx` · [근거](evidence:db-pg-access-finding-traffic-bindings-abe00c0cea) | `read,write` / `FROM,INSERT` | L64 `INSERT` `INSERT INTO finding_traffic_bindings SELECT * FROM json_populate_recordset(NULL::finding_traffic_bindings,$1::json)`<br>L67 `FROM` `UPDATE traffic_evidence_snapshots s SET unreferenced_at=NULL WHERE EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/findings.go::DB.FindingMetaByNodeID` · [근거](evidence:db-pg-access-finding-traffic-bindings-019d6081a9) | `read` / `FROM` | L777 `FROM` `SELECT node_id, id, COALESCE(status,'pending'), asset_ids, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=findings.id) FROM findings WHERE task_id=$1 AND node_id IS NOT NULL` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/findings.go::DB.GetFinding` · [근거](evidence:db-pg-access-finding-traffic-bindings-4a01758636) | `read` / `FROM` | L636 `FROM` `…scription, '') AS task_description, f.evidence_version, f.report_evidence_version, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id), COALESCE(f.report, '') FROM findings f LEFT JOIN tasks t ON f.task_id = t.id WHERE f.id = $1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/findings.go::DB.ListFindings` · [근거](evidence:db-pg-access-finding-traffic-bindings-ec3301eeff) | `read` / `FROM` | L136 `FROM` `…scription, '') AS task_description, f.evidence_version, f.report_evidence_version, (SELECT count(*) FROM finding_traffic_bindings b WHERE b.finding_id=f.id) FROM findings f LEFT JOIN tasks t ON f.task_id = t.id ORDER BY f.created_at DESC LIMIT $1` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-finding-traffic-bindings-b08bb2bd09) | `read` / `FROM` | L590 `FROM` `source fragment: SELECT b.* FROM finding_traffic_bindings b JOIN findings f ON f.id=b.finding_id WHERE f.task_id=$1 ORDER BY b.finding_id,b.position,b.id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L591 `FROM` `source fragment: SELECT s.* FROM traffic_evidence_snapshots s WHERE EXISTS(SELECT 1 FROM finding_traffic_bindings b JOIN findings f ON f.id=b.finding_id WHERE b.snapshot_id=s.id AND f.task_id=$1) ORDER BY s.id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `evidence/store.go::Store.Collect` · [근거](evidence:db-pg-access-finding-traffic-bindings-b3482f8a30) | `read` / `FROM` | L349 `FROM` `…c_evidence_snapshots s SET unreferenced_at=$1 WHERE unreferenced_at IS NULL AND NOT EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)`<br>L353 `FROM` `DELETE FROM traffic_evidence_snapshots s WHERE unreferenced_at<$1 AND NOT EXISTS(SELECT 1 FROM finding_traffic_bindings b WHERE b.snapshot_id=s.id)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 10개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-server-logs"></a>
## `server_logs`

[server_logs 물리 객체](findings-operations.md#table-server-logs) · [field 의미](semantic-catalog.md#semantic-server-logs)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/logs.go::DB.InsertLog` · [근거](evidence:db-pg-access-server-logs-e65f653e56) | `write` / `INSERT` | L21 `INSERT` `INSERT INTO server_logs(level,tag,text) VALUES($1,$2,$3) RETURNING id` | [`module-storage-background`](../../modules/storage-runtime.md#background-loops) |
| `db/logs.go::DB.ListLogsBefore` · [근거](evidence:db-pg-access-server-logs-d11fca0e4d) | `read` / `FROM` | L56 `FROM` `SELECT id, created_at, level, tag, text FROM server_logs WHERE id < $1 ORDER BY id DESC LIMIT $2` | [`module-storage-background`](../../modules/storage-runtime.md#background-loops) |
| `db/logs.go::DB.RecentLogs` · [근거](evidence:db-pg-access-server-logs-fb5556b4c7) | `read` / `FROM` | L30 `FROM` `SELECT id, created_at, level, tag, text FROM server_logs ORDER BY id DESC LIMIT $1` | [`module-storage-background`](../../modules/storage-runtime.md#background-loops) |

**처분** · located production table-symbol binding 3개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-side-question-sessions"></a>
## `side_question_sessions`

[side_question_sessions 물리 객체](findings-operations.md#table-side-question-sessions) · [field 의미](semantic-catalog.md#semantic-side-question-sessions)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/exploration.go::ExplorationStore.CancelIntent` · [근거](evidence:db-pg-access-side-question-sessions-beefdcdbfd) | `write` / `DELETE` | L570 `DELETE` `DELETE FROM side_question_sessions WHERE intent_id=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/exploration.go::ExplorationStore.SoftDeleteIntent` · [근거](evidence:db-pg-access-side-question-sessions-27a4bb437d) | `write` / `DELETE` | L415 `DELETE` `DELETE FROM side_question_sessions WHERE intent_id=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.ClearSideHistory` · [근거](evidence:db-pg-access-side-question-sessions-a8da5d3ae6) | `write` / `UPDATE` | L227 `UPDATE` `UPDATE side_question_sessions SET generation=generation+1,memory='{}' WHERE session_key=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.ExistingSideRequest` · [근거](evidence:db-pg-access-side-question-sessions-4ea67bc037) | `read` / `FROM` | L83 `FROM` `…FROM side_question_requests WHERE session_key=$1 AND client_id=$2 AND generation=(SELECT generation FROM side_question_sessions WHERE session_key=$1)` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SaveSideMemory` · [근거](evidence:db-pg-access-side-question-sessions-97967a6843) | `write` / `UPDATE` | L273 `UPDATE` `UPDATE side_question_sessions s SET memory=$3 WHERE s.session_key=$1 AND s.generation=$2 AND EXISTS(SELECT 1 FROM side_question_requests r WHERE r.id=$4 AND r.session_key=s.session_key AND r.generation=s.generation AND r.status='running')` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SaveSideSnapshot` · [근거](evidence:db-pg-access-side-question-sessions-cde2679568) | `write` / `INSERT` | L56 `INSERT` `INSERT INTO side_question_sessions(session_key,conversation_id,task_id,exploration_id,intent_id,run_id,version,snapshot) VALUES($1,$2,$3,$4,$5,$6,$7,$8) ON CONFLICT(session_key) DO UPDATE SET run_id=EXCLUDED.run_id,version=EXCLUDED.version,snapshot=EXCLU…` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideMemory` · [근거](evidence:db-pg-access-side-question-sessions-6149530f35) | `read` / `FROM` | L239 `FROM` `SELECT s.memory FROM side_question_sessions s JOIN side_question_requests r ON r.session_key=s.session_key WHERE r.id=$1 AND r.generation=s.generation AND s.generation=$2 AND r.status='running'` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideSnapshot` · [근거](evidence:db-pg-access-side-question-sessions-957b1e871e) | `read` / `FROM` | L68 `FROM` `SELECT snapshot FROM side_question_sessions WHERE session_key=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.StartSideRequest` · [근거](evidence:db-pg-access-side-question-sessions-93e8d0b365) | `read` / `FROM` | L170 `FROM` `SELECT generation FROM side_question_sessions WHERE session_key=$1 FOR UPDATE` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.UpdateSideRequest` · [근거](evidence:db-pg-access-side-question-sessions-1e41caa46d) | `read` / `FROM` | L212 `FROM` `…usage=$6,context_info=$7 WHERE r.id=$1 AND r.status='running' AND r.sequence<$5 AND EXISTS(SELECT 1 FROM side_question_sessions s WHERE s.session_key=r.session_key AND s.generation=r.generation)` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-side-question-sessions-8801a31633) | `read` / `FROM,JOIN` | L597 `FROM` `source fragment: SELECT * FROM side_question_sessions WHERE task_id=$1 ORDER BY session_key <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L598 `JOIN` `source fragment: SELECT r.* FROM side_question_requests r JOIN side_question_sessions s ON s.session_key=r.session_key WHERE s.task_id=$1 ORDER BY r.ordinal <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-side-question-sessions-d5127dfa7f) | `write` / `DELETE` | L81 `DELETE` `DELETE FROM side_question_sessions WHERE task_id=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-side-question-sessions-e1e83729ca) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 13개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-side-question-requests"></a>
## `side_question_requests`

[side_question_requests 물리 객체](findings-operations.md#table-side-question-requests) · [field 의미](semantic-catalog.md#semantic-side-question-requests)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/side_questions.go::DB.ClearSideHistory` · [근거](evidence:db-pg-access-side-question-requests-a5f44ede43) | `write` / `DELETE` | L230 `DELETE` `DELETE FROM side_question_requests WHERE session_key=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.CurrentSideRequest` · [근거](evidence:db-pg-access-side-question-requests-e1a9f07799) | `read` / `FROM` | L116 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND status='running'` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.ExistingSideRequest` · [근거](evidence:db-pg-access-side-question-requests-33fa928102) | `read` / `FROM` | L83 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND client_id=$2 AND generation=(SELECT generation FROM side_question_sessions WHERE session_key=$1)` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.InterruptSideRequests` · [근거](evidence:db-pg-access-side-question-requests-9bb182569a) | `write` / `UPDATE` | L286 `UPDATE` `UPDATE side_question_requests SET status='interrupted',error='服务重启，回答已中断',sequence=sequence+1 WHERE status='running'` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SaveSideMemory` · [근거](evidence:db-pg-access-side-question-requests-90bbb7e005) | `read` / `FROM` | L273 `FROM` `…de_question_sessions s SET memory=$3 WHERE s.session_key=$1 AND s.generation=$2 AND EXISTS(SELECT 1 FROM side_question_requests r WHERE r.id=$4 AND r.session_key=s.session_key AND r.generation=s.generation AND r.status='running')` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideHistory` · [근거](evidence:db-pg-access-side-question-requests-b5400e3847) | `read` / `FROM` | L124 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND ($2::bigint=0 OR ordinal<$2) ORDER BY ordinal DESC LIMIT $3` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideMemory` · [근거](evidence:db-pg-access-side-question-requests-9556cf1f3a) | `read` / `JOIN` | L239 `JOIN` `SELECT s.memory FROM side_question_sessions s JOIN side_question_requests r ON r.session_key=s.session_key WHERE r.id=$1 AND r.generation=s.generation AND s.generation=$2 AND r.status='running'` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideReplay` · [근거](evidence:db-pg-access-side-question-requests-827040a9e8) | `read` / `FROM` | L141 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND status='completed' ORDER BY ordinal DESC LIMIT 20` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideReplayPage` · [근거](evidence:db-pg-access-side-question-requests-edb55d3298) | `read` / `FROM` | L251 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND generation=$2 AND status='completed' AND ordinal>$3 AND ordinal<$4 ORDER BY ordinal LIMIT 20` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.SideRequest` · [근거](evidence:db-pg-access-side-question-requests-6e2bc0595c) | `read` / `FROM` | L108 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE id=$1` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.StartSideRequest` · [근거](evidence:db-pg-access-side-question-requests-dcffa93c98) | `read,write` / `FROM,INSERT` | L173 `FROM` `…ion,client_id,question,answer,status,error,model,snapshot_at,created_at,sequence,usage,context_info FROM side_question_requests WHERE session_key=$1 AND generation=$2 AND client_id=$3`<br>L184 `FROM` `SELECT EXISTS(SELECT 1 FROM side_question_requests WHERE session_key=$1 AND status='running')`<br>L194 `INSERT` `INSERT INTO side_question_requests(id,session_key,generation,client_id,question,status,model,snapshot_at) VALUES($1,$2,$3,$4,$5,'running',$6,$7) RETURNING id,ordinal,session_key,generation,client_id,question,answer,status,error,model,snapshot_at,created_…` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/side_questions.go::DB.UpdateSideRequest` · [근거](evidence:db-pg-access-side-question-requests-1be6e19fcd) | `write` / `UPDATE` | L212 `UPDATE` `UPDATE side_question_requests r SET answer=$2,status=$3,error=$4,sequence=$5,usage=$6,context_info=$7 WHERE r.id=$1 AND r.status='running' AND r.sequence<$5 AND EXISTS(SELECT 1 FROM side_question_sessions s WHERE s.session_key=r.session_key AND s.ge…` | [`feature-side-question`](../../features/human-control.md#side-question) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-side-question-requests-62486f492d) | `read` / `FROM` | L598 `FROM` `source fragment: SELECT r.* FROM side_question_requests r JOIN side_question_sessions s ON s.session_key=r.session_key WHERE s.task_id=$1 ORDER BY r.ordinal <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-side-question-requests-2313c7c779) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 14개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-asset-intercept-rules"></a>
## `asset_intercept_rules`

[asset_intercept_rules 물리 객체](findings-operations.md#table-asset-intercept-rules) · [field 의미](semantic-catalog.md#semantic-asset-intercept-rules)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/asset_intercept.go::DB.CreateAssetInterceptRule` · [근거](evidence:db-pg-access-asset-intercept-rules-268b1fbdb1) | `write` / `INSERT` | L51 `INSERT` `INSERT INTO asset_intercept_rules(enabled, kind, pattern, note, builtin) VALUES ($1, $2, $3, $4, false) RETURNING id, enabled, kind, pattern, note, builtin, created_at, updated_at` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/asset_intercept.go::DB.DeleteAssetInterceptRule` · [근거](evidence:db-pg-access-asset-intercept-rules-445d96292d) | `write` / `DELETE` | L72 `DELETE` `DELETE FROM asset_intercept_rules WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/asset_intercept.go::DB.ListAssetInterceptRules` · [근거](evidence:db-pg-access-asset-intercept-rules-8e1f052eac) | `read` / `FROM` | L33 `FROM` `SELECT id, enabled, kind, pattern, note, builtin, created_at, updated_at FROM asset_intercept_rules ORDER BY builtin DESC, id DESC` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/asset_intercept.go::DB.ToggleAssetInterceptRule` · [근거](evidence:db-pg-access-asset-intercept-rules-de1d0d5f6d) | `write` / `UPDATE` | L78 `UPDATE` `UPDATE asset_intercept_rules SET enabled=$2 WHERE id=$1` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/asset_intercept.go::DB.UpdateAssetInterceptRule` · [근거](evidence:db-pg-access-asset-intercept-rules-47862794d6) | `write` / `UPDATE` | L61 `UPDATE` `UPDATE asset_intercept_rules SET enabled=$2, kind=$3, pattern=$4, note=$5 WHERE id=$1 RETURNING id, enabled, kind, pattern, note, builtin, created_at, updated_at` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/db.go::DB.seedDefaultAssetInterceptRules` · [근거](evidence:db-pg-access-asset-intercept-rules-d1098f8cc5) | `write` / `INSERT` | L292 `INSERT` `INSERT INTO asset_intercept_rules(enabled, kind, pattern, note, builtin) VALUES (true, $1, $2, $3, true) ON CONFLICT DO NOTHING` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-task-intercept-rules"></a>
## `task_intercept_rules`

[task_intercept_rules 물리 객체](findings-operations.md#table-task-intercept-rules) · [field 의미](semantic-catalog.md#semantic-task-intercept-rules)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/task_intercept.go::AssetStore.CreateTaskInterceptRule` · [근거](evidence:db-pg-access-task-intercept-rules-05a2133849) | `write` / `INSERT` | L75 `INSERT` `INSERT INTO task_intercept_rules(task_id, enabled, action, kind, pattern, note) VALUES ($1,$2,$3,$4,$5,$6) RETURNING id, enabled, action, kind, pattern, note, created_at, updated_at` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_intercept.go::AssetStore.DeleteTaskInterceptRule` · [근거](evidence:db-pg-access-task-intercept-rules-70760af03b) | `write` / `DELETE` | L97 `DELETE` `DELETE FROM task_intercept_rules WHERE id=$1 AND task_id=$2` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_intercept.go::AssetStore.ListTaskInterceptRules` · [근거](evidence:db-pg-access-task-intercept-rules-ea22772e81) | `read` / `FROM` | L33 `FROM` `SELECT id, enabled, action, kind, pattern, note, created_at, updated_at FROM task_intercept_rules WHERE task_id=$1 ORDER BY action, id` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_intercept.go::AssetStore.ToggleTaskInterceptRule` · [근거](evidence:db-pg-access-task-intercept-rules-26009d3fc6) | `write` / `UPDATE` | L107 `UPDATE` `UPDATE task_intercept_rules SET enabled=$3 WHERE id=$1 AND task_id=$2` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_intercept.go::AssetStore.UpdateTaskInterceptRule` · [근거](evidence:db-pg-access-task-intercept-rules-e10d568bcc) | `write` / `UPDATE` | L86 `UPDATE` `UPDATE task_intercept_rules SET enabled=$3, action=$4, kind=$5, pattern=$6, note=$7 WHERE id=$1 AND task_id=$2 RETURNING id, enabled, action, kind, pattern, note, created_at, updated_at` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |
| `db/task_intercept.go::insertTaskInterceptRules` · [근거](evidence:db-pg-access-task-intercept-rules-5289e2be79) | `write` / `INSERT` | L115 `INSERT` `INSERT INTO task_intercept_rules(task_id, enabled, action, kind, pattern, note) VALUES ($1,$2,$3,$4,$5,$6)` | [`module-tool-intercept`](../../modules/tool-policy.md#intercept) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-notification-channels"></a>
## `notification_channels`

[notification_channels 물리 객체](findings-operations.md#table-notification-channels) · [field 의미](semantic-catalog.md#semantic-notification-channels)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/notification.go::DB.DeleteNotificationChannel` · [근거](evidence:db-pg-access-notification-channels-1c73b6e6ff) | `write` / `DELETE` | L198 `DELETE` `DELETE FROM notification_channels WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.ListNotificationChannels` · [근거](evidence:db-pg-access-notification-channels-3c998953c9) | `read` / `FROM` | L95 `FROM` `SELECT id, name, kind, enabled, config, mode, filter, rate_per_min, created_at, updated_at FROM notification_channels ORDER BY enabled DESC, id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.NotificationChannelByID` · [근거](evidence:db-pg-access-notification-channels-790746d20d) | `read` / `FROM` | L114 `FROM` `SELECT id, name, kind, enabled, config, mode, filter, rate_per_min, created_at, updated_at FROM notification_channels WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.NotificationStatsSnapshot` · [근거](evidence:db-pg-access-notification-channels-ef0d56b704) | `read` / `FROM` | L539 `FROM` `SELECT (SELECT count(*) FROM notification_channels), (SELECT count(*) FROM notification_channels WHERE enabled), (SELECT count(*) FROM notification_deliveries WHERE state IN ($1,$2)), (SELECT count(*) FROM notification_deliveries WHERE state=$3), (SELECT count(*) FROM notification_deliveries WHERE state=$4 AND sent…` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.SaveNotificationChannel` · [근거](evidence:db-pg-access-notification-channels-71a8049a70) | `write` / `INSERT,UPDATE` | L153 `INSERT` `INSERT INTO notification_channels(name,kind,enabled,config,mode,filter,rate_per_min) VALUES($1,$2,$3,$4,$5,$6,$7) RETURNING id`<br>L158 `UPDATE` `UPDATE notification_channels SET name=$2, kind=$3, enabled=$4, config=$5, mode=$6, filter=$7, rate_per_min=$8 WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.SetNotificationChannelEnabled` · [근거](evidence:db-pg-access-notification-channels-16ab658a14) | `write` / `UPDATE` | L177 `UPDATE` `UPDATE notification_channels SET enabled=$2 WHERE id=$1` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::listEnabledNotificationChannelsTx` · [근거](evidence:db-pg-access-notification-channels-1d231f183b) | `read` / `FROM` | L365 `FROM` `SELECT id, name, kind, config, mode, filter, rate_per_min FROM notification_channels WHERE enabled ORDER BY id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ClaimDigestBatch` · [근거](evidence:db-pg-access-notification-channels-37f497fe6b) | `read` / `JOIN` | L187 `JOIN` `SELECT dd.id FROM notification_deliveries dd JOIN notification_channels c ON c.id = dd.channel_id WHERE dd.channel_id = $1 AND dd.state IN ($2,$3) AND dd.next_attempt_at <= now() AND c.enabled ORDER BY dd.id FOR UPDATE OF dd SKIP LOCKED LIMIT $4` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ClaimRealtimeDeliveries` · [근거](evidence:db-pg-access-notification-channels-a477c0e7b3) | `read` / `JOIN` | L129 `JOIN` `SELECT dd.id FROM notification_deliveries dd JOIN notification_channels c ON c.id = dd.channel_id WHERE dd.channel_id = $1 AND dd.state IN ($2,$3) AND dd.next_attempt_at <= now() AND c.enabled AND c.mode = $4 ORDER BY dd.next_attempt_at, dd.id FOR UPDATE OF dd SKIP LOCKED LIMIT $5` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.DigestBatchDue` · [근거](evidence:db-pg-access-notification-channels-db1fb1f29a) | `read` / `JOIN` | L151 `JOIN` `SELECT EXISTS ( SELECT 1 FROM notification_deliveries d JOIN notification_channels c ON c.id = d.channel_id WHERE d.channel_id = $1 AND d.state IN ($2,$3) AND c.enabled GROUP BY d.channel_id HAVING min(d.created_at) <= now() - make_interval(secs => $4) )` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ListNotificationDeliveries` · [근거](evidence:db-pg-access-notification-channels-d5b73cdd8d) | `read` / `JOIN` | L401 `JOIN` `source fragment: joinedDeliveryQuery + runtime WHERE + ORDER BY d.id DESC + LIMIT/OFFSET placeholders <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::loadDeliveriesTx` · [근거](evidence:db-pg-access-notification-channels-826904f61d) | `read` / `JOIN` | L265 `JOIN` `…lter, c.rate_per_min FROM notification_deliveries d JOIN notification_events e ON e.id = d.event_id JOIN notification_channels c ON c.id = d.channel_id WHERE d.id IN (<runtime-expanded placeholders>) ORDER BY d.id` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 12개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-notification-events"></a>
## `notification_events`

[notification_events 물리 객체](findings-operations.md#table-notification-events) · [field 의미](semantic-catalog.md#semantic-notification-events)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/notification.go::DB.AddNotificationEvent` · [근거](evidence:db-pg-access-notification-events-d671b8097a) | `write` / `INSERT` | L257 `INSERT` `INSERT INTO notification_events(kind,finding_id,snapshot) VALUES($1,$2,$3) RETURNING id` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.FanOutPendingEvents` · [근거](evidence:db-pg-access-notification-events-eee01ab57c) | `read,write` / `FROM,UPDATE` | L289 `FROM` `SELECT id, kind, finding_id, snapshot FROM notification_events WHERE NOT fanned_out ORDER BY id FOR UPDATE SKIP LOCKED LIMIT $1`<br>L356 `UPDATE` `UPDATE notification_events SET fanned_out=true WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::RecordNotificationEventTx` · [근거](evidence:db-pg-access-notification-events-e2d1dca210) | `write` / `INSERT` | L235 `INSERT` `INSERT INTO notification_events(kind,finding_id,snapshot) VALUES($1,$2,$3)` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ListNotificationDeliveries` · [근거](evidence:db-pg-access-notification-events-b58979bce9) | `read` / `JOIN` | L396 `JOIN` `source fragment: SELECT count(*) FROM notification_deliveries d JOIN notification_events e ON e.id = d.event_id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L401 `JOIN` `source fragment: joinedDeliveryQuery + runtime WHERE + ORDER BY d.id DESC + LIMIT/OFFSET placeholders <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::loadDeliveriesTx` · [근거](evidence:db-pg-access-notification-events-01cb13b683) | `read` / `JOIN` | L265 `JOIN` `….name, c.kind, c.enabled, c.config, c.mode, c.filter, c.rate_per_min FROM notification_deliveries d JOIN notification_events e ON e.id = d.event_id JOIN notification_channels c ON c.id = d.channel_id WHERE d.id IN (<runtime-expanded placeholders>) ORDER BY d.id` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 5개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-notification-deliveries"></a>
## `notification_deliveries`

[notification_deliveries 물리 객체](findings-operations.md#table-notification-deliveries) · [field 의미](semantic-catalog.md#semantic-notification-deliveries)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/notification.go::DB.FanOutPendingEvents` · [근거](evidence:db-pg-access-notification-deliveries-e3bd3204a8) | `write` / `INSERT` | L344 `INSERT` `INSERT INTO notification_deliveries(event_id,channel_id) VALUES <runtime-expanded ($n,$n) tuples>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.NotificationStatsSnapshot` · [근거](evidence:db-pg-access-notification-deliveries-2a3b18de73) | `read` / `FROM` | L539 `FROM` `…E enabled), (SELECT count(*) FROM notification_deliveries WHERE state IN ($1,$2)), (SELECT count(*) FROM notification_deliveries WHERE state=$3), (SELECT count(*) FROM notification_deliveries WHERE state=$4 AND sent_at >= date_trunc('day', now())), COALESCE((SELECT EXTRACT(EPOCH FROM (now() - min(created_at))) * 1000 FROM notification_deliveries …` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification.go::DB.SetNotificationChannelEnabled` · [근거](evidence:db-pg-access-notification-deliveries-4792232261) | `write` / `UPDATE` | L185 `UPDATE` `UPDATE notification_deliveries SET state=$2, last_error=$3 WHERE channel_id=$1 AND state IN ($4,$5)` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ClaimDigestBatch` · [근거](evidence:db-pg-access-notification-deliveries-41525f8214) | `read,write` / `FROM,UPDATE` | L187 `FROM` `SELECT dd.id FROM notification_deliveries dd JOIN notification_channels c ON c.id = dd.channel_id WHERE dd.channel_id = $1 AND dd.state IN ($2,$3) AND dd.next_attempt_at <= now() AND c.enabled ORDER BY dd.id FOR UPDATE OF dd SKIP LOCKED LIMIT $4`<br>L202 `UPDATE` `UPDATE notification_deliveries SET batch_id = COALESCE(batch_id, $1) WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ClaimRealtimeDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-8feff6dd1d) | `read` / `FROM` | L129 `FROM` `SELECT dd.id FROM notification_deliveries dd JOIN notification_channels c ON c.id = dd.channel_id WHERE dd.channel_id = $1 AND dd.state IN ($2,$3) AND dd.next_attempt_at <= now() AND c.enabled AND c.mode = $4 ORDER BY dd.next_attempt_at, dd.id FOR UPDATE OF dd …` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.DeferDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-1cb1f5dd43) | `write` / `UPDATE` | L322 `UPDATE` `UPDATE notification_deliveries SET state=$1, attempts=GREATEST(attempts-1, 0), next_attempt_at=now(), last_error=$2 WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.DigestBatchDue` · [근거](evidence:db-pg-access-notification-deliveries-a2a50b4454) | `read` / `FROM` | L151 `FROM` `SELECT EXISTS ( SELECT 1 FROM notification_deliveries d JOIN notification_channels c ON c.id = d.channel_id WHERE d.channel_id = $1 AND d.state IN ($2,$3) AND c.enabled GROUP BY d.channel_id HAVING min(d.created_at) <= now() - make_interval(secs => $4) )` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.FailDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-0832492f88) | `write` / `UPDATE` | L336 `UPDATE` `UPDATE notification_deliveries SET state=$1, last_error=$2 WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.ListNotificationDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-1ba7713700) | `read` / `FROM` | L396 `FROM` `source fragment: SELECT count(*) FROM notification_deliveries d JOIN notification_events e ON e.id = d.event_id <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L401 `FROM` `source fragment: joinedDeliveryQuery + runtime WHERE + ORDER BY d.id DESC + LIMIT/OFFSET placeholders <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.MarkDeliveriesSent` · [근거](evidence:db-pg-access-notification-deliveries-4733db6f9b) | `write` / `UPDATE` | L287 `UPDATE` `UPDATE notification_deliveries SET state=$1, sent_at=now(), last_error='' WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.RescheduleDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-7a521922df) | `write` / `UPDATE` | L301 `UPDATE` `UPDATE notification_deliveries SET state=$1, next_attempt_at=now()+make_interval(secs => $2), last_error=$3 WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.RetryNotificationDelivery` · [근거](evidence:db-pg-access-notification-deliveries-8403471de4) | `write` / `UPDATE` | L345 `UPDATE` `UPDATE notification_deliveries SET state=$2, attempts=0, next_attempt_at=now(), last_error='' WHERE id=$1 AND state IN ($3,$4)` | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::DB.claimDeliveries` · [근거](evidence:db-pg-access-notification-deliveries-3f8ba0a0c7) | `write` / `UPDATE` | L228 `UPDATE` `UPDATE notification_deliveries SET state=$1, attempts=attempts+1, next_attempt_at=now()+make_interval(secs => $2) WHERE id IN (<runtime-expanded placeholders>)` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |
| `db/notification_delivery.go::loadDeliveriesTx` · [근거](evidence:db-pg-access-notification-deliveries-8d676caafb) | `read` / `FROM` | L265 `FROM` `…, e.kind, e.finding_id, c.id, c.name, c.kind, c.enabled, c.config, c.mode, c.filter, c.rate_per_min FROM notification_deliveries d JOIN notification_events e ON e.id = d.event_id JOIN notification_channels c ON c.id = d.channel_id WHERE d.id IN (<runtime-expanded placeholders>) ORDER BY d.id` · runtime fragment A/U | [`feature-finding-downstream`](../../features/findings-evidence.md#downstream) |

**처분** · located production table-symbol binding 14개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-llm-records"></a>
## `llm_records`

[llm_records 물리 객체](agent-runtime.md#table-llm-records) · [field 의미](semantic-catalog.md#semantic-llm-records)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/commands.go::DB.DeleteLLMRecords` · [근거](evidence:db-pg-access-llm-records-9aca9bea84) | `write` / `DELETE` | L320 `DELETE` `DELETE FROM llm_records WHERE COALESCE(task_id,'') = $1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/commands.go::DB.GetLLMRecord` · [근거](evidence:db-pg-access-llm-records-cab673cf7a) | `read` / `FROM` | L331 `FROM` `…0), COALESCE(status,''), COALESCE(error,''), request_body, response_body, raw_request, raw_response FROM llm_records WHERE id=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/commands.go::DB.InsertLLMRecord` · [근거](evidence:db-pg-access-llm-records-6d63fd4190) | `write` / `INSERT` | L211 `INSERT` `INSERT INTO llm_records(model, profile_name, session_id, task_id, worker, latency_ms, input_tokens, output_tokens, cache_read, cache_write, status, error, request_body, response_body, raw_request, raw_response) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,…` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/commands.go::DB.LLMTasks` · [근거](evidence:db-pg-access-llm-records-30b3dfbfb4) | `read` / `FROM` | L300 `FROM` `SELECT task_id, COUNT(*) AS n FROM llm_records WHERE COALESCE(task_id,'') <> '' GROUP BY task_id ORDER BY MAX(id) DESC` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/commands.go::DB.ListLLMRecords` · [근거](evidence:db-pg-access-llm-records-617fe0723a) | `read` / `FROM` | L251 `FROM` `source fragment: SELECT COUNT(*) FROM llm_records WHERE true <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L255 `FROM` `source fragment: …tokens,0), COALESCE(cache_read,0), COALESCE(cache_write,0), COALESCE(status,''), COALESCE(error,'') FROM llm_records <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-llm-records-f38b83f350) | `read` / `FROM` | L592 `FROM` `source fragment: SELECT * FROM llm_records WHERE COALESCE(task_id,'')=$1 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-llm-records-c77d100838) | `write` / `DELETE` | L70 `DELETE` `DELETE FROM llm_records WHERE COALESCE(task_id,'')=$1` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveJSONSequenceRows` · [근거](evidence:db-pg-access-llm-records-41341529c6) | `write` / `INSERT` | L407 `INSERT` `INSERT INTO llm_records SELECT * FROM json_populate_record(NULL::llm_records,$1::json)` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-llm-records-b29e826f92) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/tasks.go::DB.DeleteTaskCascadePrepared` · [근거](evidence:db-pg-access-llm-records-27d38e6b28) | `write` / `DELETE` | L639 `DELETE` `DELETE FROM llm_records WHERE COALESCE(task_id,'')=$1` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |

**처분** · located production table-symbol binding 10개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-llm-usage"></a>
## `llm_usage`

[llm_usage 물리 객체](agent-runtime.md#table-llm-usage) · [field 의미](semantic-catalog.md#semantic-llm-usage)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `db/llm_usage.go::DB.InsertLLMUsage` · [근거](evidence:db-pg-access-llm-usage-c31f6c2e58) | `write` / `INSERT` | L73 `INSERT` `INSERT INTO llm_usage(task_id, exploration_id, worker, model, profile_name, latency_ms, input_tokens, output_tokens, cache_read, cache_write, status) VALUES (NULLIF($1,''),$2,NULLIF($3,''),NULLIF($4,''),NULLIF($5,''),$6,$7,$8,$9,$10,$11)` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llm_usage.go::DB.JudgeUsageStats` · [근거](evidence:db-pg-access-llm-usage-1e4f16e088) | `read` / `FROM` | L292 `FROM` `…kens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read),0), COALESCE(SUM(cache_write),0) FROM llm_usage WHERE worker = 'judge'`<br>L301 `FROM` `…UTC', 'YYYY-MM-DD') AS day, COUNT(*), COALESCE(SUM(input_tokens),0), COALESCE(SUM(output_tokens),0) FROM llm_usage WHERE worker = 'judge' AND ts >= now() - ($1 * interval '1 day') GROUP BY day ORDER BY day` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llm_usage.go::DB.TokenByModel` · [근거](evidence:db-pg-access-llm-usage-6b6d0f6e83) | `read` / `FROM` | L86 `FROM` `…kens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read),0), COALESCE(SUM(cache_write),0) FROM llm_usage WHERE COALESCE(task_id,'') = $1 GROUP BY model ORDER BY SUM(input_tokens) + SUM(output_tokens) DESC, model` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llm_usage.go::DB.UsageByProfile` · [근거](evidence:db-pg-access-llm-usage-bcfba2f79c) | `read` / `FROM` | L125 `FROM` `…kens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read),0), COALESCE(SUM(cache_write),0) FROM llm_usage GROUP BY profile_name ORDER BY SUM(input_tokens) + SUM(output_tokens) DESC` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/llm_usage.go::DB.UsageDaily` · [근거](evidence:db-pg-access-llm-usage-cde6f94cdb) | `read` / `FROM` | L202 `FROM` `… AS day, COALESCE(SUM(input_tokens),0), COALESCE(SUM(output_tokens),0), COALESCE(SUM(cache_read),0) FROM llm_usage WHERE ts >= now() - ($1 * interval '1 day') GROUP BY profile_name, day ORDER BY day` | [`module-agent-provider`](../../modules/agent-runtime.md#provider-routing) |
| `db/task_archives.go::DB.snapshotTaskArchive` · [근거](evidence:db-pg-access-llm-usage-23ac482369) | `read` / `FROM` | L593 `FROM` `source fragment: SELECT * FROM llm_usage WHERE COALESCE(task_id,'')=$1 OR exploration_id=$2 ORDER BY id <additional runtime fragments may be omitted>` · runtime fragment A/U | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives.go::taskArchiveAggregates` · [근거](evidence:db-pg-access-llm-usage-615cc46c49) | `read` / `FROM` | L717 `FROM` `…tokens),0),COALESCE(sum(output_tokens),0), COALESCE(sum(cache_read),0),COALESCE(sum(cache_write),0) FROM llm_usage WHERE COALESCE(task_id,'')=$1 OR exploration_id=$2`<br>L729 `FROM` `…kens, COALESCE(sum(cache_read),0) cache_read_tokens,COALESCE(sum(cache_write),0) cache_write_tokens FROM llm_usage WHERE COALESCE(task_id,'')=$1 OR exploration_id=$2 GROUP BY profile_name ORDER BY sum(input_tokens)+sum(output_tokens) DESC) x`<br>L735 `FROM` `…_tokens,COALESCE(sum(output_tokens),0) output_tokens, COALESCE(sum(cache_read),0) cache_read_tokens FROM llm_usage WHERE COALESCE(task_id,'')=$1 OR exploration_id=$2 GROUP BY profile_name,date ORDER BY date) x` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::DB.CompleteTaskArchive` · [근거](evidence:db-pg-access-llm-usage-13a8f69171) | `write` / `DELETE` | L73 `DELETE` `DELETE FROM llm_usage WHERE COALESCE(task_id,'')=$1 OR exploration_id=$2` | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |
| `db/task_archives_restore.go::insertArchiveRows` · [근거](evidence:db-pg-access-llm-usage-e5292afc9f) | `write` / `INSERT` | L399 `INSERT` `INSERT INTO <allowlisted table> SELECT * FROM json_populate_recordset(NULL::<same table>,$1::json)` · 닫힌 allowlist 해석 | [`module-storage-retention`](../../modules/storage-runtime.md#retention) |

**처분** · located production table-symbol binding 9개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-sqlite"></a>
## Traffic SQLite 접근

<a id="access-exchanges"></a>
## `exchanges`

[exchanges 물리 객체](traffic-sqlite.md#table-exchanges)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `traffic/archive.go::Traffic.ExportHosts` · [근거](evidence:db-sqlite-access-exchanges-4f80e596da) | `read` / `FROM` | L63 `FROM` `SELECT ... FROM exchanges WHERE host IN (<runtime-expanded placeholders>) ORDER BY ts,id` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/archive.go::Traffic.ImportArchive` · [근거](evidence:db-sqlite-access-exchanges-b479f9f58f) | `read,write` / `FROM,INSERT` | L181 `INSERT` `INSERT OR IGNORE INTO exchanges(id,ts,host,method,url_template,url,status,content_type,req_len,resp_len,path) VALUES(?,?,?,?,?,?,?,?,?,?,'')`<br>L205 `FROM` `SELECT rowid FROM exchanges WHERE id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/evidence.go::Traffic.readEvidence` · [근거](evidence:db-sqlite-access-exchanges-9162ebd8fd) | `read` / `FROM` | L49 `FROM` `SELECT ts,url,method,status,content_type,req_len,resp_len,path FROM exchanges WHERE id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Count` · [근거](evidence:db-sqlite-access-exchanges-2bf40eda47) | `read` / `FROM` | L1020 `FROM` `SELECT COUNT(*) FROM exchanges` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Get` · [근거](evidence:db-sqlite-access-exchanges-cb9120717d) | `read` / `FROM,JOIN` | L955 `JOIN` `…req_body,b.req_blob,b.resp_head,b.resp_body,b.resp_blob,e.req_len,e.resp_len FROM exchange_bodies b JOIN exchanges e ON e.id=b.id WHERE b.id=?`<br>L966 `FROM` `SELECT path FROM exchanges WHERE id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Hosts` · [근거](evidence:db-sqlite-access-exchanges-813a9379ef) | `read` / `FROM` | L1000 `FROM` `SELECT host, COUNT(*) AS n, MAX(ts) AS last FROM exchanges GROUP BY host ORDER BY last DESC` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Page` · [근거](evidence:db-sqlite-access-exchanges-aca94a3fc0) | `read` / `FROM` | L915 `FROM` `source fragment: SELECT COUNT(*) FROM exchanges<runtime filter fragments> <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L928 `FROM` `source fragment: SELECT ... FROM exchanges<runtime filter fragments> <additional runtime fragments may be omitted>` · runtime fragment A/U<br>L931 `FROM` `source fragment: SELECT ... FROM exchanges<runtime filter fragments> ORDER BY <allowlisted column/direction>, id DESC LIMIT ? OFFSET ? <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Search` · [근거](evidence:db-sqlite-access-exchanges-a235da95f5) | `read` / `FROM` | L770 `FROM` `source fragment: SELECT id,ts,host,method,url_template,url,status,content_type,resp_len,path FROM exchanges <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.deleteWhere` · [근거](evidence:db-sqlite-access-exchanges-4e84109cd8) | `read,write` / `DELETE,FROM` | L1185 `FROM` `DELETE FROM ex_fts WHERE rowid IN (SELECT rowid FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U<br>L1189 `FROM` `DELETE FROM exchange_bodies WHERE id IN (SELECT id FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U<br>L1192 `FROM` `DELETE FROM blob_refs WHERE exchange_id IN (SELECT id FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U<br>L1195 `DELETE` `DELETE FROM exchanges WHERE <fixed internal call-site predicate>` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.hostTrees` · [근거](evidence:db-sqlite-access-exchanges-a26f83a3bb) | `read` / `FROM` | L1210 `FROM` `source fragment: SELECT DISTINCT host FROM exchanges WHERE <host LIKE ? from fixed internal call site> <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.hostsHaveNoExchanges` · [근거](evidence:db-sqlite-access-exchanges-267d0fd3c2) | `read` / `FROM` | L1584 `FROM` `SELECT count(*) FROM exchanges WHERE host=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.legacyBlobRefs` · [근거](evidence:db-sqlite-access-exchanges-1c22a6cb53) | `read` / `FROM` | L1862 `FROM` `SELECT COUNT(*) FROM exchanges WHERE path<>''` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.query` · [근거](evidence:db-sqlite-access-exchanges-c3c166aa3a) | `read` / `FROM` | L1907 `FROM` `source fragment: SELECT id,ts,host,method,url_template,url,status,content_type,resp_len,path FROM exchanges WHERE 1=1 <additional runtime fragments may be omitted>` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.record` · [근거](evidence:db-sqlite-access-exchanges-959f04152f) | `write` / `INSERT` | L466 `INSERT` `INSERT OR REPLACE INTO exchanges(id,ts,host,method,url_template,url,status,content_type,req_len,resp_len,path) VALUES(?,?,?,?,?,?,?,?,?,?,'')` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 14개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-exchange-bodies"></a>
## `exchange_bodies`

[exchange_bodies 물리 객체](traffic-sqlite.md#table-exchange-bodies)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `traffic/archive.go::Traffic.ExportHosts` · [근거](evidence:db-sqlite-access-exchange-bodies-7971225971) | `read` / `FROM` | L79 `FROM` `SELECT req_head,req_body,req_blob,resp_head,resp_body,resp_blob FROM exchange_bodies WHERE id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/archive.go::Traffic.ImportArchive` · [근거](evidence:db-sqlite-access-exchange-bodies-48e3443ec7) | `write` / `INSERT` | L191 `INSERT` `INSERT INTO exchange_bodies(id,req_head,req_body,req_blob,resp_head,resp_body,resp_blob) VALUES(?,?,?,?,?,?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/evidence.go::Traffic.readEvidence` · [근거](evidence:db-sqlite-access-exchange-bodies-d512e84e76) | `read` / `FROM` | L55 `FROM` `SELECT req_head,req_body,req_blob,resp_head,resp_body,resp_blob FROM exchange_bodies WHERE id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.Get` · [근거](evidence:db-sqlite-access-exchange-bodies-ad6310aecb) | `read` / `FROM` | L955 `FROM` `SELECT b.req_head,b.req_body,b.req_blob,b.resp_head,b.resp_body,b.resp_blob,e.req_len,e.resp_len FROM exchange_bodies b JOIN exchanges e ON e.id=b.id WHERE b.id=?` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.deleteWhere` · [근거](evidence:db-sqlite-access-exchange-bodies-cd161de2ba) | `write` / `DELETE` | L1189 `DELETE` `DELETE FROM exchange_bodies WHERE id IN (SELECT id FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.record` · [근거](evidence:db-sqlite-access-exchange-bodies-51fc030662) | `write` / `INSERT` | L480 `INSERT` `INSERT OR REPLACE INTO exchange_bodies(id,req_head,req_body,req_blob,resp_head,resp_body,resp_blob) VALUES(?,?,?,?,?,?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-blob-refs"></a>
## `blob_refs`

[blob_refs 물리 객체](traffic-sqlite.md#table-blob-refs)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `traffic/archive.go::Traffic.ImportArchive` · [근거](evidence:db-sqlite-access-blob-refs-12efa593f1) | `write` / `INSERT` | L198 `INSERT` `INSERT OR IGNORE INTO blob_refs(hash,exchange_id) VALUES(?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.deleteWhere` · [근거](evidence:db-sqlite-access-blob-refs-a443b6feb5) | `write` / `DELETE` | L1192 `DELETE` `DELETE FROM blob_refs WHERE exchange_id IN (SELECT id FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.gcBlobs` · [근거](evidence:db-sqlite-access-blob-refs-928f5df99f) | `read` / `FROM` | L1805 `FROM` `SELECT DISTINCT hash FROM blob_refs` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.record` · [근거](evidence:db-sqlite-access-blob-refs-c0b4d474ee) | `write` / `INSERT` | L491 `INSERT` `INSERT OR IGNORE INTO blob_refs(hash,exchange_id) VALUES(?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 4개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

<a id="access-ex-fts"></a>
## `ex_fts`

[ex_fts 물리 객체](traffic-sqlite.md#table-ex-fts)

| production symbol | mode/verb | 의미·조건(SQL) | 구현 귀속 |
|---|---|---|---|
| `traffic/archive.go::Traffic.ImportArchive` · [근거](evidence:db-sqlite-access-ex-fts-e7acacd3ef) | `write` / `INSERT` | L209 `INSERT` `INSERT INTO ex_fts(rowid,content) VALUES(?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.compactIndex` · [근거](evidence:db-sqlite-access-ex-fts-446971b0d7) | `write` / `INSERT` | L1156 `INSERT` `INSERT INTO ex_fts(ex_fts) VALUES('optimize')` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.deleteWhere` · [근거](evidence:db-sqlite-access-ex-fts-735362d242) | `write` / `DELETE` | L1185 `DELETE` `DELETE FROM ex_fts WHERE rowid IN (SELECT rowid FROM exchanges WHERE <fixed internal call-site predicate>)` · runtime fragment A/U | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.ftsFilter` · [근거](evidence:db-sqlite-access-ex-fts-973e53370c) | `read` / `FROM` | L803 `FROM` `rowid IN (SELECT rowid FROM ex_fts WHERE ex_fts MATCH ?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.reclaimChunk` · [근거](evidence:db-sqlite-access-ex-fts-f9b44927da) | `write` / `INSERT` | L1764 `INSERT` `INSERT INTO ex_fts(ex_fts, rank) VALUES('merge', ?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |
| `traffic/traffic.go::Traffic.record` · [근거](evidence:db-sqlite-access-ex-fts-2b5c06a26b) | `write` / `INSERT` | L501 `INSERT` `INSERT INTO ex_fts(rowid,content) VALUES(?,?)` | [`feature-traffic-evidence`](../../features/findings-evidence.md#traffic-evidence) |

**처분** · located production table-symbol binding 6개를 file/symbol과 확인 가능한 SQL verb에 연결했다. runtime-built 행은 최종 predicate/order/placeholder 집합이 P/U이며, arbitrary formatted identifier·실제 호출·row 수·query plan은 관찰하지 않았다.

