Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
현재 구현: [수치별 역할 연결 순수 계약](docs/changes/role-link-contract-implementation.md). 원문 후보·수치별 전체 관계·불확실/미검토·정확 인용 위치를 보존하고 원문에서 다시 검증하는 두 모듈을 구현했다. 신규201개와 인접523개 검사가 통과했다. 독립 검토 C0/I0/M0·새 전체8,300개 QA와 린트/형식/타입/빌드/OpenAPI 검증을 통과했으며 모델 SDK/실제 관계 정확도·앱 적용은 후속이다.

# IssueDigest

다음 설계: [수치별 역할 적용 관계·명시 coverage](docs/changes/role-link-coverage.md). 후보×수치의 모든 관계에 복수 역할·관련 없음·불확실·미검토를 기록하는 행렬을 설계했다. 원문/proposal과 실제 잔여 예산을 유지한 무호출 시제품이며 새SDK/실제 관계 정확도는 미검증이다.
기준 설계: [수치별 역할 적용 관계·명시 coverage](docs/changes/role-link-coverage.md). 후보×수치의 모든 관계에 복수 역할·관련 없음·불확실·미검토를 기록하는 행렬을 설계했다. 원문/proposal과 실제 잔여 예산을 유지한 무호출 시제품이며 새SDK/실제 관계 정확도는 미검증이다.

최신 실제 평가: [table 검수5회](docs/research/role-table-acceptance.md). 긴 자료도 전체 원문/추출을 유지해 검수를 완료했지만, 사전 역할 오류8대상 중 탐지2/미탐6이며 추가진단3개는 판정 유보다. 참고$0.0355525·원래 결과/비용을 보존하고 앱 연결을 보류한다.

Expand Down
4 changes: 3 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
현재 구현: [수치별 역할 연결 순수 계약](changes/role-link-contract-implementation.md). 원문 후보·수치별 전체 관계·불확실/미검토·정확 인용 위치를 보존하고 원문에서 다시 검증하는 두 모듈을 구현했다. 신규201개와 인접523개 검사가 통과했다. 독립 검토 C0/I0/M0·새 전체8,300개 QA와 린트/형식/타입/빌드/OpenAPI 검증을 통과했으며 모델 SDK/실제 관계 정확도·앱 적용은 후속이다.

# 문서 안내·협업 방법

다음 설계: [수치별 역할 적용 관계·명시 coverage](changes/role-link-coverage.md). 후보×수치의 모든 관계에 복수 역할·관련 없음·불확실·미검토를 기록하는 행렬을 설계했다. 원문/proposal과 실제 잔여 예산을 유지한 무호출 시제품이며 새SDK/실제 관계 정확도는 미검증이다.
기준 설계: [수치별 역할 적용 관계·명시 coverage](changes/role-link-coverage.md). 후보×수치의 모든 관계에 복수 역할·관련 없음·불확실·미검토를 기록하는 행렬을 설계했다. 원문/proposal과 실제 잔여 예산을 유지한 무호출 시제품이며 새SDK/실제 관계 정확도는 미검증이다.

최신 실제 평가: [table 검수5회](research/role-table-acceptance.md). 긴 자료도 전체 원문/추출을 유지해 검수를 완료했지만, 사전 역할 오류8대상 중 탐지2/미탐6이며 추가진단3개는 판정 유보다. 참고$0.0355525·원래 결과/비용을 보존하고 앱 연결을 보류한다.

Expand Down
56 changes: 56 additions & 0 deletions docs/changes/role-link-contract-implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Role-link pure contract implementation

2026-10-22 KST. Binding spec: [reviewed design](role-link-coverage.md). Existing isolated worktree verified clean; OpenSpec root:null, no initialization. Two sequential tasks implement only pure contracts, not the borrowed-model SDK.

## Global Constraints

