callidescope-configure
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTelling callidescope what to do
告诉 callidescope 该做什么
Two surfaces, read together on every run: the flags on the command line, and
the they layer over. Neither is complete on its own:
names a limit the configuration has to have set, and a file
destination is only written when a flag asks for it.
callidescope.config.ts--check每次运行都要同时读取两个层面:命令行上的 flags,以及它们所叠加的 。二者单独看都不完整: 指定一个配置必须已经设置的限制,而只有 flag 提出要求时才会写入文件目标。
callidescope.config.ts--checkThe two decisions a run makes
一次运行所做的两个决定
Every invocation answers two independent questions, neither implying the other:
| Question | Answered by |
|---|---|
| What does this run fail on? | |
| What does this run rewrite? | |
A run given neither nor reads no destination and
rewrites none: it traces, prints, and exits. That is what makes a bare run
safe to type inside somebody's checkout, and why a gate on a pull request
leaves every committed report exactly as it found it.
--write--check reports每次调用都会回答两个彼此独立的问题,二者互不蕴含:
| 问题 | 由什么回答 |
|---|---|
| 本次运行会在什么情况下失败? | |
| 本次运行会重写什么? | |
如果既未传入 ,也未传入 ,本次运行就不会读取任何目标,也不会重写任何目标:它只会进行 trace、打印结果并退出。正因如此,在某个 checkout 中直接输入裸命令是安全的;而 PR 上的门禁也会让所有已提交的报告保持原样。
--write--check reportsThe flags
Flags
| Flag | Meaning |
|---|---|
| Comma-separated callable addresses, each |
| Path to a |
| Comma-separated project directories to trace, each holding its own |
| Override the matching |
| Comma-separated globs and callee patterns, overriding the authored field. The tool's own default exclusions are folded back in, exactly as they are under a configured |
| |
| Where each report goes. Overrides the path of that declared |
| A number, overriding that limit wherever a project declared it. |
| The two decisions above: fail on a comma-separated set drawn from |
Every configured field has an overriding flag, save one.
names the ignore files a run reads — no flag corresponds to it. An override
may change a declared value and may not supply one, so no flag makes an
under-configured run legal, and a list written empty reads as absent.
and take every override above but the destinations and the limits,
plus and ; is theirs alone.
excludeFromdepthbreadth--config--format--addresses| Flag | 含义 |
|---|---|
| 逗号分隔的可调用项地址,每个地址的格式为 |
| |
| 要 trace 的项目目录,多个目录以逗号分隔;每个目录都必须包含自己的 |
| 覆盖对应的 |
| 逗号分隔的 glob 和被调用项模式,覆盖显式编写的对应字段。工具自身的默认排除项会重新合并进来,其行为与配置中的 |
| 指定打印内容使用 |
| 指定各类报告的写入位置。仅覆盖已声明的相应 |
| 指定数值,覆盖项目声明的相应限制。如果配置未声明 |
| 决定前述两个问题:在一组逗号分隔的值(取自 |
每个已配置字段都有一个对应的覆盖 flag,只有一个例外。 指定一次运行会读取哪些 ignore 文件,因此没有对应的 flag。覆盖项可以改变已声明的值,却不能提供配置中未声明的值;所以没有任何 flag 能让配置不完整的运行变得合法,而显式写出的空列表会被视为未声明。用于 和 的检查可以采用除目标位置和限制覆盖项之外的所有上述覆盖 flag,另加 和 ; 则仅供它们使用。
excludeFromdepthbreadth--config--format--addressesOne precedence rule governs every override
所有覆盖项都遵循同一条优先级规则
Every combination of a command-line value with a configured one is resolved in
one place, , under one rule:
FlagResolutionServiceA flag that changes what a run judges or writes may only override a value the configuration already declares. A flag that selects mode or presentation is command-line only, because neither can make an under-configured run legal.
--check--write--format--configpath--maximum-breadth--jsonwrite.jsonEvery complaint from resolution is collected rather than thrown at the first
one, so a command line with two mistakes is two mistakes to fix, not two runs.
命令行值与配置值之间的每一种组合,都会在同一个位置 中按照同一条规则解析:
FlagResolutionService改变一次运行评判什么或写入什么的 flag,只能覆盖配置已经声明的值。选择模式或展示形式的 flag 仅限命令行使用,因为二者都不能让配置不完整的运行变得合法。
--check--write--format--configpath--maximum-breadth--jsonwrite.json解析过程中的所有问题都会被一并收集,而不是遇到第一个就立即抛出;因此,包含两处错误的命令行需要修复两处问题,而不需要运行两次。
--check
takes a set, and the set matters
--check--check
接收一组值,而这组值很重要
--check| Value | What fails the run |
|---|---|
| A call stack deeper than |
| A callable calling more callables directly than |
| A configured destination no longer holding what a fresh run would write |
Two refusals to expect, both deliberate:
- with no value is refused. A set with nothing in it is indistinguishable from the flag left off, so
--checkwith the variable unset would pass forever over a stack twice as deep as anything allowed — worse than no gate, because it looks like protection.--check "$GATES" - An unrecognized value is refused, and the message lists what is accepted.
| 值 | 导致运行失败的情况 |
|---|---|
| 调用栈深度超过 |
| 一个可调用项直接调用的可调用项数量超过 |
| 已配置的目标位置不再包含新一次运行将会写入的内容 |
需要预期两种拒绝情况,二者都是有意设计的:
- 不带值的 会被拒绝。 没有任何值的集合与完全省略该 flag 无法区分,因此当变量未设置时,
--check会对一个深度达到允许值两倍的调用栈永远通过;这比没有门禁更糟,因为它看起来像是存在保护。--check "$GATES" - 无法识别的值会被拒绝,错误消息会列出所有可接受的值。
Why depth
and reports
belong on opposite sides of a pull request
depthreports为什么 depth
和 reports
应位于 PR 流程的两侧
depthreportsDepth is the gate. A stack got longer in this change, and this change is
what fixes it. Run it on every pull request, and on every commit if you like —
depth reads source and needs no build, which is what keeps it cheap enough for
a commit hook.
bash
npx callidescope --check depthIn an Nx workspace, prefer the per-project target to this flag. A
whole-workspace reaches the right verdict the expensive way:
one uncacheable run over the repository on every commit.
infers a onto each project instead, tracing it with its Nx dependencies
and failing only on the findings that project owns, so judges what a change touched and nothing else. Depth is gated
on every project, since it has a default; breadth is gated only on a project
whose own declares . The flag
remains the answer without Nx.
gate--check depth@callidescope/nxgatenx affected --target=gatecallidescope.config.tslimits.maximumBreadthStaleness is not a gate. A report goes stale whenever the call graph moves
anywhere, which is nearly every change, so gating on it fails pull requests for
drift they did not cause. Publish on the default branch instead, where nothing
else competes to rewrite the same block:
bash
npx callidescope --write--write --check reports--configuration=writedepthdepthbash
npx callidescope --check depth在 Nx workspace 中,应优先使用每个项目自己的 target,而不是这个 flag。 对整个 workspace 执行 也能得出正确结论,但采用的是代价高昂的方式:每次 commit 都要对整个 repository 进行一次无法缓存的运行。 则会为每个项目自动推导 ,结合其 Nx dependencies 进行 trace,并且只在失败项确实属于该项目本身时判定失败;因此, 只评判变更触及的项目,不会评判其他项目。每个项目都会受到 门禁,因为它具有默认值;只有项目自己的 声明了 时,才会受到 门禁。如果没有 Nx,该 flag 仍然是适用的解决方案。
gate--check depth@callidescope/nxgatenx affected --target=gatedepthcallidescope.config.tslimits.maximumBreadthbreadth报告过期不是门禁。 只要调用图中的任何位置发生变化,报告就可能过期,而这几乎发生在每次变更中;因此,对报告过期设置门禁,会因为并非本次变更造成的漂移而使 PR 失败。应在默认分支上发布报告;在那里,没有其他流程会竞争重写同一区块:
bash
npx callidescope --write--write --check reports--configuration=write--directories
, and why a run is slow without it
--directories--directories
,以及不指定它时运行缓慢的原因
--directoriesThe difference between a whole-workspace analysis and a check that finishes in
seconds. Each directory named needs its own , and the programs
built are those plus every project they transitively import, so a call into a
dependency still resolves to a real frame:
tsconfig.jsonbash
npx callidescope -d packages/foo,packages/bar --check depthOmit it and callidescope walks the working directory for every
it finds — the workspace-wide picture, not an answer about one package.
tsconfig.jsonIt takes paths, not project names: callidescope knows nothing of workspace
tooling, and a directory holding a is the whole contract. The
same list can be set once as in the workspace configuration file.
tsconfig.jsondirectoriesThere is a real trade-off when narrowing a lookup: callers outside
the named directories and the closure below them do not exist to the run,
since the closure runs downward and a dependent that calls in is never built.
For a rename whose blast radius is the point, trace wide enough to contain
every consumer.
breadthAn Nx workspace can hand the selecting to Nx instead, through the separate
plugin, which infers , , , and
targets onto every project and traces each one with its Nx dependencies, so
those are projects the run is scoped to rather than ones it merely reached
through a closure. The first three only print; decides an exit code and
is what a branch runs. An excluded project keeps the three that print and is
denied the gate, since its own code is never traced. It is a separate package
on purpose: this CLI depends on nothing Nx-shaped.
@callidescope/nxtracedepthbreadthgategate它决定了整个工作区分析与几秒内完成的检查之间的差异。每个指定目录都需要自己的 ,而构建出的 programs 包括这些目录及其传递导入的所有项目;因此,对依赖项的调用仍会解析为真实的栈帧:
tsconfig.jsonbash
npx callidescope -d packages/foo,packages/bar --check depth省略它时,callidescope 会遍历工作目录,查找它能找到的每一个 ;这样得到的是整个 workspace 的视图,而不是针对某一个 package 的答案。
tsconfig.json它接收的是路径,而不是项目名称:callidescope 不了解任何 workspace 工具,拥有 的目录就是完整约定。同一个列表也可以在工作区配置文件中通过 一次性设置。
tsconfig.jsondirectories缩小 查询范围时确实存在取舍:指定目录及其下方闭包之外的调用方对本次运行而言并不存在,因为闭包只向下延伸,而调用进入该目录的上游 dependent 不会被构建。对于重命名任务,如果其影响范围正是关注重点,就应 trace 到足以包含所有使用方的范围。
breadthNx workspace 还可以通过独立的 插件,把选择过程交给 Nx。该插件会为每个项目推导 、、 和 target,并结合各项目的 Nx dependencies 进行 trace;因此,这些项目属于运行明确限定的范围,而不是仅仅通过依赖闭包触及到的项目。前三个 target 只负责打印; 决定退出码,也是分支实际运行的 target。被排除的项目仍保留前三个打印 target,但不会被允许运行 ,因为它自身的代码从未被 trace。之所以将它设计为独立 package,是因为这个 CLI 不依赖任何 Nx 形态的组件。
@callidescope/nxtracedepthbreadthgategategate--format
decides what prints, not what is written
--format--format
决定打印什么,而不决定写入什么
--formatPrinting and writing are independent, and both can be on at once.
names one of (the default), , or for standard
output; the destinations declared under a project's or the workspace's own
decide what reaches a file. leads because it is the one
rendering that reads in a terminal, pastes into an issue, and is already what
the files hold. There is no field — the console rendering is a
command-line concern only.
--formatmarkdownmermaidjsonwritemarkdownwrite.format打印与写入彼此独立,而且可以同时启用。 为标准输出指定 (默认)、 或 ;项目自身配置或工作区自身配置中 下声明的目标位置,则决定哪些内容会写入文件。以 Markdown 为主,是因为它是唯一既能直接在终端中阅读、又能粘贴到 issue 中,而且已经用于现有文件内容的渲染形式。不存在 字段;控制台渲染方式只属于命令行关注点。
--formatmarkdownmermaidjsonwritewrite.formatPrompting, and why it will not hang a script
提示输入,以及为什么它不会使脚本挂起
callidescopedepthbreadthdepthbreadth--addresses--format--addresses--formatmarkdownThe refusal is the load-bearing half. does not fail on a non-terminal
stdin — it draws its menu, never resolves, and lets the process exit 0 having
done nothing — so a required value asserts a terminal before prompting at all
and reports a rejected command line instead. Without it, a CI run that forgot
an argument would read as a green one.
prompts对于命令行中遗漏的值,、 和 都会提示输入: 和 会在缺少 时提示,三者都会在缺少 时提示。没有任何 flag 可以关闭提示,因为附加了终端这一条件本身就是全部依据:脚本、hook 或 CI job 不会有终端,因此永远不会被提示。在非交互环境中,缺失的 会被拒绝并以非零状态退出,因为没有其他方式可以提供它;缺失的 则会回退到默认值 ,并继续运行。
callidescopedepthbreadthdepthbreadth--addresses--format--addresses--formatmarkdown拒绝行为才是其中真正承担关键作用的部分。 在 stdin 不是终端时不会失败:它会绘制菜单,却永远无法解析出结果,并让进程在什么都没做的情况下以 0 退出。因此,所需值会先确认存在终端,然后才尝试提示;一旦不满足条件,就直接报告命令行已被拒绝。否则,一个忘记传参的 CI 运行会显示为绿色。
promptsThe workspace configuration file
工作区配置文件
Any of , searched for
upward from the working directory, TypeScript first because that is the form
that gets type checking. This is the workspace configuration — the file a
run is pointed at. A repository with none is traced with defaults rather than
told to write one.
callidescope.config.{ts,mts,cts,js,mjs,cjs,json,jsonc}ts
import { type CallidescopeConfiguration } from "@callidescope/configuration";
const callidescopeConfiguration: CallidescopeConfiguration = {
excludeFrom: ["configuration/.callidescopeignore"],
limits: { maximumDepth: 6 },
};
export default callidescopeConfiguration;The whole surface is seven top-level keys: , ,
, , , , and . The
workspace file also exports alongside its default export —
a separate binding, not a member of this type — for a project's own
to spread.
directoriesentryPointsexcludeexcludeCalleesexcludeFromlimitswriteprojectDefaultscallidescope.config.ts可以使用 中的任意一种格式。工具会从工作目录向上查找,并优先使用 TypeScript,因为这种形式可以获得类型检查。这是工作区配置,也就是一次运行所指向的文件。没有任何配置的 repository 仍会使用默认设置进行 trace,而不会被要求先编写一个配置文件。
callidescope.config.{ts,mts,cts,js,mjs,cjs,json,jsonc}ts
import { type CallidescopeConfiguration } from "@callidescope/configuration";
const callidescopeConfiguration: CallidescopeConfiguration = {
excludeFrom: ["configuration/.callidescopeignore"],
limits: { maximumDepth: 6 },
};
export default callidescopeConfiguration;整个配置界面包含七个顶层键:、、、、、 和 。工作区文件还会在默认导出之外导出 ,供项目自己的 展开使用;它是独立的绑定,并不是该类型的一个成员。
directoriesentryPointsexcludeexcludeCalleesexcludeFromlimitswriteprojectDefaultscallidescope.config.tslimits
limitslimits
limitsThere are two, both per project, both gated.
| Limit | Default | Meaning |
|---|---|---|
| | Frames a call stack may hold, entry point inclusive |
| none | Callables one callable may call directly |
maximumBreadth--check breadthPicking a first : run once with no gate, read the deepest stacks,
and set the limit at the shape you want rather than at whatever the code
currently is — a limit set to today's worst number gates nothing.
maximumDepthPer project, pick each one by boundary-testing rather than by reading a
number off a run. Write a candidate, run that project's gate, then run it one
lower: a limit worth having passes at the number written and fails at one
below. A scoped run's printed summary covers the whole trace, dependency
closure included, so the depth it reports is routinely deeper than anything
the judged project owns — only a gate's verdict knows which findings belong to
the project.
A limit is a schema field and nothing else now. The schema is strict, and
accepts only and . A retired field —
, , ,
— is refused rather than silently stripped. Those four
limits, the two findings they tuned, and the module-identity concept behind
them are gone from the tool entirely — see the repository's ADR 0006, "Narrow
callidescope to depth and breadth".
limitsmaximumDepthmaximumBreadthspreadThresholddirectSpreadThresholdminimumCallerscallerMajorityRatioThe implementation-candidate cap is a constant, not a configuration field.
It decides where structural interface resolution stops guessing, which is a
property of the resolution rather than a number any run judges by, so it lives
in and is not written anywhere in .
@callidescope/graphcallidescope.config.ts这里有两个限制,二者都按项目设置,也都用于门禁。
| 限制 | 默认值 | 含义 |
|---|---|---|
| | 调用栈最多允许包含的栈帧数量,包含入口点 |
| 无 | 一个可调用项可直接调用的可调用项数量 |
maximumBreadthbreadth--check breadth首次选择 时:先不带门禁运行一次,查看最深的调用栈,并将限制设置为你希望代码呈现的形状,而不是当前代码恰好达到的数值;如果把限制设为今天的最差数值,它就几乎无法门禁任何东西。
maximumDepth按项目分别选择限制时,应采用边界测试,而不是直接采用某次运行显示的数值。 写下一个候选值,运行该项目的 gate,再把限制降低一级运行一次:一个真正有价值的限制,应当在写下的数值上通过,并在低一级的数值上失败。限定范围的运行所打印摘要涵盖整个 trace,包括依赖闭包,因此它报告的深度通常比被评判项目自身拥有的任何调用栈都深;只有 gate 的判定结果知道哪些 findings 属于该项目。
目前,限制仅是 schema 字段,不承担其他职责。 Schema 是严格的, 只接受 和 。已经退役的字段——、、、——会被拒绝,而不是被静默移除。这四个限制、它们调节的两类 findings,以及背后的模块身份概念,都已从工具中彻底移除;详见 repository 的 ADR 0006《Narrow callidescope to depth and breadth》。
limitsmaximumDepthmaximumBreadthspreadThresholddirectSpreadThresholdminimumCallerscallerMajorityRatio实现候选上限是常量,而不是配置字段。 它决定结构化接口解析在何处停止猜测。这是解析过程本身的属性,并不是任何运行用于判定结果或门禁的数值,因此它位于 中,不会写入任何 。
@callidescope/graphcallidescope.config.tsentryPoints
entryPointsentryPoints
entryPoints| Option | Default | Meaning |
|---|---|---|
| none | Callables named outright as roots, each |
| 13 framework decorators | Decorators whose methods a framework invokes |
| | Treat every |
| | Promote callables nothing in the repository calls |
| | Trace test files too |
addresses<file>#<qualified-name>depthbreadth:<line>ts
entryPoints: {
addresses: ["packages/foo/src/modules/read/read.service.ts#ReadService.read"],
},Declared addresses add roots and take none away: the rules below still run
first, orphan promotion still catches whatever nobody named, and an
already-rooted callable stays one root.
Reach for it when a package sits low in the graph: a stack is filed under the
project owning its root, and most of what such a package publishes is
called from above, so it roots nothing and any limit on it gates nothing.
An address resolving to nothing, to several declarations, or to nothing
parseable fails the whole run — carries each message
and its fix.
callidescope-triagedecoratorsincludeOrphans| 选项 | 默认值 | 含义 |
|---|---|---|
| 无 | 明确指定为根节点的可调用项,每个地址的格式为 |
| 13 个框架 decorator | 其方法会被框架调用的 decorator |
| | 将每个 |
| | 将 repository 中无人调用的可调用项提升为根节点 |
| | 同时 trace 测试文件 |
addressesdepthbreadth<file>#<qualified-name>:<line>ts
entryPoints: {
addresses: ["packages/foo/src/modules/read/read.service.ts#ReadService.read"],
},声明的 addresses 只会增加根节点,不会移除根节点:下面的规则仍会先行执行,orphan 提升仍会捕获所有未命名项,而已经成为根节点的可调用项仍只保留一个根节点身份。
当一个 package 位于调用图底层时,应使用它:调用栈会归入拥有其根节点的项目,而这类 package 发布的多数内容都从上层调用,因此它不会产生根节点,针对它的任何限制也就不会产生门禁效果。如果一个地址无法解析、解析到多个声明,或完全没有可解析内容,整次运行都会失败; 会给出每条消息及其修复方法。
callidescope-triagedecoratorsincludeOrphansKeeping code out of a run
让代码不参与运行
Two tools, for two different questions:
- takes globs and is additive to the built-in defaults (
exclude,node_modules,dist,coverage,output,.nx), so a configuration naming its own noise does not restate them..conformetry - names gitignore-syntax files, workspace-only. This is how a long exclusion list stays out of the configuration file itself, and it is the right home for fixture packages written to be deliberately bad.
excludeFrom - takes globs matched against a callable's display name (
excludeCallees) and drops matching calls from the graph entirely, counting toward neither depth nor breadth. This is for cross-cutting instrumentation: a call to a logger is a fact about instrumentation rather than about the shape of the code around it, and counting it would move every other callable's numbers on a change that has nothing to do with them.Type.member
excludeexcludeFromexcludeCalleests.Programexcludetsconfig.jsonexclude这里有两种工具,分别回答两个不同的问题:
- 接受 glob,并且会叠加到内置默认项(
exclude、node_modules、dist、coverage、output、.nx)之上。因此,配置只需声明自有噪声项,无需再次列出这些默认值。.conformetry - 指定采用 gitignore 语法的文件,并且仅限工作区使用。较长的排除列表可以因此留在配置文件之外;这里也是存放那些故意编写得很糟糕的 fixture package 的合适位置。
excludeFrom - 接受根据可调用项显示名称(
excludeCallees)匹配的 glob,并从调用图中彻底移除匹配调用,调用它们既不计入Type.member,也不计入depth。这项能力适用于横切式插桩:例如,对 logger 的调用反映的是插桩事实,而不是周围代码的形状;如果将其计数,那么与这些调用无关的变更也会改变其他每个可调用项的数值。breadth
excludeexcludeFromexcludeCalleests.Programexcludetsconfig.jsonexcludedirectories
directoriesdirectories
directoriesThe same list takes, set once, workspace-only.
--directories与 相同,只是通过工作区配置一次性设置,且仅限工作区使用。
--directorieswrite
writewrite
writeEvery destination is optional, and unconfigured is the normal case: a run
naming no destination reports to the console and exits non-zero on violations,
so nothing it writes can go stale.
| Key | Purpose |
|---|---|
| A machine-readable report at |
| A marker-delimited block spliced into |
| The same block with the stacks drawn as one flowchart |
write.mermaidwrite.markdownts
write: {
json: { indentation: 2, path: "output/callidescope.json" },
markdown: { path: "docs/call-stacks.md" },
mermaid: { path: "docs/call-stacks-diagram.md" },
},Both take a , placed under the heading, a (defaults to
, and should be set when the block is spliced into a file
that already has a title, since most markdown linters reject a second
first-level heading), and — how many stacks are shown before the
rest go behind a disclosure, three by default. belongs to the
destination rather than to the run because it is a fact about the document the
block lands in: a project's own README wants three and a whole-workspace
report file wants all of them. A whole-run block opens with the summary
counts, one row per project against its own depth limit, and a scoreboard
of how many sit over, on, or clear of theirs; the findings tables follow.
descriptionheading# 🔭 CallidescopepreviewCountpreviewCountThere is no fan-out that writes a section into every project's readme.
Each project declares its own (and , if it
wants a diagram) in its own — see
What a project may set. The workspace's own
is the block that really is about the workspace: the summary
counts, one row per project against its own depth limit, and the scoreboard.
write.markdownwrite.mermaidcallidescope.config.tswrite.markdownA markdown destination may also supply , to replace the built-in
tables, or , to place the block itself — handed
and , so it reuses the same splice. Returning reports
the destination as stale; anything else, included, counts as
current.
renderwriteBlocksyncAnchoredBlockwrapInAnchorsfalseundefined每个目标位置都是可选的,未配置属于正常情况:没有指定目标位置的运行会向控制台报告结果,并在发现违规时以非零状态退出,因此它所写的内容不会过期。
| 键 | 用途 |
|---|---|
| 在 |
| 将带有标记分隔符的区块嵌入 |
| 使用相同区块,但将调用栈绘制为一张 flowchart |
write.mermaidwrite.markdownts
write: {
json: { indentation: 2, path: "output/callidescope.json" },
markdown: { path: "docs/call-stacks.md" },
mermaid: { path: "docs/call-stacks-diagram.md" },
},二者都可提供 ,内容会放在 heading 下方;还可提供 ,默认值为 。当区块被嵌入一个已经有标题的文件时,应设置 heading,因为大多数 Markdown linter 都不允许出现第二个一级标题。二者还可提供 ,用于指定在将其余调用栈放入 disclosure 之前显示多少个,默认是三个。 属于目标位置,而不是整次运行,因为它描述的是最终承载该区块的文档:项目自己的 README 可能只展示三个,而整个工作区的报告文件可能希望展示全部。整次运行的区块开头会显示汇总计数、每个项目相对于自身深度限制的一行结果,以及超过、等于或低于各自限制的项目数量统计;随后才是 findings 表格。
descriptionheading# 🔭 CallidescopepreviewCountpreviewCount不存在把某个区块写入每个项目 README 的扇出机制。 每个项目都在自己的 中声明自己的 (如果需要图表,还需声明 ),详见项目可以设置哪些内容。工作区自身的 对应的才是真正面向整个工作区的区块:汇总计数、每个项目相对于自身深度限制的一行结果,以及相应的统计信息。
callidescope.config.tswrite.markdownwrite.mermaidwrite.markdownMarkdown 目标位置还可以提供 ,用于替换内置表格;或者提供 ,用于放置区块本身。该函数会收到 和 ,从而复用相同的嵌入机制。返回 会将目标位置报告为过期;其他任何返回值,包括 ,都视为内容为最新。
renderwriteBlocksyncAnchoredBlockwrapInAnchorsfalseundefinedEvery traced project's own configuration is required and complete
每个被追踪项目自身的配置都是必需且完整的
A second sits at each traced project's own root, the
directory holding the that makes it a project, found by name in
that directory alone with no upward walk, in any of the same eight extensions.
callidescope.config.tstsconfig.jsonEvery traced project has one, and every one of them is complete. A traced
project with no configuration file at all is refused by name, and so is a file
that leaves a field out. Completeness is deliberate: an absent field and a
field set to the value it would have defaulted to look identical in a diff,
and only one of them was a decision — absent and
used to mean "somebody forgot" and "this project
gates depth and not breadth" respectively, and per-field fallback could not
tell them apart. See the repository's ADR 0007, "Require a complete
configuration from every traced project".
maximumBreadthmaximumBreadth: undefinedThe file a run was pointed at is never also read as a project's — one file, one
role per run. A package whose task names its own configuration and then traces
itself would otherwise have it refused for the workspace-only fields it
legitimately sets, so a package needing both keeps two files under two names.
每个被追踪项目的根目录中还有第二个 。该项目根目录就是包含 、从而使该目录成为项目的目录。该文件只按名称在这个目录中查找,不向上查找,并支持前述八种扩展名中的任意一种。
callidescope.config.tstsconfig.json每个被追踪项目都有一个这样的文件,而且每个文件都是完整的。 完全没有配置文件的被追踪项目会被按名称拒绝,遗漏任何字段的文件也会被拒绝。完整性要求是有意为之:缺失字段与把字段设置为默认值时,在 diff 中看起来完全相同,但二者只有一个代表明确决定。过去, 缺失和 会分别被理解为“有人忘了写”和“该项目只对 depth 设置门禁、不对 breadth 设置门禁”,按字段回退无法区分二者。详见 repository 的 ADR 0007《Require a complete configuration from every traced project》。
maximumBreadthmaximumBreadth: undefined一次运行所指向的文件绝不会被同时当作项目配置读取;一次运行中,一个文件只承担一个角色。如果某个 package 的 task 声明了自己的配置,随后又 trace 自己,那么该文件会因为包含仅限工作区使用的合法字段而被拒绝。因此,需要同时具备两种角色的 package 应在两个不同名称下保留两个文件。
What a project may set
项目可以设置哪些内容
| Field | What it does |
|---|---|
| Which of that project's callables root a stack, |
| The depth every stack rooted in that project is judged against |
| The breadth every callable that project declares is judged against |
| Globs naming that project's own files to leave untraced |
| Where that project's own published section goes |
| Where that project's own diagram goes, when it wants one |
A project's own destinations and globs are anchored to that
project's root, never to the workspace: in
's own file names , and
there writes
. No spelling of either reaches a sibling. A
destination left publishes nothing for that project.
excludeexclude: ["src/generated/**"]packages/thingpackages/thing/src/generated/**write: { markdown: { path: "docs/CALLS.md" } }packages/thing/docs/CALLS.mdundefinedThe run's own stays workspace-relative and is layered underneath, so
a project can leave more out and never put back what the run left out. Noise
spanning several projects still belongs in the workspace file.
excludewrite.jsonEvery other field is refused by name, before anything is traced, and the
message names the six above so it is actionable without opening this skill.
| 字段 | 作用 |
|---|---|
| 指定该项目中哪些可调用项成为调用栈根节点,包括 |
| 评判以该项目为根节点的所有调用栈时采用的深度限制 |
| 评判该项目声明的每个可调用项时采用的广度限制 |
| 指定不 trace 该项目自身哪些文件的 glob |
| 该项目自己发布的区块写入何处 |
| 该项目自己的图表写入何处;如果项目需要图表则可设置 |
项目自身的目标位置和 glob 始终以该项目根目录为基准,绝不会以工作区为基准:例如, 自身文件中的 指向 ,同一文件中的 则写入 。无论采用哪种写法,都无法影响 sibling project。目标位置保持为 时,该项目不会发布任何内容。
excludepackages/thingexclude: ["src/generated/**"]packages/thing/src/generated/**write: { markdown: { path: "docs/CALLS.md" } }packages/thing/docs/CALLS.mdundefined本次运行自身的 仍以工作区为基准,并作为底层规则叠加其上。因此,项目可以排除更多内容,但无法恢复已被本次运行排除的内容。跨越多个项目的噪声仍应放在工作区文件中。
excludewrite.json其他所有字段都会在开始 trace 之前按名称被拒绝,错误消息会列出上表中的六个字段,使操作无需打开本 skill 也能明确。
Spread the defaults, then override
先展开默认值,再进行覆盖
The workspace configuration exports beside its default
export. A project spreads it and overrides what it means to, which is what
makes a complete file cost one line:
projectDefaultsts
import { projectDefaults } from "../../configuration/callidescope.config.js";
export default {
...projectDefaults,
limits: { maximumBreadth: undefined, maximumDepth: 10 },
};Both limits are named even though only one is a real number. is this project saying outright that it gates depth and not breadth
— the one statement an absent field could never distinguish from a project that
forgot. The same holds for and publishing no
diagram.
maximumBreadth: undefinedwrite.mermaid: undefinedSpread , never the workspace's default export. The two are
different objects on purpose: the default export carries ,
, , and the rest of what only the workspace may set,
so spreading it earns a refusal naming the first such field.
holds exactly the surface a project is entitled to, so spreading it cannot
adopt an output destination or an ignore file by accident.
projectDefaultsdirectoriesexcludeFromwrite.jsonprojectDefaultsNothing is resolved across two files, and there is no longer a record of
where a number came from. Every number a project is judged by is written in
that project's own file — there is no per-field fallback to the workspace once
a project's file exists, and no versus distinction left
to draw, because the spread already put the number here where a reader can see
it. Documentation that still talks about a limit being "inherited", or a
project readme carrying an "Origin" column, describes the tool before this
requirement — see the skill for the refusal this
replaced.
declaredinheritedcallidescope-triageThe workspace number carries is a default rather than a
ceiling: a project spreading it and then overriding to a higher limit keeps
its own, because a workspace number pinned by the single worst stack anywhere
gates nothing for the projects nowhere near it.
projectDefaultsentryPointsentryPointsaddresses...projectDefaults.entryPointsWhy the other fields cannot vary per project. and
judge a call graph built once, so two projects asking
different questions of the same edges is coherent. ,
, , and are different: they name what a
run reads, where its own report lands, or how it partitions the workspace, and
a project cannot answer those differently from the run tracing it.
maximumDepthmaximumBreadthexcludeCalleesdirectoriesexcludeFromwrite.json工作区配置会在默认导出之外导出 。项目展开它,再覆盖自己需要覆盖的内容;这使一个完整文件只需增加一行:
projectDefaultsts
import { projectDefaults } from "../../configuration/callidescope.config.js";
export default {
...projectDefaults,
limits: { maximumBreadth: undefined, maximumDepth: 10 },
};虽然两个限制中只有一个是实际数值,但二者都必须明确写出。 表示该项目明确只对 depth 设置门禁、不对 breadth 设置门禁;这是缺失字段永远无法与“项目忘记填写”区分开的唯一明确声明。 以及不发布图表,也遵循同样的原则。
maximumBreadth: undefinedwrite.mermaid: undefined应展开 ,绝不能展开工作区的默认导出。 二者有意使用不同对象:默认导出包含 、、 以及其他仅限工作区设置的内容,因此展开它会立刻触发拒绝,并指出第一个不允许的字段。 恰好包含项目有权设置的界面,因此展开它不会意外继承输出目标或 ignore 文件。
projectDefaultsdirectoriesexcludeFromwrite.jsonprojectDefaults不会跨两个文件解析任何内容,也不再保留数值来源记录。 项目评判所依据的每个数值都写在项目自己的文件中;一旦项目文件存在,就不会按字段回退到工作区设置,也不再需要区分 与 ,因为展开操作已经将数值放在读者可以看到的当前位置。仍在讨论限制被“继承”的文档,或仍带有 “Origin” 列的项目 README,描述的都是这项要求出现之前的工具;关于它所替代的拒绝行为,请参阅 skill。
declaredinheritedcallidescope-triageprojectDefaultsentryPointsentryPointsaddresses...projectDefaults.entryPoints为什么其他字段不能按项目变化。 和 用于评判同一份只构建一次的调用图,因此两个项目针对同一批边提出不同问题是可以理解的。、、 和 则不同:它们定义一次运行读取什么、自己的报告写到哪里,或如何划分工作区;项目不能针对同一次 trace 给出不同答案。
maximumDepthmaximumBreadthexcludeCalleesdirectoriesexcludeFromwrite.jsonReading the whole set back
回读完整集合
A ratchet written one file per project is no longer reviewable in the single
file it used to live in. The command is where it is reviewable as a
set instead:
limitsbash
npx callidescope limitsA markdown table, one row per project per limit — , , ,
— naming the file each number is written in. means
nothing anywhere declares that limit, the usual case for breadth. The
row comes first and is the only one that may carry no file: it is
the default every project's own file spreads, not a number any file wrote down
for itself. It resolves configuration and measures nothing, so it costs
milliseconds rather than a trace.
ProjectLimitValueDeclared innoneworkspace如果棘轮式约束改成每个项目一个文件,就无法再像过去那样在单个文件中完成审查。 命令可以按集合形式进行审查:
limitsbash
npx callidescope limits它会输出一个 Markdown 表格,每个项目的每项限制各占一行——、、、——并指出写入相应数值的文件。 表示任何地方都没有声明该限制,这也是 的常见情况。 行位于最前面,并且是唯一可能没有对应文件的行:它表示每个项目自身文件所展开的默认值,而不是任何文件为自己明确写下的数值。该行只解析配置,不执行任何测量,因此只需数毫秒,而不必执行 trace。
ProjectLimitValueDeclared innonebreadthworkspaceAfter changing any of this
修改这些内容之后
A configuration change usually moves the numbers, making every committed report
stale. Re-run the write configuration in the same change, and lint before
regenerating: every frame carries a , so a formatter that sorts class
members moves the line numbers after it, and a report written before that sort
is stale the moment it lands.
file:lineWhen a run is refused or a report reads stale, reach for .
To read what a run printed, reach for .
callidescope-triagecallidescope-trace配置变更通常会改变数值,从而使所有已提交报告过期。应在同一次变更中重新运行 write 配置,并且先执行 lint,再重新生成报告:每个栈帧都带有 ,因此,如果 formatter 对 class member 进行了排序,生成报告后行号就会发生变化;在排序前生成的报告会在写入瞬间立刻过期。
file:line当运行被拒绝或报告显示过期时,请使用 。要阅读一次运行的输出,请使用 。
callidescope-triagecallidescope-trace