From ca91f50ab9c6ece58a6095149d5ed47ae6c61f7f Mon Sep 17 00:00:00 2001 From: Tom Softreck Date: Wed, 26 Aug 2026 02:54:35 +0200 Subject: [PATCH 1/2] docs(ticket-088): plan same-source conflict repair --- TODO.md | 4 +++ project/TICKETS.md | 1 + project/ticket-088/README.md | 32 +++++++++++++++++++++ project/ticket-088/ai-codex-logs.txt | 3 ++ project/ticket-088/ai-codex.md | 32 +++++++++++++++++++++ project/ticket-088/changelog.md | 11 ++++++++ project/ticket-088/intent.json | 42 ++++++++++++++++++++++++++++ project/ticket-088/preprompt.md | 8 ++++++ 8 files changed, 133 insertions(+) create mode 100644 project/ticket-088/README.md create mode 100644 project/ticket-088/ai-codex-logs.txt create mode 100644 project/ticket-088/ai-codex.md create mode 100644 project/ticket-088/changelog.md create mode 100644 project/ticket-088/intent.json create mode 100644 project/ticket-088/preprompt.md diff --git a/TODO.md b/TODO.md index 92bdcfc8..e4549702 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,10 @@ ## Active tickets +- [ ] [`ticket-088`](project/ticket-088/README.md) — prevent overlapping + projections of one source sentence from creating a false blocking polarity + contradiction. Current state: `IN_PROGRESS / EDIT`; workstream: `core-dsl`. + - [ ] [`ticket-054`](project/ticket-054/README.md) — restore skills-agent discovery, prove a todo2code → Repair PR → independent Validator hand-off, then add three bounded todo2code-grounded skills. Current state: diff --git a/project/TICKETS.md b/project/TICKETS.md index ab6d7096..1ee40406 100644 --- a/project/TICKETS.md +++ b/project/TICKETS.md @@ -61,4 +61,5 @@ of `project/README.md`, which remains a generated technical-analysis artifact. | **ticket-083** | [`README.md`](./ticket-083/README.md) | [`preprompt.md`](./ticket-083/preprompt.md) | - | [`ai-codex.md`](./ticket-083/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-083/ai-codex-logs.txt) | [`changelog.md`](./ticket-083/changelog.md) | | **ticket-084** | [`README.md`](./ticket-084/README.md) | [`preprompt.md`](./ticket-084/preprompt.md) | - | [`ai-codex.md`](./ticket-084/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-084/ai-codex-logs.txt) | [`changelog.md`](./ticket-084/changelog.md) | | **ticket-085** | [`README.md`](./ticket-085/README.md) | [`preprompt.md`](./ticket-085/preprompt.md) | - | [`ai-codex.md`](./ticket-085/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-085/ai-codex-logs.txt) | [`changelog.md`](./ticket-085/changelog.md) | +| **ticket-087** | [`README.md`](./ticket-087/README.md) | [`preprompt.md`](./ticket-087/preprompt.md) | - | [`ai-codex.md`](./ticket-087/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-087/ai-codex-logs.txt) | [`changelog.md`](./ticket-087/changelog.md) | diff --git a/project/ticket-088/README.md b/project/ticket-088/README.md new file mode 100644 index 00000000..827534dc --- /dev/null +++ b/project/ticket-088/README.md @@ -0,0 +1,32 @@ +# Ticket 088: Do not contradict overlapping same-source excerpts + +- **ID**: ticket-088 +- **Owner**: Founder session request (user:tom) +- **Status**: PLAN +- **Workflow state**: WAIT_FOR_APPROVAL +- **Created**: 2026-08-26 + +## Goal and scope + +Prevent the linker from emitting a blocking contradiction when two deterministic +extractors project overlapping excerpts from the same source location and one +excerpt ends before the full sentence's negation. Preserve genuine conflicts +between disjoint statements and different sources. + +## Acceptance criteria + +- [x] AC-01: The active Founder request authorizes continued autonomy repair, + protected publication and deployment. +- [ ] AC-02: Opposite-polarity records from the same normalized source path and + overlapping line range cannot produce `contradicts`. +- [ ] AC-03: Opposite-polarity records from distinct sources can still produce + a blocking contradiction when semantic evidence clears the threshold. +- [ ] AC-04: The exact PLF-8307 replay has no new blocking delta for AC-03 / + TICKET-071. +- [ ] AC-05: Focused, full Node, governance, Docker and whitespace gates pass. + +## Participants + +- Human participant: user:tom through the active session request; no user-* file + was created by this script. +- Agent participant: [ai-codex.md](ai-codex.md) diff --git a/project/ticket-088/ai-codex-logs.txt b/project/ticket-088/ai-codex-logs.txt new file mode 100644 index 00000000..5714ca89 --- /dev/null +++ b/project/ticket-088/ai-codex-logs.txt @@ -0,0 +1,3 @@ +2026-08-26 SESSION_EXECUTION_AUTHORIZATION Founder requested continued autonomy repair, publication and deployment +2026-08-26 PLF8307_EVIDENCE Core 1585/1585 and governance passed; comparison blocked on REL-f32bb9c9b1ce836495f3 between project/ticket-071/README.md lines 32-33 and line 32 +2026-08-26 ROOT_CAUSE full document excerpt is negative because it contains 'not as Sprawdzanie'; shorter overlapping NL excerpt ends before that negation and is positive; these are not independent contrary claims diff --git a/project/ticket-088/ai-codex.md b/project/ticket-088/ai-codex.md new file mode 100644 index 00000000..450dcf31 --- /dev/null +++ b/project/ticket-088/ai-codex.md @@ -0,0 +1,32 @@ +--- +participant-id: agent:codex +participant: codex +role: agent +ticket: ticket-088 +--- +# Participant: codex (AI agent) + +## Understanding + +PLF-8307 passed 1585 Core tests and governance but publication stopped with +`blocking_delta=1`. Exact replay proved the added contradiction joins a full +documentation sentence at lines 32-33 with a shorter NL projection at line 32 +from the same ticket README. The shorter projection ends before "not as +Sprawdzanie", so it is not independent contrary evidence. + +## Execution plan + +1. Commit this source-bounded plan before implementation. +2. Add a linker regression for overlapping same-source excerpts while retaining + a distinct-source contradiction control. +3. Apply the narrow source-overlap guard and run focused/full verification. +4. Replay the exact PLF-8307 patch, publish through Validator, then repin the + coding-agent runtime and retry the governed Core ticket. + +## Actual changes + +- Plan prepared; the active Founder request supplies execution authorization. + +## Blockers + +- None inside the recorded bounded repair; trusted merge remains independent. diff --git a/project/ticket-088/changelog.md b/project/ticket-088/changelog.md new file mode 100644 index 00000000..bba2c9e5 --- /dev/null +++ b/project/ticket-088/changelog.md @@ -0,0 +1,11 @@ +# Ticket Changelog (ticket-088) + +## [0.1.0] - 2026-08-26 + +- Initial governance scaffold created. +- No human participant identity or content was generated. + +## [0.2.0] - 2026-08-26 + +- Bound the repair to the exact PLF-8307 same-source overlap evidence and kept + independent cross-source contradictions in scope as a negative control. diff --git a/project/ticket-088/intent.json b/project/ticket-088/intent.json new file mode 100644 index 00000000..b3a83d26 --- /dev/null +++ b/project/ticket-088/intent.json @@ -0,0 +1,42 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-088", + "summary": "Do not contradict overlapping excerpts projected from the same source location", + "workstream": "core-dsl", + "classification": { + "kind": "BUG", + "priority": "P1", + "origin": "health" + }, + "allowedPaths": ["project/ticket-088/**", "TODO.md", "project/TICKETS.md", "src/graph/linker.ts", "test/linker-pairing.test.ts"], + "forbiddenPaths": ["project/ticket-*/user-*.md"], + "stacks": [], + "dependsOn": [], + "conflictsWith": [], + "integrationTicket": null, + "delivery": { + "acceptedBaseSha": "43f5574918a9e703dd998e95b21d86479a2fd315", + "targetBranch": "main", + "outcome": "Workspace comparison does not block a valid change because a shorter extractor projection omits the later negation in the same sentence.", + "nonGoals": ["No global polarity suppression", "No comparison threshold change", "No public schema change", "No direct merge"], + "complexity": "XS", + "estimatedMinutes": 20, + "budgets": {"maxImplementationFiles": 2, "maxAffectedComponents": 1, "maxPublicInterfaceChanges": 0, "maxRuntimeDependencies": 0}, + "architecture": { + "status": "accepted", + "decision": "Treat overlapping source ranges in one normalized source file as alternate projections of one statement for contradiction classification only; retain their ordinary source-kind relation.", + "components": [{"name": "intent-linker", "paths": ["src/graph/linker.ts", "test/linker-pairing.test.ts"]}], + "responsibilityChanges": false, + "interfaceChanges": [], + "dataChanges": [], + "ui": {"impact": "none", "states": [], "evidence": []}, + "rollback": "Revert the exact protected merge; the prior fail-closed false positive returns." + }, + "runtimeDependencies": [], + "validation": [ + {"criterion": "AC-02,AC-03", "commands": ["npm run build", "node --test dist/test/linker-pairing.test.js"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, + {"criterion": "AC-04", "commands": ["t2c compare-workspace --base 3e88a1d --task project/ticket-071/README.md --nl-mode deterministic --markdown-mode deterministic --communication-mode deterministic"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, + {"criterion": "AC-05", "commands": ["npm run verify", "./project/governance-check.sh --actor agent", "make docker-smoke", "git diff --check"], "evidence": "project/ticket-088/ai-codex-logs.txt"} + ] + } +} diff --git a/project/ticket-088/preprompt.md b/project/ticket-088/preprompt.md new file mode 100644 index 00000000..559facf5 --- /dev/null +++ b/project/ticket-088/preprompt.md @@ -0,0 +1,8 @@ +# Ticket preprompt + +- **Task ID**: ticket-088 +- **Task title**: Do not contradict overlapping same-source excerpts +- **Created**: 2026-08-26T00:53:48Z + +Keep executable implementation outside this governance/evidence directory. +Read a human-owned user-*.md file only when one exists. From a37f4020c0f0719cbb1a9336c9d03b895071972d Mon Sep 17 00:00:00 2001 From: Tom Softreck Date: Wed, 26 Aug 2026 03:04:14 +0200 Subject: [PATCH 2/2] fix(ticket-088): ignore overlapping source projection conflicts --- project/ticket-088/README.md | 12 ++--- project/ticket-088/ai-codex-logs.txt | 3 ++ project/ticket-088/ai-codex.md | 11 ++++- project/ticket-088/changelog.md | 9 ++++ project/ticket-088/intent.json | 3 +- src/graph/linker.ts | 23 +++++++++- test/linker-pairing.test.ts | 68 ++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 11 deletions(-) diff --git a/project/ticket-088/README.md b/project/ticket-088/README.md index 827534dc..db0cdd0f 100644 --- a/project/ticket-088/README.md +++ b/project/ticket-088/README.md @@ -2,8 +2,8 @@ - **ID**: ticket-088 - **Owner**: Founder session request (user:tom) -- **Status**: PLAN -- **Workflow state**: WAIT_FOR_APPROVAL +- **Status**: IN_PROGRESS +- **Workflow state**: PUBLICATION - **Created**: 2026-08-26 ## Goal and scope @@ -17,13 +17,13 @@ between disjoint statements and different sources. - [x] AC-01: The active Founder request authorizes continued autonomy repair, protected publication and deployment. -- [ ] AC-02: Opposite-polarity records from the same normalized source path and +- [x] AC-02: Opposite-polarity records from the same normalized source path and overlapping line range cannot produce `contradicts`. -- [ ] AC-03: Opposite-polarity records from distinct sources can still produce +- [x] AC-03: Opposite-polarity records from distinct sources can still produce a blocking contradiction when semantic evidence clears the threshold. -- [ ] AC-04: The exact PLF-8307 replay has no new blocking delta for AC-03 / +- [x] AC-04: The exact PLF-8307 replay has no new blocking delta for AC-03 / TICKET-071. -- [ ] AC-05: Focused, full Node, governance, Docker and whitespace gates pass. +- [x] AC-05: Focused, full Node, governance, Docker and whitespace gates pass. ## Participants diff --git a/project/ticket-088/ai-codex-logs.txt b/project/ticket-088/ai-codex-logs.txt index 5714ca89..04d30b9b 100644 --- a/project/ticket-088/ai-codex-logs.txt +++ b/project/ticket-088/ai-codex-logs.txt @@ -1,3 +1,6 @@ 2026-08-26 SESSION_EXECUTION_AUTHORIZATION Founder requested continued autonomy repair, publication and deployment 2026-08-26 PLF8307_EVIDENCE Core 1585/1585 and governance passed; comparison blocked on REL-f32bb9c9b1ce836495f3 between project/ticket-071/README.md lines 32-33 and line 32 2026-08-26 ROOT_CAUSE full document excerpt is negative because it contains 'not as Sprawdzanie'; shorter overlapping NL excerpt ends before that negation and is positive; these are not independent contrary claims +2026-08-26 FOCUSED_TEST node --test dist/test/linker-pairing.test.js passed 16/16 +2026-08-26 EXACT_REPLAY base blocking=1 workspace blocking=1 blocking_delta=0 conflicting_topics=null for Core candidate PLF-8307 +2026-08-26 VALIDATION npm run verify, make docker-smoke, governance GOV-PASS and git diff --check passed diff --git a/project/ticket-088/ai-codex.md b/project/ticket-088/ai-codex.md index 450dcf31..e55cc635 100644 --- a/project/ticket-088/ai-codex.md +++ b/project/ticket-088/ai-codex.md @@ -25,8 +25,15 @@ Sprawdzanie", so it is not independent contrary evidence. ## Actual changes -- Plan prepared; the active Founder request supplies execution authorization. +- Added a source-overlap guard that normalizes paths and suppresses only a + contradiction between records whose source line ranges overlap. +- Added a regression reproducing the PLF-8307 document/NL projection and a + negative control proving that an independent source can still contradict it. +- Replayed the exact PLF-8307 candidate: the base and workspace each retain one + pre-existing blocking diagnostic, so the candidate adds no blocking delta. +- Passed the focused tests, full repository verification, Docker smoke, + governance and whitespace gates. ## Blockers -- None inside the recorded bounded repair; trusted merge remains independent. +- Trusted merge remains a separate Validator Agent decision. diff --git a/project/ticket-088/changelog.md b/project/ticket-088/changelog.md index bba2c9e5..0371c3e9 100644 --- a/project/ticket-088/changelog.md +++ b/project/ticket-088/changelog.md @@ -9,3 +9,12 @@ - Bound the repair to the exact PLF-8307 same-source overlap evidence and kept independent cross-source contradictions in scope as a negative control. + +## [0.3.0] - 2026-08-26 + +- Prevented overlapping projections of one normalized source location from + producing a false contradiction. +- Added the PLF-8307 regression and an independent-source contradiction + control. +- Recorded a zero blocking-delta replay plus successful full, Docker, + governance and whitespace validation. diff --git a/project/ticket-088/intent.json b/project/ticket-088/intent.json index b3a83d26..05232628 100644 --- a/project/ticket-088/intent.json +++ b/project/ticket-088/intent.json @@ -34,7 +34,8 @@ }, "runtimeDependencies": [], "validation": [ - {"criterion": "AC-02,AC-03", "commands": ["npm run build", "node --test dist/test/linker-pairing.test.js"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, + {"criterion": "AC-02", "commands": ["npm run build", "node --test dist/test/linker-pairing.test.js"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, + {"criterion": "AC-03", "commands": ["npm run build", "node --test dist/test/linker-pairing.test.js"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, {"criterion": "AC-04", "commands": ["t2c compare-workspace --base 3e88a1d --task project/ticket-071/README.md --nl-mode deterministic --markdown-mode deterministic --communication-mode deterministic"], "evidence": "project/ticket-088/ai-codex-logs.txt"}, {"criterion": "AC-05", "commands": ["npm run verify", "./project/governance-check.sh --actor agent", "make docker-smoke", "git diff --check"], "evidence": "project/ticket-088/ai-codex-logs.txt"} ] diff --git a/src/graph/linker.ts b/src/graph/linker.ts index b3fed51f..69538849 100644 --- a/src/graph/linker.ts +++ b/src/graph/linker.ts @@ -1,7 +1,7 @@ import { createRelationId, graphFingerprint } from '../core/id.js'; import { assertIntentRecords } from '../core/schema.js'; import { keywords, topicKeywords } from '../core/text.js'; -import { pathAliases, symbolAliases } from '../core/target.js'; +import { normalizePath, pathAliases, symbolAliases } from '../core/target.js'; import type { IntentGraph, IntentRecord, IntentRelation, RelationType, SourceKind } from '../core/types.js'; import { buildSymbolResolutionIndex, hasResolvedNlAstSymbolPair, type SymbolResolutionIndex } from './symbol-resolution.js'; import { aggregateCapabilityOverlap, isFileAggregate } from './capability-evidence.js'; @@ -443,7 +443,9 @@ function isModuleTopicEvidencePair(left: IntentRecord, right: IntentRecord): boo function determineRelation(left: IntentRecord, right: IntentRecord, evidence: PairEvidence): DirectedRelation { // `scorePair` already computed this over the same two strings. const textScore = evidence.textScore; - if (left.statement.polarity !== right.statement.polarity && textScore >= 0.45) { + if (left.statement.polarity !== right.statement.polarity + && textScore >= 0.45 + && !isOverlappingSameSourceProjection(left, right)) { return { from: left, to: right, type: 'contradicts' }; } if (left.source.kind === right.source.kind && textScore >= 0.82) { @@ -455,6 +457,23 @@ function determineRelation(left: IntentRecord, right: IntentRecord, evidence: Pa return { from: left, to: right, type: 'related_to' }; } +/** + * Two extractors may project different spans from one physical sentence. A + * line-level NL projection can end before a continuation containing negation, + * while a document projection covers the complete sentence. Those records are + * alternate observations of one source location, not independent contrary + * claims. Disjoint ranges in the same file remain eligible for contradiction. + */ +function isOverlappingSameSourceProjection(left: IntentRecord, right: IntentRecord): boolean { + const leftPath = left.source.path ? normalizePath(left.source.path) : ''; + const rightPath = right.source.path ? normalizePath(right.source.path) : ''; + if (!leftPath || leftPath !== rightPath) return false; + const leftLines = left.source.lines; + const rightLines = right.source.lines; + if (!leftLines || !rightLines) return false; + return leftLines.start <= rightLines.end && rightLines.start <= leftLines.end; +} + function relationForSourceKinds(left: IntentRecord, right: IntentRecord): DirectedRelation | null { for (const rule of SOURCE_RELATION_RULES) { const relation = matchSourceRule(left, right, rule); diff --git a/test/linker-pairing.test.ts b/test/linker-pairing.test.ts index ccec1b64..ffcab171 100644 --- a/test/linker-pairing.test.ts +++ b/test/linker-pairing.test.ts @@ -25,6 +25,74 @@ function astFact(path: string, symbol: string, object: string): IntentRecord { }); } +function polarityProjection(options: { + sourceKind: 'document' | 'nl'; + sourcePath: string; + sourceLines: { start: number; end: number }; + text: string; + polarity: 'positive' | 'negative'; +}): IntentRecord { + return buildRecord({ + kind: options.sourceKind === 'document' ? 'documentation_statement' : 'declared_intent', + action: 'document', + object: 'unverified renders as terminal bounded observation', + target: { symbols: ['unverified'] }, + text: options.text, + polarity: options.polarity, + lifecycle: 'proposed', + sourceKind: options.sourceKind, + sourcePath: options.sourcePath, + sourceLines: options.sourceLines, + extractor: 'test', + epistemicClass: 'declaration', + confidence: 0.8, + basis: ['fixture'], + }); +} + +test('overlapping excerpts from one source location cannot contradict each other', () => { + const document = polarityProjection({ + sourceKind: 'document', + sourcePath: './project/ticket-071/README.md', + sourceLines: { start: 32, end: 33 }, + text: 'unverified renders as a terminal bounded observation, not as Checking', + polarity: 'negative', + }); + const shortenedNl = polarityProjection({ + sourceKind: 'nl', + sourcePath: 'project/ticket-071/README.md', + sourceLines: { start: 32, end: 32 }, + text: 'unverified renders as a terminal bounded observation', + polarity: 'positive', + }); + + const graph = linkIntentRecords([document, shortenedNl], AT); + assert.equal(graph.relations.length, 1); + assert.equal(graph.relations[0]?.type, 'documents'); + assert.ok(!diagnoseGraph(graph, AT).diagnostics.some((item) => item.code === 'CONFLICTING_INTENT')); +}); + +test('independent opposite-polarity sources still create a blocking contradiction', () => { + const document = polarityProjection({ + sourceKind: 'document', + sourcePath: 'project/ticket-071/README.md', + sourceLines: { start: 32, end: 33 }, + text: 'unverified renders as a terminal bounded observation, not as Checking', + polarity: 'negative', + }); + const independentNl = polarityProjection({ + sourceKind: 'nl', + sourcePath: 'TASK.md', + sourceLines: { start: 1, end: 1 }, + text: 'unverified renders as a terminal bounded observation', + polarity: 'positive', + }); + + const graph = linkIntentRecords([document, independentNl], AT); + assert.equal(graph.relations[0]?.type, 'contradicts'); + assert.ok(diagnoseGraph(graph, AT).diagnostics.some((item) => item.code === 'CONFLICTING_INTENT')); +}); + test('Two unrelated AST facts sharing only a file are not linked', () => { const graph = linkIntentRecords([ astFact('src/module.ts', 'parseHeaders', 'nagłówki żądania HTTP'),