Preserve all450 existing non-Markdown tracked files,562 actual-trial evidence files,45 earlier design and59 reviewed role-link design files. Only two new production modules and two matching synthetic test modules. No providers/network/old runners/private actual evidence in workers, no SDK/Model calls, app/API/UI/DB/worker/default-model changes, deployment/main merge. No fake legacy audit/report receipts, hard omission/repair, full semantic/source coverage or human approval. Existing exact RoleAliasGenerationV2 and full original table packet stay unchanged. Use pure existing _guard/_original_values/_checked_generation/locator helpers read-only, validate required markers and exact raw/actual/nested/container/tuple/scalar types before dumps. No missing defaults or normalization. TDD, explicit restore_introduced_modules fixture from test_shared_measurement_context_v2, focused and meaningful adjacent/static checks only. Controller owns full QA/preservation/privacy/offline actual-source checks/reviews/PR/Sites. Workers must not spawn subagents or push/deploy. Exact public signatures/types below are the Task1→Task2 interface; report any unavoidable naming clarification.

## Task 1: Deterministic surface catalog and domains

- [x] Implement and test pure catalog.

Own only packages/agents/src/issuedigest_agents/role_link_catalog.py and packages/agents/tests/test_role_link_catalog.py plus own checkbox. Read binding spec. APIs build_role_link_catalog(source:Source,generation:RoleAliasGenerationV2)->RoleLinkCatalog; validate_role_link_catalog(source:Source,result:RoleLinkCatalog|dict[str,Any])->RoleLinkCatalog; role_link_packet(source:Source,generation:RoleAliasGenerationV2)->dict[str,Any]. Export ROLE_ORDER='STOREIBP', immutable stable role metadata (or fresh role_legend projection) mapping S measurement_scope,T measurement_period,O operator,R reporter,E entity_qualifier,I programme_identity,B comparison_baseline,P purpose; states '-' explicitly_unrelated,'?' linkage_uncertain,'_' not_reviewed. Object key order is NOT role order. Provide pure encoding metadata/version for Task2 to hash. Required literal markers/no defaults: catalog profile='role-link-catalog-v1', rules_version='surface-role-hints-v1', source_inventory_exhaustive=False. Catalog includes exact original generation; generation_sha256 hash of canonical original; source_packet_sha256 hash of complete existing build_role_table_packet; rules_sha256 hash of exact patterns/limits/context rules; hints tuple[RoleLinkHint,...]; domains tuple[RoleLinkDomain,...]. Hint fields hint_id,quote_id,anchor:RoleAliasAnchor,span:ExactSpan,origins tuple of exact origin labels. Domain fields quote_id,numbers tuple[str,...],hints tuple[str,...]. Source quote/table and current selection validated before any serialization; validator extracts/statically guards original generation before dumping then reconstructs entire catalog/hash/metadata/domain. Exact model subclasses, unchecked copies, missing nested/default markers, scalar/container subclasses and raw tuple lists rejected.

Deterministic origin patterns copied verbatim (lexical hints only):
- dot_list: r'[가-힣A-Za-z0-9]+(?:·[가-힣A-Za-z0-9]+)+'; every r'[^·]+' member produces dot_member.
- year_surface: r'[0-9]{1,4}년(?:간|까지|부터)?'
- relative_time_surface: r'(?:올해(?:\s*[0-9]+월(?:부터|까지)?)?|전년도(?:\s*대비)?|현재)'
- institution_suffix_surface: r'[가-힣]+(?:부|청|공단|위원회|정부|대학)(?=[은는이가을를의에과와]|으로|에서|로|[^가-힣]|$)'
- place_suffix_surface: r'[가-힣]+(?:특별자치도|특별시|광역시|도|시|군|구)(?=[은는이가을를의에과와]|으로|에서|로|[^가-힣]|$)'
- quoted_phrase: r"'[^'\n]+'|‘[^’\n]+’|「[^」\n]+」"

Use current source sentence order, then start/end order; merge only same quote/sentence/start/end origins (sorted exact labels). IDs m1.. global, quote IDs q1.. original quote order. Preserve duplicates at different locations and group/member overlap. For t unique under overlapping occurrence count c=null; otherwise choose shortest context by increasing extra length, then increasing left position, containing exact t exactly once and occurring exactly once in sentence, with overlapping occurrences counted. Must resolve through existing strict locator and verify exact original position; max t/c1000, no normalization. If no context/locator impossible raise sanitized RoleLinkCatalogError(reason='unlocatable_hint'); >24 hints in ANY quote => reason='candidate_overflow', no partial/truncation. Other malformed inputs reason='invalid_input'. Error exposes only reason/sanitized message, no source. Full source remains present even if pattern finds no hint. Runtime ceiling applies to same-position deduplicated hint count, before attempting to repair/omit any hint; report no partial catalog on failure.

