feat(ledger): divergence readout — button B where button A is canon, shape history, and judged-shape recheck (#2793, milestone 294 step 7)
CI & Build / TypeScript typecheck (push) Failing after 2s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 28s
CI & Build / Python tests (push) Failing after 37s
CI & Build / Build & push image (push) Skipped
CI & Build / TypeScript typecheck (push) Failing after 2s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 28s
CI & Build / Python tests (push) Failing after 37s
CI & Build / Build & push image (push) Skipped
Every judgment now goes through one helper that remembers the fingerprint judged (classified_sha) and writes a code_shape_events row; the sync writes vanished / reappeared / drifted events and flags recheck_at when a body moves under an instance/variant. The refresh flags diverges_from on shapes new since the previous computation that sit where one canon dominates the judged siblings of their directory+kind and were not proposed as that canon (a first seed flags nothing); the write-path hint asks the same question in-band for the shapes the hook names. list_shapes(flag=divergence|recheck), shape_history(project_id, path, symbol) (read-only), coverage line/payload/ card carry divergent + recheck. Backup v8 carries the history. Plugin 0.1.36. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -447,6 +447,17 @@ interface Coverage {
|
||||
// agent's confirm, and the biggest repeats-with-no-canon families.
|
||||
proposed?: number;
|
||||
derive_groups?: DeriveGroup[];
|
||||
// The divergence readout (#2793): button B where button A is canon, and
|
||||
// judged shapes whose bodies moved since they were judged.
|
||||
divergent?: number;
|
||||
divergence?: Divergence[];
|
||||
recheck?: number;
|
||||
}
|
||||
interface Divergence {
|
||||
path: string;
|
||||
symbol: string;
|
||||
kind: string;
|
||||
canon_snippet_id: number;
|
||||
}
|
||||
|
||||
const coverage = ref<Coverage | null>(null);
|
||||
@@ -775,6 +786,28 @@ async function confirmDelete() {
|
||||
{{ g.label }} <span class="coverage-gap-count">×{{ g.size }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="coverage.divergent || coverage.recheck"
|
||||
class="coverage-gaps"
|
||||
title="Divergent: a new shape where one canon dominates its directory and that isn't proposed as that canon — button B where button A is canon. Recheck: a judged shape whose body changed since it was judged."
|
||||
>
|
||||
<span class="coverage-gaps-label">Divergence:</span>
|
||||
<span
|
||||
v-for="d in coverage.divergence || []"
|
||||
:key="d.path + '::' + d.symbol"
|
||||
class="coverage-gap-chip coverage-divergent"
|
||||
:title="d.path + ' — canon here is snippet #' + d.canon_snippet_id"
|
||||
>
|
||||
{{ d.kind === 'css' ? '.' : '' }}{{ d.symbol }}
|
||||
<span class="coverage-gap-count">→ #{{ d.canon_snippet_id }}</span>
|
||||
</span>
|
||||
<span v-if="(coverage.divergent || 0) > (coverage.divergence?.length || 0)" class="coverage-gap-chip">
|
||||
+{{ (coverage.divergent || 0) - (coverage.divergence?.length || 0) }} more
|
||||
</span>
|
||||
<span v-if="coverage.recheck" class="coverage-gap-chip">
|
||||
{{ coverage.recheck }} to recheck
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<p v-else class="coverage-empty">
|
||||
Not measured yet — Refresh reads the bound repo's definitions into
|
||||
@@ -1329,6 +1362,7 @@ async function confirmDelete() {
|
||||
font-size: 0.74rem;
|
||||
}
|
||||
.coverage-gap-count { opacity: 0.65; }
|
||||
.coverage-divergent { border-color: var(--fs-warning); }
|
||||
.coverage-empty {
|
||||
margin: 0;
|
||||
font-size: 0.8rem;
|
||||
|
||||
Reference in New Issue
Block a user