Skip to content

Commit 66ac3b3

Browse files
committed
Strengthen edge case validation evidence
1 parent 7bc6051 commit 66ac3b3

3 files changed

Lines changed: 7 additions & 4 deletions

File tree

‎docs/experiments/review-summary-edge-cases.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ Validated on 2026-09-23 from `5a2685c`, before selecting real issues for the pla
44

55
## Renamed-file reassignment
66

7-
A real-Git fixture declares `retry.ts` → `renamed.ts`, then creates an unplanned rename with a content edit. The review exposes unplanned segments on both the removed old path and added new path. Manually assigning every segment to the rename item leaves each segment in scope.
7+
A real-Git fixture declares `retry.ts` → `renamed.ts`, then creates an unplanned rename with a content edit. The review exposes removed and added text segments with `-` and `+` operations. The fixture resolves the removed side through `oldPath` and the added side through `path`, verifies both declared names, then manually assigns both segments. Each remains in scope.
88

99
Result: no defect reproduced. `ReviewService` evaluates a manual assignment against both `path` and `renamed_from`. The integration fixture remains as coverage.
1010

1111
## Literal pathspec metacharacters
1212

13-
A planting fixture uses the literal declared filename `*.txt` beside a decoy `a.txt`. An owned commit edits the literal file; a later commit removes it while retaining the decoy. The plant helper rejects the history at its declared-file transition check with `Declared plant needs a regular file retained through the remaining history.`
13+
A planting fixture uses the literal declared filename `*.txt` beside a decoy `a.txt`. An owned commit edits the literal file; a later commit removes it while retaining the decoy. Direct controls prove `git ls-tree ... -- '*.txt'` returns no match and that `ls-tree` rejects `:(glob)` pathspec magic as unsupported. The plant helper then rejects the history at its declared-file transition check with `Declared plant needs a regular file retained through the remaining history.`
1414

1515
Result: no defect reproduced. The decoy does not satisfy the literal transition check. The fixture remains as coverage for Git pathspec metacharacters.
1616

‎test/plant.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ it('treats metacharacters literally when checking declared-file transitions',()=
4040
const config={database:join(root,'review.sqlite'),repository,identity,pathIdentity:{caseSensitive:true as const,unicodeNormalization:'none' as const},demo:false};
4141
const store=new Store(config.database);
4242
try{store.createPlan(JSON.stringify(plan),'json',{identity,issue:10,baseEntries:['*.txt','a.txt'].map(path=>({path,kind:'file' as const})),pathKey:path=>path,allowedCommands:[]},base,head);store.recordHistory(identity,{revision:1,snapshotId:store.getSnapshot(identity).id},base,head,[{sha:owned,owner:'P1',origin:'owned',sourceSha:null}]);}finally{store.close();}
43+
expect(git('ls-tree','--name-only',head,'--','*.txt')).toBe('');
44+
expect(()=>git('ls-tree','--name-only',head,'--',':(glob)*.txt')).toThrow(/pathspec magic not supported/);
4345
expect(()=>plant(config,join(root,'experiment'),{declaredText:'planted',undeclaredText:'outside',undeclaredPath:'extra.txt'})).toThrow(/Declared plant needs a regular file retained/);
4446
},15000);
4547

‎test/review.test.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ it('keeps both sides of a declared rename in scope after manual reassignment',()
2525
writeFileSync(join(config.repository,'renamed.ts'),'export function delay(attempt: number) {\n return Math.min(5000, 200 * 2 ** attempt);\n}\n');
2626
execFileSync('git',['-c','core.hooksPath=/dev/null','add','-A'],{cwd:config.repository});
2727
execFileSync('git',['-c','core.hooksPath=/dev/null','commit','-m','Rename retry implementation'],{cwd:config.repository,stdio:'pipe'});
28-
let view=service.load();const candidates=view.segments.filter(segment=>segment.row==='Unplanned'&&['retry.ts','renamed.ts'].includes(segment.path));
29-
expect(new Set(candidates.map(segment=>segment.path))).toEqual(new Set(['retry.ts','renamed.ts']));
28+
let view=service.load();const candidates=view.segments.filter(segment=>segment.row==='Unplanned'&&segment.kind==='text'&&['-','+'].includes(segment.operation)&&['retry.ts','renamed.ts'].includes(segment.operation==='-'?segment.oldPath??segment.path:segment.path));
29+
expect(new Set(candidates.map(segment=>segment.operation))).toEqual(new Set(['-','+']));
30+
expect(new Set(candidates.map(segment=>segment.operation==='-'?segment.oldPath??segment.path:segment.path))).toEqual(new Set(['retry.ts','renamed.ts']));
3031
for(const candidate of candidates){view=service.act({action:'assign',key:candidate.key,item:'P1',token:view.token});expect(view.segments.find(segment=>segment.key===candidate.key)?.scope).toBe('in-scope');}
3132
});
3233
it('persists bounded per-item notes without creating a plan revision',()=>{

0 commit comments

Comments
 (0)