Domains include EVERY quote, all its hints and original binding-order selected numbers from that quote, even numbers0/hints0. Empty selection remains full catalog/source with empty number domains. role_link_packet exactly profile='role-link-review-v1', source_packet=current unchanged existing table packet, hint_table={columns:['id','quote_id','s','t','c'],rows:[[hint_id,quote_id,s,t,c],...]}, domains list of {quote_id,numbers,hints}, role_legend mapping, required role_order, state_legend mapping, source_inventory_exhaustive=False. Origins and exact original spans remain backend catalog only. No arbitrary runtime supplied catalog/projection accepted as canonical. Tests red/green: literal projection/order, per-pattern/group member/dedup/overlap/repeated exact location,24inclusive/25overflow, unlocatable marker/1000, no-hint/empty selection/multiquote, fresh source/gen/catalog drift, marker/raw/actual/tuple/scalar/container/subclass tamper before dumps. No private actual fixtures. Run focused/static/adjacent then commit owned files/checkbox; detailed TDD/report supplied path.

## Task 2: Explicit matrix report and reconstruction

- [x] Implement and test pure relation contract.

Own only packages/agents/src/issuedigest_agents/role_link_contract.py and packages/agents/tests/test_role_link_contract.py plus own checkbox. Consume Task1 catalog APIs/DTOs/constants without edits. APIs build_role_link_report(source:Source,generation:RoleAliasGenerationV2,data:RoleLinkInput|dict[str,Any])->RoleLinkReport; validate_role_link_report(source:Source,result:RoleLinkReport|dict[str,Any])->RoleLinkReport. RoleLinkInput required rows:tuple[str,...],incomplete:bool, no defaults. Required report markers profile='role-link-report-v1',encoding_version='role-link-matrix-v1',role_order='STOREIBP',source_inventory_exhaustive=False. Report includes current RoleLinkCatalog (and thus unchanged generation), catalog_sha256, domain_sha256, encoding_sha256 (hash exact role/order/state/version), input:RoleLinkInput, decisions tuple[RoleLinkDecision,...], coverage:RoleLinkCoverage, status exact Literal described below. All fields required. No usage/model/prompt receipt yet; those belong to later SDK.

Rows exactly match ALL hints globally; each row's columns match that hint quote's exact domain numbers. Split semicolons;0column row must exactly ''. Positive cells one or more unique letters in ROLE_ORDER; decode to tuple of semantic role names in that order. Accept multi-role SO, reject OS/duplicates/spaces/lowercase/unknown/separator gaps/mixed state+role. Other cells exactly -,?,_. Do not fill missing cells, sort, normalize, infer negatives, or silently discard rows. '_' requires incomplete=true; '?' is distinct from not_reviewed. incomplete=true even without '_' remains conservatively incomplete. All raw/actual/nested scalar/container guards before any serialization, strict bool vs int, subclasses/unchecked copies and missing original source/gen markers rejected. Error RoleLinkContractError sanitized, no partial/source leakage.

Each RoleLinkDecision includes hint_id,number,state exact classified_roles/explicitly_unrelated/linkage_uncertain/not_reviewed,roles tuple of semantic names,quantity:ExactSpan,hint:ExactSpan,support:ExactSpan,support_sentence_ids tuple[str,...]. For every SAME-QUOTE pair, reconstruct full original numeric candidate.expression and hint exact location; support is minimal contiguous WHOLE current sentences covering full numeric expression and hint disambiguating context (if nonnull), including intermediate/blank sentences. Recheck both spans/quote/order/full quantity against current source. Retain every pair even uncertain/unrelated/unreviewed; no crossquote pairing or semantic truth claim. Do not cast into old20-sentence/5role/144diagnostic audit report; >20 current support sentences are allowed in this OWN exact report. Max288pairs follows24hints perquote *12total selectednumbers, not new hidden truncation. Coverage fields selected_numbers,total_hints,candidate_pairs,classified_pairs,unrelated_pairs,uncertain_pairs,unreviewed_pairs (strict nonnegative ints); counts exact current decisions.

