見聞 Kenbun implementation report

Implementation complete · 10 July 2026

From Python scanner to multi-ecosystem detector.

Kenbun now identifies application boundaries across Python, JavaScript, and TypeScript repositories; understands modern frontend frameworks and five workspace managers; and reports one normalized, platform-neutral schema without executing repository code.

Branch main · working tree Schema version 1 Scope Kenbun + test-patrick only State local changes uncommitted
20new public fixture repositories
12primary application detectors
6workspace modes: 5 managers + mixed
29commit-pinned external scenarios
106Python + Rust + external checks

Architecture

One static pipeline, two ecosystems.

The scanner walks once, extracts ecosystem-specific facts, then assembles applications by directory.

01 / INPUT Filesystem walk Root-scoped ignore rules, deterministic ordering, bounded reads, no parent-ignore leakage.
02 / PYTHON Manifest + AST PEP 621, requirements, Pipfile, lockfiles, FastAPI entrypoint analysis, Django and Flask identity.
03 / NODE Package signals package.json, configs, scripts, language evidence, Vite qualification, Inertia corroboration.
04 / BOUNDARIES Application assembly Same-root facts merge. Nested packages stay isolated unless they independently qualify.
05 / OUTPUT Schema v1 Applications, technologies, dependency sets, build scripts, workspaces, evidence, diagnostics.

Public contract

A smaller API with richer facts.

Selection, deployability, prompting, and runtime command policy stay with consumers.

Before · schema 0
ScanResult
├─ projects: list[Project]
├─ deploy_targets: list[DeployTarget]
├─ classification: Classification
├─ want_files: list[WantFile]
└─ status / input

scan(root, target_dir=...)

Policy embedded in output
└─ recommended: bool
After · schema 1
ScanResult
├─ workspace: Workspace | None
├─ applications: list[Application]
└─ diagnostics: list[Diagnostic]

scan(root, application_dir=...)

Facts only
├─ Technology
├─ DependencySet
└─ BuildScript

Application

Unique directory, name, technologies, optional entrypoint, ecosystem dependency sets, build facts, Python metadata, evidence, and diagnostics.

Technology

Stable name plus kind, primary/supporting role, confidence, and evidence. Vite remains a build tool even when it identifies a standalone app.

DependencySet

One application can carry both Python and Node manifests, managers, locks, declared dependencies, and resolved Python packages.

Detection coverage

Framework identity without code execution.

FastAPI retains detailed AST resolution. Other frameworks use conservative manifest, config, and script evidence.

Primary frameworks

FastAPIDjangoFlask Next.jsAstroNuxt SvelteKitTanStack Start React RouterSolidStartRemix

Languages

PythonJavaScriptTypeScript

UI + integration

ReactVueSvelte SolidCross Inertia

Workspaces + build

uvnpmpnpm YarnBunmixed Vite
Same root

One FastAPI application

./ ├── pyproject.toml FastAPI + cross-inertia ├── main.py main:app ├── package.json React + Inertia + build └── vite.config.js asset tooling

FastAPI stays primary; Python, TypeScript, React, Vite, and Cross Inertia attach as supporting facts.

Separate roots

Two applications

./ ├── backend/ │ ├── pyproject.toml │ └── main.py └── frontend/ ├── package.json └── app/page.tsx

Recursive discovery emits backend FastAPI and frontend Next.js as independent application choices.

External corpus

Real repositories, immutable expectations.

Twenty clean public repositories live in test-patrick; Cross Inertia is pinned directly to its upstream template.

