Skip to content

Hunk classification: suggest evolution, value or block for every hunk - #13

Merged
llima merged 10 commits into
mainfrom
feat/hunk-classification
Sep 26, 2026
Merged

llima merged 10 commits into
mainfrom
feat/hunk-classification

Conversation

@llima

@llima llima commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Version bumped to 0.4.0 (minor: new output in three commands). Merging publishes craftar@0.4.0 to npm after approval in the npm environment.
  • Hunk classification (M1 slice 4, spec 08): every hunk gets a suggested class — evolution (one side is newer text), value (identifier-like tokens swapped inside shared prose, with a suggested param.<slug>) or block (lines only one side has) — plus a reason from a closed set. A pure, deterministic heuristic in src/core/classify.ts; a suggestion never decides anything.
  • Where it shows: forge diff prints <class>: <reason> after the unchanged hunk header (and → param.… for a value); its --json hunks gain suggestion: {class, reason, tokens?} next to kind. forge variants appends counts by class ([1 evolution · 2 block]) and its --json gains classes, which add up to distance.hunks. --save-plan annotates each hunk; --plan ignores the annotation (a mangled one is dropped).
  • The LCS is shared by the line diff and the new word diff (lcsOps); diffOps behaves as before.

Emitted bytes

None change. No emitter, importer, sync, status or resolve code is touched, so no workspace sees update. The only changed committed file outside src//test/ code is the golden unify plan, regenerated by its script: it gains exactly three suggestion lines; the golden expected tree is unchanged.

Test plan

  • npm run typecheck — passes
  • npm run build — passes
  • npx vitest run --exclude test/ci.test.ts (Linux) — 398 passed / 5 skipped
  • Oracle skipped — no fixture; not impacted by this slice (no workspace byte changes)
  • CI green on Linux and Windows (Windows not run locally; assertions reviewed for platform-sensitive paths/EOL)
  • node-cli-reviewer and docs-author: clean after one correction round (parameter names made unique within a hunk even when a suffix meets another token's slug; AC 2 contract test over the whole corpus; --save-plan help text)
  • Deferred nit: the AC 2 contract test depends on the file's earlier tests having run (it fails loudly, never falsely green, when filtered alone)

A saved plan may carry the suggested class per hunk; --plan never reads it, and a
hand-mangled one is dropped instead of failing the plan.
One LCS for lines and for words, with the same tie-break; diffOps behaves as before.
A pure heuristic over the real hunk shapes: one-sided lines are blocks, a swap of
identifier-like tokens is a value with a param.<slug>, and anything else is evolution.
diffIngredients is the single place hunks are classified, so forge diff, forge variants
and --save-plan agree; a one-sided file counts as a block, keeping the sum at distance.hunks.
Each hunk header gains its class and reason (and the suggested params for a value), and
each variant its counts by class, after the unchanged prefixes.
Nothing compared the committed plan with a fresh --save-plan; now it does, and the
regenerated golden gains only the three suggestion lines.
The README rows and the --help texts of forge variants, forge diff and --save-plan
name the suggested class and say it never decides anything.
A suffixed name could equal another token's own slug (acme_api_2); the suffix now grows
until the name is free. The contract test covers every suggestion the corpus produces.
The README row said so; the option text did not.
@llima
llima merged commit 573b958 into main Sep 26, 2026
8 checks passed
@llima
llima deleted the feat/hunk-classification branch September 26, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant