Nested drilldown: N-depth bundles, recursive descend, zoom-dive, recursive-by-default repository maps - #1
Merged
Merged
Conversation
Add a component ownership sidecar (<stem>.ownership.json, validated by
ownership.schema.json) and a pure-computation `archify locate` command
that classifies every path in a git range as touched / uncovered /
ambiguous / excluded and every component as touched / untouched / stale.
- No LLM, no inference, no map edits; ambiguity is reported, never
resolved by implicit glob precedence. `--lint` turns ambiguity into an
authoring-time failure and reports uncovered as advisory only.
- Receipt (locate-receipt.schema.json) is deterministic: stable code
point sort, no timestamps, no absolute paths, 40-char SHAs, sha256 of
map and sidecar. Two runs are byte-identical.
- Renames via `git diff --name-status -M -z`; both sides recorded and a
moved_between_components fact emitted when owners differ.
- `--facts` attaches import-edge observations; endpoints outside any
component are `componentId: null`, never dropped.
- When the map itself changed in the range, `archify compare` runs as a
child process under <out>/compare/ and is linked from mapDelta; the
locate exit code is independent of the comparison.
- Delta `navigation` field group classifies a changed `drilldown` target
as `navigation-changed` rather than `changed` or `moved`.
- SVG annotation helpers extracted from architecture-delta.mjs into
delta/svg-annotate.mjs and shared with the locate HTML.
Tests: archify/test/{locate,locate-glob,locate-html,locate-bundle,
ownership,architecture-delta,generate-validators}.test.mjs. Full suite
1170 tests / 1133 pass / 0 fail / 37 skipped on Node 26; Node 22 package
gates 18 pass. check:validators clean.
…iewer
Add `archify bundle <dir> [--check]`: one entry diagram plus up to twelve
same-directory children of any diagram type, bound by manifest.json
(bundle.schema.json) using diagram ids and two sha256 digests
(spec_sha256 for the runtime handshake, artifact_sha256 for offline
validation). Depth is fixed at two; each level keeps the 12-node cap.
- Architecture components may declare an optional `drilldown: <child id>`
(schema addition, pending maintainer sign-off). The renderer draws the
mark into the SVG so it survives canonical export.
- Viewer descends in place: parent SVG is hidden, never transformed;
breadcrumb + 96px silhouette; child opens in a same-directory iframe;
Esc/Backspace/breadcrumb ascend and restore scroll. Parent geometry is
unchanged by construction (drilldown-browser.test.mjs verifies pixels).
- Handshake: hello/ack over postMessage with unconditional event.source
check and shape validation; id/sha mismatch, unsafe filename, or a
1200 ms timeout shows an explicit stale card (built with textContent,
strings via i18n) instead of rendering the child.
- validateBundle runs derived-count checks (manifest schema first,
fail-closed), including the shared child-ownership subset rule from
locate/ownership.mjs. Required <entryId>.ownership.json; no directory
order dependence.
- Locate projection pass-through: `locate --bundle` embeds component and
child node states; parent chip "N FILES TOUCHED INSIDE" hidden at zero;
stale gets a distinct non-green treatment.
- Bundle render flags are parsed once at the renderer CLI entry and
passed explicitly; svgRootAttrs no longer reads process.argv.
- Drilldown runtime exposed as pure functions on Archify.drilldown and
unit-tested in node:vm; CI webm-artifact job runs the Chrome test.
Tests: bundle-{schema,manifest,validate,ownership}, drilldown-{mark,
viewer,stale,locate,browser}, svg-root-attrs, cli, i18n. Full suite
1170 / 1133 pass / 0 fail; Chrome tests 12/12; actionlint clean except
pre-existing SC2016 in release.yml.
…eriments - docs/decisions/identity-map-2026-09-09.md: drilldown contract, ownership sidecar spec, locate receipt format, diagnostic codes, "what we do not do", E1/E3 raw numbers, PR tt-a1i#269/tt-a1i#281 gap assessment, schema changes pending sign-off, code-vs-draft divergences, open questions. Every decision cites path:line. - E3 (100-commit replay of a hand-written self-map): 9/100 commits needed a map edit, 0 ambiguous, uncovered returns to 0; sources line anchors decayed 68.7% over the same range. E1: 8/50 fix commits structural (16%), supporting "orientation", not defect-finding, wording. - docs/cases/archify-self/: ten-component self-map, two children (architecture + workflow), sidecars, manifest, receipts for PR tt-a1i#256 and PR tt-a1i#352 (regenerable; only receipts are kept), README with commands. - archify/references/{locate,drilldown-bundles}.md; SKILL.md fast path unchanged. CHANGELOG entry; one-clause ROADMAP note that the diagram diff stance still holds.
archify/assets/template.html gained the drilldown runtime and locate
projection styles, so every artifact that embeds the template is
rebuilt per CONTRIBUTING:
- archify.zip via scripts/build-zip.sh on Node 22.23.2
(1,959,997 bytes, +82,567 vs origin/main)
- packaged and root examples/*.html goldens, checkout-platform-delta
html + receipt (compare embeds two explorers)
- docs/gallery via scripts/build-gallery.mjs (11 artifacts / 99 checks)
- docs/cases/mco-runtime.architecture.html and
experiments/mco-showcase/mco-runtime.html (byte-repro against mco
@ 9f1a1cf)
- docs/assets/archify-live-proof.{gif,json}: readme-showcase.test.mjs
pins the gallery artifact sha256 into the receipt, forcing the rebuild
No SVG geometry changes in any golden; diffs are viewer chrome only.
CI's headless Chrome caught a refit on ascend: the first implementation hid the entry SVG with display:none, so it left layout, the adaptive reader re-measured the canvas as overflowing on reveal and shrank --archify-reader-width from 1376px to 960px, scaling every node box by 0.691. Reproduced at 1440x900 with the test's 240px canvas pinch. The entry SVG now stays in flow with visibility:hidden while the child is overlaid, and the reader/viewer-chrome measurers are frozen while data-drilldown-level is set, so no fit runs at all. drilldown-browser asserts pixel-identical node boxes at 1440x900 and 800x600 with a child taller than the parent canvas. Decision record §3.7 and the drilldown reference describe the mechanism and why. Goldens, gallery, MCO artifacts and README GIF rebuilt for the template change. npm test: 1170 / 1133 pass / 0 fail / 37 skipped.
Generalize drilldown bundles from a fixed two-level parent/child pair to a tree of arbitrary depth (2-8): any diagram in the bundle may declare its own drilldown, max_depth is computed from the tree, ownership sidecars bind to whichever diagram a drilldown row names as parent, and excluded globs accumulate down the full chain. Adds bundle-depth and locate-bundle-depth test coverage plus the deep-checkout fixtures. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Viewer now reads a bundle's full tree instead of only its first level: a non-leaf child offers the same Descend control and drilldown mark for its own components, so a diagram can be descended into a second and third time (iframe inside iframe). A parent hands its child a scoped subtree of the manifest inside the existing handshake hello; every navigation request/reply (hello ack, escape, breadcrumb, ascend) carries a session number (and ascend messages a request id) so a delayed or superseded ack/escape/breadcrumb update is ignored — the Locate projection message carries no session at all, since it is not part of this handshake. The breadcrumb is drawn once at the root as the full chain to whichever level is deepest; Esc/Backspace close exactly one level from wherever focus is, and a breadcrumb rung's click ascends directly to that depth via the new ascendTo/closeInnermost/escapeToParent API. Readiness (data-drilldown-state="open") is now gated only on a successful handshake ack. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A nested child still renders its own full page chrome (header, page padding) inside its shrinking iframe box; the toolbar/legend column .header's padding-right normally reserves is already hidden while nested, so it is pure waste here. Four html[data-bundle-nested="true"] rules reclaim that space. Pure CSS, no behavior change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd + nested CSS) Rebuild archify.zip, the five bundled examples (default root and ../examples), the checkout-platform-delta compare artifact/receipt, the docs gallery, and the README showcase GIF from PR1's own head (bundle N-depth + recursive descend + nested-chrome CSS only — no camera/dive bytes yet). Excludes docs/cases/ archify-self and docs/cases/mco-runtime.*/experiments/mco-showcase, which need checkouts not available here and are not reproduced in this run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Viewer now zooms continuously between 1x and 3x around the pointer
(mouse wheel, Ctrl+wheel trackpad pinch) or the two-finger touch pinch
midpoint, alongside the existing +/-/0 controls. viewer-camera.js adds
zoomAt(nextScale, clientX, clientY, { snap }) anchored on a caller-supplied
point via svgOrigin(); a gesture that cannot change scale (1x floor) leaves
page scrolling alone and emits minZoomOut instead. Pinch pointer capture is
held for the gesture's lifetime, drags are scoped to the pointer that
started them, and a third touch during an active pinch cannot start a new
drag. onChange/offChange subscribe to every apply() with a transitioning
flag that settles on transitionend or a 200ms fallback; on/off cover
minZoomOut and gesture events. viewer-wheel-browser.test.mjs covers wheel/
pinch/minZoomOut end to end in a real Chrome; its checks wait for the
transform to stay stable for a 260ms minimum before asserting on it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A new Archify.dive (viewer/dive.js) lets a reader turn manual zoom itself into drilldown navigation. Off by default (localStorage['archify-dive'], toggled by Z or a .diagram-nav button shown only when the current diagram has a drilldown row). The precise trigger: manual camera mode (never a semantic Focus/Guided/Radar reveal), scale >= 2.5, no prefers-reduced-motion, not the mobile-contained wide-diagram mode, none of Route Probe / Semantic Lens / Presentation active (Intent Trace is deliberately excluded from this blocking list — its own "active" node is just a 90ms fine-pointer hover preview, true almost the whole time a real mouse hovers the node being wheel-zoomed), no redive lock, rearmed, and no descent already open or mid-handshake; once eligible, a candidate node gets a visible 250ms dwell (a ring on the node plus a status line) before calling the existing Archify.drilldown.descend. The dwell is cancelled by any camera movement beyond a small epsilon (0.004 scale, 0.5px x/y) versus where it started, or by losing eligibility for any other reason, on either the transitioning or settled onChange notification. Inside a nested child, two zoom-out gestures at the 1x floor with distinct (source, gestureId) pairs within 600ms ascend one level the same way a breadcrumb click does. After an ascend, a redive lock and a separate `rearmed` flag both go false; a new dwell needs both cleared. The lock clears on a fresh pointerdown/keydown anywhere in the document, or on a gesture 'start' once the document has gone >=400ms (GESTURE_SILENCE_MS) without any gesture activity at all — time-based and document-local, deliberately not a comparison of gesture ids, since the ascend-triggering gesture happened in a different document with its own id space. `rearmed` only flips back to true once the camera is later seen at scale < 2.5 on a settled snapshot, i.e. the reader has zoomed back out past the dive threshold at least once since the ascend. viewer-camera.js is unchanged by this feature; export/print/SVG bytes are unaffected. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rebuild archify.zip, the five bundled examples (default root and ../examples), the checkout-platform-delta compare artifact/receipt, the docs gallery, and the README showcase GIF now that camera gestures and dive are in the template, on top of PR1's own rebuild. Same docs/cases/archify-self and docs/cases/mco-runtime.*/experiments/ mco-showcase exclusion as commit 4 (needs checkouts not available here). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ream drafts Working documents behind the feat/nested-drilldown branch: the phase plan, the Sonnet implementation briefs and reports for phases 0-5 and the commit split, the Codex astra second-opinion reviews for every phase, the Faz 5 acceptance evidence, and the upstream drafts (PR1/PR2 descriptions, the issue tt-a1i#280 comment, the commit plan). Multi-MB test transcript logs are ignored, not committed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… plays Presentation only hides chrome and puts the diagram on stage; a reader zooming a drilldown node by hand there is exactly the audience dive is for. The blocker that made Presentation an exclusive mode is replaced by `Archify.guidedViews.isPlaying()`: a playing guided story (whose semantic camera already never dives) is the genuinely incompatible surface. Route Probe and Semantic Lens blockers, the Intent Trace exclusion, and the redive lock are unchanged. `viewer/README.md` (dive contract eligibility list) and the CHANGELOG bullet state the new blocking set; `archify/assets/template.html` regenerated (`check:viewer` clean; drilldown-dive-browser and generate-viewer tests 290/290). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Same file set and commands as the PR2 rebuild: render:examples (both roots, plus examples/web-app.html rendered directly), the checkout compare artifact + receipt, build:gallery, build:readme-showcase and scripts/build-zip.sh. Gates: release-package-gates, readme-showcase, architecture-delta and generate-viewer tests 323/323 (2 skipped). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dles SKILL.md gains "Repository maps: recursive drilldown bundles": a whole-repository/system request defaults to a bundle authored outside-in — survey the repo, write the level-0 candidate at once, then run a decomposition test per architecture component (several distinct internal parts, own request path, own stores/boundaries, and inlining would break the twelve-node cap), recurse through architecture children only (other types are leaves, 2–8 total levels), author independent children in parallel as fresh work from their own source evidence, deliver each diagram, then `archify bundle <dir>` as the single sanctioned re-render of delivered HTML, browser evidence on the final entry, and a tree report with stopping decisions. The reference's "When to use it" points back at the section. CHANGELOG bullet; archify.zip rebuilt (SKILL.md and the reference are packaged). Codex astra review: DÜZELTMEYLE KABUL, all six findings applied (narrow single-diagram exception, leaf/recursion rule, source survey before schema reading, deliver-vs-bundle re-render exception, softened file:// claim, lighter report duty). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…; install from this fork All three READMEs and the landing pages now install from `Cagatay342/archify` (`npx skills add Cagatay342/archify -g`, the explicit Cursor command, `skills use`) and the quick-start repository prompt asks for a nested drilldown bundle, with one line on the outside-in default. The temporary fork blockquote is gone. Kept within the README budget tests (≤295 lines, ≤2085 words, mirrors identical); `cursor-onboarding.test.mjs`'s install constant follows the fork. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
max_depth2–8, tree validation, ownership sidecar chain generalized past one hop.onChange,minZoomOut.viewer/dive.js, opt-inZ): zoom a drilldown node past 2.5× → 250 ms dwell → descend; two zoom-outs at 1× ascend; redive lock; allowed in Presentation, blocked only while a guided story plays.SKILL.md"Repository maps: recursive drilldown bundles" — whole-repository maps default to an outside-in bundle with a per-component decomposition test, parallel children,archify bundle <dir>.archify.zip, examples, gallery, showcase GIF).Test plan
npm run check:viewer,check:validatorsat every viewer/schema commitdocs/diagrams/nested/(3 levels,bundle --check10/10)update-notifiertiming tests,motion-governor-browserhang.🤖 Generated with Claude Code