SourceCategoryExpected resultRevisionStatus
kenbun-fastapi-basicPythonFastAPI · main:apped740d6Pass
kenbun-django-basicPythonDjango identity0f251b7Pass
kenbun-flask-basicPythonFlask identity1d56f35Pass
kenbun-nextjs-basicNodeNext.js + React + TypeScripte8fd986Pass
kenbun-astro-basicNodeAstro + TypeScript6aca222Pass
kenbun-nuxt-basicNodeNuxt + Vue + TypeScriptc2dc8e8Pass
kenbun-sveltekit-basicNodeSvelteKit + Svelte + Vitef3966acPass
kenbun-tanstack-start-basicNodeTanStack Start + React + Vite0539925Pass
kenbun-react-router-basicNodeReact Router Framework Modeeaaa53dPass
kenbun-solidstart-basicNodeSolidStart + Solid2d52a02Pass
kenbun-remix-basicNodeLegacy Remix + Reactacc2752Pass
kenbun-vite-react-basicNodeStandalone Vite + React + JavaScript9698ba1Pass
kenbun-vite-boundariesBoundarySPA included; Vite library excluded2670c8ePass
kenbun-fullstack-directoriesBoundaryFastAPI backend + Next.js frontendab1dae1Pass
kenbun-no-appBoundaryLibraries produce zero applications10f1453Pass
kenbun-workspace-uvWorkspaceFastAPI + Django + libraryb856a62Pass
kenbun-workspace-npmWorkspacenpm · Next.js + librarya404bb6Pass
kenbun-workspace-pnpmWorkspacepnpm · Astro + libraryf239edbPass
kenbun-workspace-yarnWorkspaceYarn · SvelteKit + libraryec2ce61Pass
kenbun-workspace-bunWorkspaceBun · Nuxt + library4d3e1d3Pass
cross-inertia-templates / fastapi-basicIntegrationOne FastAPI app + React, Vite, Inertia28db570Pass

The runner expands these 21 pinned sources into 29 scenarios by scanning workspace roots, member directories, nested member directories, and both full-stack application hints.

Verification

Green locally and against GitHub snapshots.

External fixtures are manual-only; default CI remains deterministic and network-independent.

Python test suiteAPI, scanner, workspaces, runner safety, regressions
66
Rust test suiteNode parsing, command detection, workspace expansion, ignore roots
11
External fixture scenariosFull commit SHAs, cached archive scans, expected projections
29
Static quality gatesRuff, Ruff format, Rustfmt, Clippy with warnings denied, diff check
5/5
106scenarios passed

Zero failing checks in the final consolidated run.

01
Root-scoped ignoresFixture scans no longer inherit Kenbun’s parent .gitignore and hide directories such as packages/lib.
02
Nested workspace discoveryScanning inside an actual package member resolves upward; matching globs without a package manifest do not.
03
Mixed uv + Node rootsBoth declarations contribute members and the workspace is normalized as mixed.
04
Same-root fact preservationA Node-primary app keeps valid Python dependencies and metadata from the same directory.
05
Vite false positivesDirect dependency + explicit vite build + index.html are all required before Vite creates an app.
06
Evidence completenessCross Inertia records both pyproject.toml and package.json corroboration.
07
Hint safetyAbsolute POSIX, Windows, and escaping application_dir values are rejected.
08
No npm guessingConflicting manager evidence yields None plus KB308—even for library-only packages.

Implementation map

Where the change lives.

The working tree remains uncommitted so the complete implementation can be reviewed before publishing.

src/model.rs

Schema v1 public records and canonical JSON surface.

src/node.rs

Node manifests, frameworks, languages, Vite, workspaces, and manager inference.

src/scan.rs

Python/Node candidate assembly, same-root merging, technologies, build scripts.

src/workspace.rs

uv, Node, mixed, member, nested-member, and upward discovery behavior.

src/fileset.rs

Deterministic root-scoped filesystem indexing and exclusions.

src/kenbun/

Python exports and exact typed stubs for the new public surface.

tests/test_node_scan.py

Framework, Vite, Inertia, workspace, boundary, and manager regressions.

tests/external_fixtures.json

Commit-pinned sources, scan variants, and normalized expectations.

scripts/check_external_fixtures.py

Safe archive download, cache, extraction, scan, and focused diff runner.

docs/spec.md

Normative schema-v1 contract, behavior, and deferred capabilities.

README.md

Updated multi-ecosystem usage and supported detection overview.

CHANGELOG.md

Unreleased breaking API and detector additions.

Reproduce the final verification

uv run maturin develop --uv PASS
uv run pytest -q 66 PASS
cargo test 11 PASS
cargo clippy --all-targets --all-features -- -D warnings PASS
uv run python scripts/check_external_fixtures.py --offline 29 PASS