유대선
프로젝트로
·기술 회고·4

An architecture map that sets itself up — without the tool ever calling an LLM

DalkkakAI's in-app architecture surface now bootstraps itself on any project: the engine scans the code deterministically, generates a setup prompt, hands it to the user's own BYO agent (Claude Code/Codex) to author the manifest, then consumes the result. No LLM call from the product. Proven live in-app on a fresh Go project: 0→100% coverage, 18 named components, a 10-flow system diagram — all from the app's own agent. Plus the bug that made it look broken: a 12KB prompt that pasted but never submitted.

The problem with "AI understands your codebase"

Every "AI maps your architecture" tool eventually hits the same wall: the meaning — what a module is called, what it does, how a request actually flows at runtime — can't be derived from the syntax tree alone. You need a model that reads the code and reasons about it. So the tool calls an LLM.

DalkkakAI can't do that. Our whole premise is BYO: the user brings their own Claude Code or Codex; the product never calls an LLM itself. So how does the architecture map get the meaning?

By not calling the LLM — and letting the user's agent do it, on a task the product hands it.

The loop

engine (deterministic, no AI)          → scans the repo, emits the skeleton
archsetup.py (deterministic, no AI)    → writes .dalkkak/_setup.md:
                                          the scanned inventory + the exact
                                          arch.json / flow.json schemas
[user's BYO agent runs the prompt]     → reads the code, authors
                                          .dalkkak/{arch,flow}.json
engine consumes the manifest           → the panel fills with real names,
                                          summaries, and a runtime flow

The split is the whole idea. Everything the machine can know for certain — the file list, the import graph, git churn, co-change coupling — is computed deterministically and marked as fact. Everything that requires judgment — "this cluster is the Auth subsystem," "the login flow goes router → handler → Postgres" — is produced by the user's agent and marked as inference (✦ AI 합성 · 검증 대상). Staleness is tracked by content-hash, so when the code drifts past the summary, the panel can say so instead of lying.

The product's contribution is the prompt, not the answer. And the prompt is generated from the real scan, so it's never hardcoded to one stack.

Proving it on a project it had never seen

The honest test isn't "does it work on our repo" — we'd tuned it there. It's a cold project. I pointed it at a fresh Go app (a file-vault service: encrypted storage, 2FA auth, audit log, endpoint agents) the engine had never touched. One click of 🤖 에이전트로 셋업:

That last part is the thing static analysis structurally cannot give you — a runtime flow is not in the AST. The agent read it out of the code, and the product rendered it as a clean layered stack instead of a tangled graph.

The key point: this time it wasn't a stand-in. The app's own dedicated agent did it, end to end, in-app.

The bug that made it look dead

It didn't work the first time, and the failure was invisible in the worst way. The panel said ✓ 에이전트가 작성 중… ("agent is writing"), but nothing ever appeared. No error. Just waiting.

tmux capture-pane on the dedicated setup agent told the truth: the ~12KB prompt was sitting in Claude Code's input as a collapsed [Pasted text +119 lines]pasted but never submitted. The dispatcher writes the text and sends one newline 250ms later; for a paste that large, Claude Code stages it in bracketed-paste mode and waits for a separate Enter, and the single newline raced the paste's own buffering. Sending one Enter by hand started it instantly.

The fix is one line of intent — nudge a submit Enter a beat after delivery — but the lesson is the cheaper one: pasting a big multi-line blob into a TUI is not the same as submitting it, and a "still working?" timeout must never be shorter than the real task. Reading and summarizing a whole repo is minutes, not seconds; my first auto-poll gave up at 3 minutes, right before the agent finished at ~4.

What's real, and what isn't yet

Calibrated confidence applies to my own claims too. What's verified: the loop runs in-app on a cold project, the manifest is valid, the engine consumes it, the flow tab renders. What's not done: the map doesn't yet refresh itself as you keep coding — the live-change feed tab is still a placeholder, and the AI summaries go stale (they're marked stale, but not auto-regenerated). The deterministic half updates on demand; the "always current, show me what changed and where" half is the next build.

But the hard part — an architecture map that bootstraps its own meaning on any project, without the tool ever touching an LLM — is working.