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-10-28T01:09:48.358Z
  • Commit — 3205a763fbe2
  • Content hash — ba595d4edf6728b4 (identifies the measurement itself; tests/e2e/prompt-census.test.js fails when the repo no longer matches it)
  • Model for cost/context figures — claude-sonnet-5
  • Surfaces — 38
  • Per-call total — 23,515 tokens (what every surface costs, summed)
  • Unique fixed text — 15,010 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,804 per-call / 7,782 unique, 21 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.40497—497
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.23270—270
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.33309—309
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
buildPlacementEnvelopepackages/rex/src/analyze/place-reason.tsPlace a change on a shortlisted capability or constraint, or propose a new node.16233—233
buildSpecDraftEnvelopepackages/rex/src/analyze/spec-draft-reason.tsRedraft a capability spec in present tense, citing the source item of every criterion.22354—354
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.12106—106
buildValidationFeedbackEnvelopepackages/rex/src/analyze/escalate.tsRetry feedback appended to a prompt whose response failed validation.1262—62

sourcevision — 2,722 per-call / 2,241 unique, 7 surfaces ​

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

hench — 4,708 per-call / 4,706 unique, 9 surfaces ​

BuilderFilePurposeLiteralsOwnSharedPer-call
buildSystemPromptpackages/hench/src/agent/planning/prompt.tsThe agent's system prompt — role, rules, workflow, error handling.771,186—1,186
buildGoLanguageContextpackages/hench/src/agent/planning/prompt.tsGo toolchain and convention context, added when the project is Go.26278—278
formatTaskBriefpackages/hench/src/agent/planning/brief.tsRender the task brief section — task, parent chain, requirements.40184115299
buildReviewSystemPromptpackages/hench/src/agent/analysis/adversarial-review.tsSystem prompt for the adversarial review pass.27331—331
buildReviewBriefpackages/hench/src/agent/analysis/adversarial-review.tsBrief handed to the reviewer — what to attack and where to report.1141,5363651,901
buildOrientationSystemPromptpackages/hench/src/agent/lifecycle/orientation.tsSystem prompt for the one-off repository orientation pass.10147—147
buildOrientationPromptpackages/hench/src/agent/lifecycle/orientation.tsOrientation task prompt — what to establish about the repo.36391—391
buildRetryNoticepackages/hench/src/agent/lifecycle/cli-loop.tsNotice appended on retry telling a fresh session what is on disk.455—55
formatPlanModeAppendixpackages/hench/src/agent/lifecycle/plan-mode-prompt.tsAppendix re-spawning a session that stalled in plan mode.12120—120

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

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

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
reportOutputLineshench3531353
RESHAPE_FEW_SHOTrex3261326
JSON_OBJECT_ONLYsourcevision16580
commitTrailersBlockhench55155
formatFileHeaderssourcevision54154
ONLY_NEW_INSIGHTSsourcevision25250
sessionFiltersBlockhench48148
summarizeExistingrex9436
projectContextContentrex10330
formatMemberSectionrex29129
formatItemSectionrex29129
summarizePRDrex22122
formatAnnotatedFindingsourcevision15115
inboxClausehench11111
workflowBlockhench616
formatChangeBriefhench515

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.1,485n/a — 527 of the fixed text is on another branch958
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
system3,16279182.6%
brief66816717.4%

Workflow skills — 22,952 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-reviewyes24,1176,030
ndx-reshapeyes10,2502,563
ndx-captureyes9,0232,256
iso-map—8,2852,072
ndx-planyes8,0272,007
ndx-workyes7,9841,996
triage—7,4211,856
dev-link—5,0541,264
ndx-configyes4,9851,247
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.