Skip to content

Prompt Token-Cost Baseline

Every prompt surface in the monorepo that reaches an LLM, with the token cost of the fixed text it always emits. This file is re-recorded as the Agent Prompt & Workflow Efficiency epic proceeds, so the figures below are current rather than original. The epic started from 22,670 per-call / 13,630 unique at 2a64b185 — the last recording before any prompt was rewritten, and the number the epic's overall reduction should be measured against. Use --compare for the delta since whatever is recorded here now.

  • Recorded at — 2026-09-11T12:15:04.131Z
  • Commit1ce09a26728b
  • Content hashe10365e5d95f379b (identifies the measurement itself; tests/e2e/prompt-census.test.js fails when the repo no longer matches it)
  • Model for cost/context figuresclaude-sonnet-5
  • Surfaces — 36
  • Per-call total — 21,688 tokens (what every surface costs, summed)
  • Unique fixed text — 13,201 tokens (distinct text a rewrite has to edit)

How to reproduce

sh
pnpm build                                    # the census imports built builders
node scripts/prompt-census.mjs                # measure HEAD
node scripts/prompt-census.mjs --compare      # before/after vs this file
node scripts/prompt-census.mjs --dump hench   # print one assembled prompt
node scripts/prompt-census.mjs --write        # re-record the baseline

What the two numbers mean

Fixed is the prompt text a builder always emits, extracted from the string literals in its body. It is what a rewrite reduces. Context is what the run supplies — file lists, PRD items, analysis output — and it does not shrink because someone tightened a sentence. Keeping them apart is what stops a reduction being credited to the wrong surface.

Counting literals rather than output is also what makes the three construction styles comparable. core writes a few large template literals per prompt; hench pushes dozens of short fragments onto an array; rex and sourcevision declare a list of named sections. A literal-per-file scan undercounts the last two badly; counting literals per builder does not.

Token counts come from budgetPreflight() in @n-dx/llm-client — the same estimator the runtime uses for context-window preflight, so a number here is the number the runtime would produce for the same text.

Per-call vs unique

Own is the text written inside a builder. Shared is the prompt constants it interpolates — PRD_SCHEMA, FEW_SHOT_EXAMPLE and friends, which rex reuses across many builders. Per-call is their sum: what one invocation actually sends.

The two totals answer different questions. Per-call is the bill. Unique is the edit surface — a constant used by ten builders is written once, so shortening it is worth ten times its own size. Reporting only the per-call sum would point a rewrite at the largest builders rather than at the most-reused text.

Measurement revisions

A total in this file can move because prompts changed or because the measurement changed. Only the first is a result. Revisions of the second kind are recorded here so a jump is never mistaken for a regression or a win.

  • Envelope migration — rex's and sourcevision's prompts moved onto PromptEnvelope, and every builder was renamed *Prompt*Envelope, so a --compare across that change shows the whole registry as NEW/REMOVED. The assembled text is byte-identical apart from removed doubled blank lines, proved by the prompt-text-identity snapshot suites in both packages. In the same change the extractor learned to follow module-local helper calls: factoring duplicated prompt text into a helper had been dropping it from the count entirely. That correction raised the recorded totals by ~5% with no prompt growing — the earlier figures were an undercount.
  • rex redundancy pass — the first entry here that is a real reduction rather than a measurement change: -904 per-call / -278 unique, by deleting instructions that the same prompt already gave elsewhere and resolving a task-size contradiction (hours vs engineer-weeks). No instruction was removed from a prompt that did not still state it.

rex — 15,217 per-call / 7,195 unique, 19 surfaces

BuilderFilePurposeLiteralsOwnSharedPer-call
buildFileImportEnvelopepackages/rex/src/analyze/reason.tsPropose PRD items from a single source document.181231,0421,165
buildScanImportEnvelopepackages/rex/src/analyze/reason.tsPropose PRD items from a batch of scanner findings.404001,2571,657
buildAddEnvelopepackages/rex/src/analyze/reason.tsPropose new PRD items from a natural-language description.252101,4301,640
buildMultiAddEnvelopepackages/rex/src/analyze/reason.tsPropose items for several scan targets in one call.271951,4301,625
buildBreakdownEnvelopepackages/rex/src/analyze/reason.tsSplit proposals judged too large into child tasks.17200483683
buildConsolidateEnvelopepackages/rex/src/analyze/reason.tsMerge overlapping proposals before they enter the PRD.19234484718
buildAssessmentEnvelopepackages/rex/src/analyze/reason.tsAssess whether proposal tasks are at the right granularity.40497497
buildIdeasEnvelopepackages/rex/src/analyze/reason.tsExtract proposals from free-form notes that local parsing missed.283581,4301,788
buildConsolidationGuardEnvelopepackages/rex/src/analyze/consolidation-guard.tsSecond-opinion check before a consolidation is applied.21273432705
buildDecompositionEnvelopepackages/rex/src/analyze/decompose.tsDecompose a task whose level-of-effort exceeds the threshold.23270270
buildDisambiguationEnvelopepackages/rex/src/analyze/extract.tsResolve an ambiguous extraction against existing PRD items.21186541727
buildClarifyEnvelopepackages/rex/src/analyze/guided.tsAsk clarifying questions during guided PRD authoring.33309309
buildSpecEnvelopepackages/rex/src/analyze/guided.tsTurn guided answers into a structured spec.22150432582
buildModifyEnvelopepackages/rex/src/analyze/modify-reason.tsApply a natural-language edit to an existing PRD item.29295492787
buildGroupRenameEnvelopepackages/rex/src/analyze/propose-group-renames.tsRename a group of sibling items to a consistent scheme.2721429243
buildRenameEnvelopepackages/rex/src/analyze/rename-resolve.tsPick the better of two colliding item titles.2320429233
buildReshapeEnvelopepackages/rex/src/analyze/reshape-reason.tsPropose a restructure of the PRD hierarchy.7181,4021,420
buildBodyMergeEnvelopepackages/rex/src/analyze/reshape-reason.tsMerge two item descriptions into one during a reshape.12106106
buildValidationFeedbackEnvelopepackages/rex/src/analyze/escalate.tsRetry feedback appended to a prompt whose response failed validation.126262