Status: selected_numbers0 => not_applicable; selected>0 and pairs0 => candidate_inventory_empty. Both zero-pair cases require incomplete=false and exact complete0column carrier, implying no future model request. With pairs>0: incomplete flag => candidate_review_incomplete; else any? => candidate_review_uncertain; else reviewed_candidates. Never no_issues_flagged/approval/exhaustive. Whole quote with numbers0 must not erase other valid pairs. Store source/generation/catalog/domain/encoding hashes via catalog/report and compare every field to fresh canonical reconstruction. Validators must reject raw or actual altered decisions/coverage/roles/spans/input/status/hashes/markers before defaults/normalization; reconstruct whole original catalog from current source, not trusting stored metadata.

TDD synthetic tests: positive multirole/each state and conservative priority, unreviewed+false reject, explicit ordering regression, full row/column coverage/0columns, empty selection/no inventory/multiquote, no inference on ignored hints, exact full quantity/support/context/blank sentences including >20sentence own report;288pair boundary (no 144legacycap), roundtrip raw/actual result, every marker/metadata/source/gen/catalog/domain/encoding/input/decision/count/spans tamper, wrongtypes/subclasses/default restoration. Structural tests do not claim model classification accuracy. Reuse meaningful fixtures restoring module identity; no private actual gold/source reads. Focused/static/adjacent only. Commit/report as Task1.

## Controller gates

- [x] Task/whole-branch independent review and fresh full QA.
- [x] Fresh real-source catalogs/domain/projection and matrix roundtrips offline; preserve450code/562actual/45+59design and privacy.
- [x] Canonical docs, Draft PR and Sites with prior version preserved; archive/remove only own SDD and owned QA resources. No app/main deployment.


## Implementation evidence and remaining gate

Commits24a606a (catalog) and24874f8 (report), two new modules/two synthetic test modules; existing450 non-Markdown files unchanged. New201 tests, adjacent523; task and fresh whole-branch reviews C0/I0/M0. Fresh full QA code24874f8: Python7,480+JS820=8,300; lint/format/type/build/OpenAPI pass, failure/skip/warning0. No source/runtime/app/provider changes after QA; later commits are documentation only.

Offline current real inputs: all5 catalogs/47 exact hints and unchanged complete table packets match reviewed design; pairs15/16/6/192/42. Four synthetic assignments (?/_/-/SO) per source produce20 full report roundtrips, exact quantity/hint/support, all pairs and expected states. These are structural consistency checks, not model classification accuracy, candidate recall, importance, human approval or proof of exhaustive source coverage. Raw and actual reconstructions both pass. Existing562 actual-trial and45+59 design files unchanged; private60value scan and local document links pass. No actual provider requests, old trial reruns, SDK integration or app/main deployment.

Next: separately bounded model SDK using this explicit contract; fixed actual classifications/output completeness/candidate recall/false positives and original-result materiality, unresolved human adjudication, then app total budget/permission/durable recovery acceptance. Earlier actual2detected/6missed and3unadjudicated diagnostics remain unchanged. Reconstruction hashes ensure current-source consistency; they are not cryptographic proof that a model originally emitted particular input. The frozen upstream generation still cannot represent sources with zero numeric candidates anywhere; this change supports empty selections and numeric-free quotes within otherwise valid sources without broadening it.

Draft PR88 targets research/role-link-coverage-design; no merge. Sites v110 published2026-10-22 15:18:15 KST from ac72ba624b2d889bcb00d1adc9e8976cccdc9646; priorv109 archived. Native publication succeeded. Text/link/privacy checks:95HTML/2,180local targets/280public files/60private values. Browser QA not rerun for text-only existing layout. Owned QA container removed and loopback port closed, other resources untouched. Own SDD ledger/reviews archived privately; feature branch/worktree retained.
Loading
Loading