The RFC, source-implementation research, GitHub architecture research,
ranking evaluation report, 2026-08-14 optimization plan and ten-round
review record were six separate files that cross-linked each other for
the same decision chain. They are merged into
docs/tool-search-progressive-discovery.md as Part 1..6, ordered
decision -> research -> evidence -> plan -> review record.
- cross-file links become in-document "本文档 Part N" pointers; the five
remaining relative links (source and evaluator paths) still resolve
- section content is unchanged apart from one addition: 5.8 Inspect now
records the path-form boundary (multi-token args resolve as a CLI path;
a canonical path must be passed as a single argument), matching the
dws schema help text
Fifth-review addition: declaring InputFile silently claims the whole
@-prefixed value space, which matters in this product because at-mention
style values are common (--at-user @zhangsan would report a file read
failure), and declaring InputStdin makes a literal "-" unreachable. Both
are decided at declaration time and cannot be fixed downstream, so record
them next to the confirmation rule in the author rules.
Fourth-review fix: the FlagSpec sub-field table in the homology doc is
the named authority for "what each field does and whether it reaches
Schema parameters", and RFC §5.0.2 asserts declaration fields embed into
dws.schema.*. Input satisfied neither entry, leaving its deliberate
non-projection indistinguishable from an oversight. Add the table row and
the §5.0.2 exception note so the capability stays a declared fact (Usage
prose) rather than inviting an invented annotation.
Document the landed corecmd.Input transitional form: declaration shape
(FlagSpec/LeafFlag/shortcut.Flag), runtime resolution semantics and
ordering, author rules (help prose, confirmation interaction with
stdin, construction-time validation), and the delta table against the
target typed InputSource design.
The Coverage context was the PR critical path (~17 min end to end):
coverage-current re-ran the whole suite serially (-p 1, ~13 min) and
coverage-baseline re-ran it again at the merge-base (~13 min) although
that profile is a pure function of the base commit.
- coverage-current now owns only the scoped (standard-tier) profile;
full-suite candidate profiles come from a 5-way shard matrix
(app/cli/generators/helpers/remaining) that keeps -p 1 inside each
shard on isolated runners. scripts/ci/test-packages.sh list-coverage
defines the shards and verify proves the union equals the previous
single-run package set exactly once.
- the aggregate Coverage job reassembles the disjoint shard profiles
into coverage.txt before make coverage-gate, failing closed when a
shard file is missing, so gate semantics (100% changed-code +
scope-matched overall non-regression) are byte-compatible.
- coverage-baseline restores the merge-base full-suite profile from an
exact-key cache (merge-base SHA + resolved Go version) written by the
last green main push; any miss falls back to recomputing in the
merge-base worktree. Exact key only - no prefix fallback, a near-miss
profile would compare the candidate against the wrong commit.
- new contract tests pin the shard matrix, the assembly step, the
exact-key cache pair, and the absence of restore-keys; the package
plan test also covers the coverage shard partition.
Self-review follow-ups on the ranking hardening series:
- the avoid_when boilerplate filter compared lowercased phrases against
a mixed-case constant, so the "需要该 Shortcut..." noise filter never
fired; the constant is now lowercase (no ranking change: the boilerplate
was never contained by any query, sentinel 990/1123 unchanged)
- add direct unit coverage for the avoid_when penalty (echoed-phrase
match, unrelated-query pass-through, boilerplate filter, partial
overlap, explain annotation)
- update tool-search-ranking-evaluation.md to the post-hardening
numbers (ensemble R@5 88.16%, Forbidden 0%/0%, action_v1 shadow
84.24% with the trade-off recorded)
- drop the dead algorithm_freeze manifest block; nothing consumes it
after the hash decoupling
- default engine: fielded BM25 ensemble (action_v1 remains a shadow candidate)
- add --explain score_breakdown: per-field contributions, structured
multiplier, query classification and avoid_when penalty
- add DWS_TOOL_SEARCH_* env overrides (algorithm, k1/b, field weights,
explain) for release-independent tuning and rollback
- tokenizer: CJK unigram+bigram so single-character intents match; align
isToolSearchCJK with unicode.Han used by the evaluation slices
- structured routing: extend vocabularies with English synonyms,
word-boundary matching for ASCII values, restrict the rerank gate to
technical identifiers only
- avoid_when demotion layer wraps every lexical algorithm (Forbidden@5
proxy 37.55% -> 0); intent-overlap matching rejected after control
showed it demoted gold answers (Recall@5 0.8664 -> 0.7845)
- remove the OA task_id +1.00 fixture-specific multiplier
- build the default engine once per process for long-lived hosts
- evaluation baseline: intent-proxy R@5 990/1123 (88.16%); update
integration sentinels accordingly