sourcevision — 2,659 per-call / 2,194 unique, 7 surfaces

BuilderFilePurposeLiteralsOwnSharedPer-call
buildFirstPassEnvelopepackages/sourcevision/src/analyzers/enrich-batch.tsFirst-pass zone enrichment for a batch of zones.57317463780
buildLaterPassEnvelopepackages/sourcevision/src/analyzers/enrich-batch.tsLater-pass zone enrichment, given the previous pass's output.50265434699
buildMetaEnvelopepackages/sourcevision/src/analyzers/enrich-config.tsMeta-evaluation choosing the enrichment strategy for a repo.2353114545
buildSingleZoneFirstPassEnvelopepackages/sourcevision/src/analyzers/enrich-per-zone.tsPer-zone enrichment, first pass — names and describes one zone.2513816154
buildSingleZoneLaterPassEnvelopepackages/sourcevision/src/analyzers/enrich-per-zone.tsPer-zone enrichment, later pass — adds only what pass 1 missed.2712041161
buildLLMClassifyEnvelopepackages/sourcevision/src/analyzers/classify.tsClassify file archetypes the heuristic classifier could not.199191
buildPrimerEnvelopepackages/sourcevision/src/analyzers/primer.tsDistil CONTEXT.md into the startup primer every agent run inherits.21229229

hench — 3,531 per-call / 3,531 unique, 9 surfaces

BuilderFilePurposeLiteralsOwnSharedPer-call
buildSystemPromptpackages/hench/src/agent/planning/prompt.tsThe agent's system prompt — role, rules, workflow, error handling.62768768
buildGoLanguageContextpackages/hench/src/agent/planning/prompt.tsGo toolchain and convention context, added when the project is Go.26278278
formatTaskBriefpackages/hench/src/agent/planning/brief.tsRender the task brief section — task, parent chain, requirements.42214214
buildReviewSystemPromptpackages/hench/src/agent/analysis/adversarial-review.tsSystem prompt for the adversarial review pass.27331331
buildReviewBriefpackages/hench/src/agent/analysis/adversarial-review.tsBrief handed to the reviewer — what to attack and where to report.1291,4601,460
buildOrientationSystemPromptpackages/hench/src/agent/lifecycle/orientation.tsSystem prompt for the one-off repository orientation pass.9114114
buildOrientationPromptpackages/hench/src/agent/lifecycle/orientation.tsOrientation task prompt — what to establish about the repo.15191191
buildRetryNoticepackages/hench/src/agent/lifecycle/cli-loop.tsNotice appended on retry telling a fresh session what is on disk.45555
formatPlanModeAppendixpackages/hench/src/agent/lifecycle/plan-mode-prompt.tsAppendix re-spawning a session that stalled in plan mode.12120120

core — 281 per-call / 281 unique, 1 surfaces

BuilderFilePurposeLiteralsOwnSharedPer-call
buildReviewerPromptpackages/core/pair-programming.jsQA reviewer prompt for the pair-programming second opinion.6281281

Shared prompt constants

Ranked by total per-call cost — size times the number of builders that interpolate it. This is the leverage ordering for a rewrite.

ConstantPackageTokensUsed byPer-call total
FEW_SHOT_EXAMPLErex432104,320
PRD_SCHEMArex33361,998
reshapeRoleContentrex1,05411,054
TASK_QUALITY_RULESrex1566936
CONSOLIDATION_INSTRUCTIONrex2234892
formatProjectShapesourcevision3932786
placementContentrex1553465
OUTPUT_INSTRUCTIONrex528416
ANTI_PATTERNSrex616366
RESHAPE_FEW_SHOTrex3261326
JSON_OBJECT_ONLYsourcevision16464
formatFileHeaderssourcevision54154
ONLY_NEW_INSIGHTSsourcevision25250
summarizeExistingrex9436
projectContextContentrex10330
formatMemberSectionrex29129
formatItemSectionrex29129
summarizePRDrex22122
formatAnnotatedFindingsourcevision15115

Assembled prompts (fixed representative input)

One entry point per package, invoked with a checked-in fixture so the number is reproducible without a model call. Dump any of them with --dump <package>.

PackageEntry pointInputFixedContextAssembled
rexbuildAssessmentEnvelopeGranularity assessment over one two-task proposal.497245742
sourcevisionbuildPrimerEnvelopePrimer distillation over a fixed 3-zone CONTEXT.md excerpt.229137366
henchbuildPromptEnvelopeFull agent envelope (system + brief) for a CLI-provider run.982n/a — 398 of the fixed text is on another branch584
corebuildReviewerPromptPair-programming reviewer prompt over three changed files.28116297

A fixed figure above the assembled length is not an error: the fixed column counts every branch in the builder, and one run takes one path. buildSystemPrompt alone carries separate CLI/API, auto-commit, and self-heal branches. The unreached text is still worth shortening — it just is not billed on this particular path.

rex envelope sections

buildAssessmentEnvelope assembles its prompt from named sections, so its cost is reported per section rather than as one literal. These are the same sections extractPromptSectionDiagnostics() reports at runtime, over the fixture in Granularity assessment over one two-task proposal.

SectionCharsTokensShare
input1,05526435.6%
output63415921.4%
anti-patterns49812516.8%
structure40610213.7%
quality229587.8%
role134344.6%

sourcevision envelope sections

buildPrimerEnvelope assembles its prompt from named sections, so its cost is reported per section rather than as one literal. These are the same sections extractPromptSectionDiagnostics() reports at runtime, over the fixture in Primer distillation over a fixed 3-zone CONTEXT.md excerpt.

SectionCharsTokensShare
input58514740.3%
rules40210127.7%
output3127821.4%
role1563910.7%

hench envelope sections

buildPromptEnvelope assembles its prompt from named sections, so its cost is reported per section rather than as one literal. These are the same sections extractPromptSectionDiagnostics() reports at runtime, over the fixture in Full agent envelope (system + brief) for a CLI-provider run.

SectionCharsTokensShare
system1,66341671.4%
brief66816728.6%

Workflow skills — 17,217 tokens, 13 skills

A skill body enters the agent's context whole the moment the skill is invoked, so its size is a per-invocation bill in the same way a builder's fixed text is a per-call one. The two totals are NOT added together: a skill run and an analyze call are different events.

shipped marks the skills ndx init installs into other repositories. The rest exist only here, which makes them easy to forget — they were exempt from the portability guards until this table gave them a number.

SkillShippedCharsTokens
ndx-adversarial-reviewyes20,5125,128
iso-map8,2852,072
triage7,4211,856
ndx-reshapeyes5,8161,454
dev-link5,0541,264
ndx-planyes4,4371,110
ndx-captureyes4,4071,102
ndx-configyes3,322831
ndx-workyes2,954739
ndx-feedbackyes2,565642
no-plan-modeyes2,476619
ndx-zoneyes817205
ndx-statusyes780195

Packages with no LLM prompt surfaces

Recorded so the absence is a finding rather than an oversight — these were checked.

PackageWhy
webServes the dashboard and proxies MCP. Every LLM call it surfaces is made by rex, sourcevision, or hench behind a gateway; web composes no prompt text of its own.
llm-clientFoundation tier. Carries the prompt envelope and token types that the other packages fill in, but composes no prompt text itself.

Out of scope: interactive readline prompts

These are questions to a human, not to a model. They are listed by name pattern so a later audit does not mistake one for an LLM prompt surface.

Name patterns:

  • /^prompt[A-Z]/
  • /^confirmPrompt$/
  • /^defaultPrompt$/
  • /Prompt(Input|Choice|Confirm)$/

Specific builders whose names match a prompt pattern but which are not LLM prompts:

BuilderFileWhy it is out of scope
buildPromptpackages/rex/src/cli/commands/chunked-review-state.tsReadline prompt string ((3/8 accepted) > ) passed to promptLine. Named buildPrompt but never reaches a model.
parseDuplicatePromptInputpackages/rex/src/cli/commands/smart-add.tsParses a human's answer to a readline prompt.
promptReviewpackages/hench/src/agent/analysis/review.tsInteractive review gate — asks the operator, not a model.
extractPromptSectionDiagnosticspackages/hench/src/agent/lifecycle/prompt-diagnostics.tsMeasures a prompt envelope; emits no prompt text.
logPromptSectionspackages/hench/src/agent/lifecycle/prompt-diagnostics.tsLogs envelope section sizes to the CLI.
promptForTestCommandpackages/hench/src/tools/test-command-resolver.tsAsks the operator for a test command.

Released under the Elastic License 2.0.