@dailephd/my-dev-kit-lab 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +10 -5
  3. package/benchmarks/contracts/warm-index-benchmark-cases.json +330 -0
  4. package/dist/src/cli/help.js +27 -4
  5. package/dist/src/commands/runExperimentDescribeCommand.js +13 -2
  6. package/dist/src/commands/runExperimentRunCommand.js +210 -20
  7. package/dist/src/core/fileGlobs.js +44 -0
  8. package/dist/src/evaluation/benchmarkMetadata.js +13 -0
  9. package/dist/src/evaluation/localRepositorySubject/config.js +296 -0
  10. package/dist/src/evaluation/localRepositorySubject/evaluationCase.js +36 -0
  11. package/dist/src/evaluation/localRepositorySubject/expectedFiles.js +51 -0
  12. package/dist/src/evaluation/localRepositorySubject/gitRepository.js +128 -0
  13. package/dist/src/evaluation/localRepositorySubject/index.js +8 -0
  14. package/dist/src/evaluation/localRepositorySubject/inventory.js +127 -0
  15. package/dist/src/evaluation/localRepositorySubject/loadLocalRepositorySubject.js +48 -0
  16. package/dist/src/evaluation/localRepositorySubject/manifest.js +52 -0
  17. package/dist/src/evaluation/localRepositorySubject/types.js +55 -0
  18. package/dist/src/evaluation/projectFileTree.js +45 -1
  19. package/dist/src/evaluation/retrievalQuality/buildRetrievalEvidence.js +292 -0
  20. package/dist/src/evaluation/retrievalQuality/corpusCompleteness.js +122 -0
  21. package/dist/src/evaluation/retrievalQuality/factContextTargets.js +44 -0
  22. package/dist/src/evaluation/retrievalQuality/index.js +5 -0
  23. package/dist/src/evaluation/retrievalQuality/metrics.js +233 -0
  24. package/dist/src/evaluation/retrievalQuality/types.js +9 -0
  25. package/dist/src/evaluation/runMyDevKitRetrieval.js +6 -1
  26. package/dist/src/evaluation/runRawFullFileBaseline.js +18 -4
  27. package/dist/src/evaluation/targetImmutability/captureTargetSnapshot.js +29 -7
  28. package/dist/src/evaluation/targetImmutability/compareTargetSnapshots.js +4 -0
  29. package/dist/src/experiments/defaultRegistry.js +2 -0
  30. package/dist/src/experiments/plugins/contextWindowScaling/localSubjectErrors.js +35 -0
  31. package/dist/src/experiments/plugins/contextWindowScaling/localSubjectExclusions.js +75 -0
  32. package/dist/src/experiments/plugins/contextWindowScaling/localSubjectExecution.js +136 -0
  33. package/dist/src/experiments/plugins/contextWindowScaling/localSubjectPrivacy.js +128 -0
  34. package/dist/src/experiments/plugins/contextWindowScaling/localSubjectScratch.js +85 -0
  35. package/dist/src/experiments/plugins/contextWindowScaling/metadata.js +2 -2
  36. package/dist/src/experiments/plugins/contextWindowScaling/plugin.js +93 -0
  37. package/dist/src/experiments/plugins/contextWindowScaling/projectProfile.js +4 -9
  38. package/dist/src/experiments/plugins/index.js +1 -0
  39. package/dist/src/experiments/plugins/retrievalPrecisionRecall/config.js +39 -0
  40. package/dist/src/experiments/plugins/retrievalPrecisionRecall/execution.js +152 -0
  41. package/dist/src/experiments/plugins/retrievalPrecisionRecall/executionArtifact.js +15 -0
  42. package/dist/src/experiments/plugins/retrievalPrecisionRecall/index.js +9 -0
  43. package/dist/src/experiments/plugins/retrievalPrecisionRecall/localSubjectExecution.js +139 -0
  44. package/dist/src/experiments/plugins/retrievalPrecisionRecall/localSubjectPrivacy.js +119 -0
  45. package/dist/src/experiments/plugins/retrievalPrecisionRecall/metadata.js +21 -0
  46. package/dist/src/experiments/plugins/retrievalPrecisionRecall/metrics.js +158 -0
  47. package/dist/src/experiments/plugins/retrievalPrecisionRecall/plugin.js +253 -0
  48. package/dist/src/experiments/plugins/retrievalPrecisionRecall/types.js +8 -0
  49. package/dist/src/report/experiments/buildPluginExperimentReport.js +21 -2
  50. package/dist/src/report/experiments/buildRetrievalPrecisionRecallReport.js +83 -0
  51. package/dist/src/report/experiments/index.js +4 -0
  52. package/dist/src/report/experiments/renderPluginExperimentReportHtml.js +7 -3
  53. package/dist/src/report/experiments/renderPluginExperimentReportText.js +9 -0
  54. package/dist/src/report/experiments/renderRetrievalPrecisionRecallHtml.js +96 -0
  55. package/dist/src/report/experiments/renderRetrievalPrecisionRecallText.js +121 -0
  56. package/dist/src/report/experiments/retrievalPrecisionRecallReportModel.js +3 -0
  57. package/dist/src/report/experiments/writePluginExperimentReports.js +8 -2
  58. package/docs/METRICS.md +34 -2
  59. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,34 @@ All notable changes to my-dev-kit-lab are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.8.0] - 2026-10-04
8
+
9
+ ### Retrieval precision/recall
10
+
11
+ - Added `retrieval-evidence-v1`, a deterministic observation of the existing my-dev-kit search, lookup, slice, and source lifecycle (retrieved files and symbols with `available`, `partial`, or `unavailable` status, safe repository-relative paths, fail-closed parsing, and no source-body scraping).
12
+ - Added a deterministic retrieval-quality metric engine: file precision and recall, symbol precision and recall, fact coverage from explicit `factIds`-to-context mappings, irrelevant context ratio, retrieved token count, and the missed files, missed symbols, and uncovered fact IDs, with explicit `available`, `unavailable`, and `not-applicable` states. It produces no ranking or winner.
13
+ - Added the `retrieval-precision-recall` experiment plugin with one `my-dev-kit-retrieval` variant and a bundled 12-case corpus (the warm-index benchmark cases, with explicit fact mappings) over two benchmark projects, one index per project and one retrieval per case. No agent is invoked. `experiment run --experiment retrieval-precision-recall` accepts `--out`, `--case`, `--benchmark-project`, and `--kit-command`.
14
+ - Added the `retrieval-precision-recall-execution.json` artifact and specialized deterministic JSON, HTML, and text reports.
15
+ - Added external-local support through the existing `LocalRepositorySubject` architecture: `--target <repository>` with `--local-subject-config <path>` runs one private index per configured case from its exact source roots, excludes Git-ignored and oversized files, enforces the eligible file universe, treats the repository as read-only, removes private scratch before persistence, and writes `local-repository-subject-manifest.json`. A failed external run writes no normal artifact, report, or manifest family.
16
+ - Durable external-local output redacts the repository path, tool and output roots, file, symbol, and fact identities, case titles, and retrieval warning text, and preserves exact numeric evidence.
17
+ - Extended the packed-package acceptance gate (`npm run verify:packed-package`) to cover installed plugin discovery, bundled and external-local execution, privacy, failure paths, and package and target immutability.
18
+ - Corrected cross-platform portability of the retrieval-precision-recall verification: the packed-package gate now checks private-scratch containment against the physical output root (Windows short-name aliases), and the related unit and report tests use platform-native paths and separate runtime state from durable output.
19
+ - Not included: ranked retrieval metrics, retrieval-strategy comparison, strategy ranking or winner selection, context packs, and real-agent evaluation.
20
+
21
+ ## [0.7.2] - 2026-10-04
22
+
23
+ ### Local-repository experiments
24
+
25
+ - Added explicitly selected local Git repositories as `context-window-scaling` subjects: `experiment run --experiment context-window-scaling --target <repository> --local-subject-config <path>`, with a strict `LocalRepositorySubjectConfigV1`. The experiment, its treatments, budgets, token estimator, correctness, success, plots, and report schemas are unchanged, and bundled and synthetic modes behave as before.
26
+ - Contexts for both treatments are built only from regular files inside the declared source roots that Git does not ignore and that are at most 1 MiB; ignored, oversized, symbolic-link, and other unsafe entries are excluded, and the guided treatment fails if retrieval returns an excluded file.
27
+ - The repository is treated as read-only: private scratch state is created outside it and removed, repository state is compared before and after the run, and an output directory equal to or inside the repository is rejected. A detected change fails the run and is not reverted.
28
+ - Durable external-local output omits the repository path, source text, and file names: exact file identities appear as numbered `<redacted file N>` placeholders marked by `fileIdentityRedaction: "redacted"`, and the report target carries `privacyProjection: "external-local-redacted"`. A new `local-repository-subject-manifest.json` records the logical subject ID, full Git commit, branch, dirty state, safety policy, source roots, case IDs, and aggregate size counts.
29
+ - A failed external-local run exits nonzero with a bounded error and writes no report, execution artifact, or manifest.
30
+ - Fixed a crash in which a local-repository run pointed at a directory past the Windows path-length limit ended with an unhandled stream error instead of a classified error, and made known-file redaction in error text cover backslash-separated paths.
31
+ - Extended help, `experiment describe` text, and the packed-package acceptance gate (`npm run verify:packed-package`) to cover the installed external-local run with the real published my-dev-kit, rejection cases, privacy scanning that includes JSON-escaped Windows paths, and target immutability.
32
+ - Replaced a trailing-slash regular expression in glob base normalization with a linear scan after a CodeQL polynomial-regular-expression finding; glob selection behavior is unchanged.
33
+ - No retrieval precision, recall, ranking, or winner metric was added; those remain planned for v0.8.0.
34
+
7
35
  ## [0.7.1] - 2026-10-02
8
36
 
9
37
  ### Synthetic large-repository generator
package/README.md CHANGED
@@ -6,7 +6,9 @@ my-dev-kit provides local repository indexing and graph-guided retrieval. my-dev
6
6
 
7
7
  Whole-ecosystem workflows are centralized in [my-dev-kit/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md). Its [command-surface compatibility map](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md#915-command-surface-compatibility-map) documents which Lab outputs can safely seed my-dev-kit investigation, Observer reference work, or Orchestrator evidence, and which look-alike artifacts are not direct inputs.
8
8
 
9
- The latest release is v0.7.1 (synthetic large-repository generator), and the published package and installed CLI are version 0.7.1. The previous release is v0.7.0 (context-window scaling), and v0.7.2 (real/local external repository experiments) is planned after the current release. The v0.4.5 context-integrity evaluation remains intentionally frozen against the published `@dailephd/my-dev-kit@1.10.4` and `@dailephd/my-dev-kit-orchestrator@1.2.3` contracts; those versions are historical validation baselines, not a statement that they are the ecosystem's current releases. See [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md) for current state.
9
+ The latest release is v0.8.0 (retrieval precision/recall), and the published package and installed CLI are version 0.8.0. The previous release is v0.7.2 (local-repository experiments). The v0.4.5 context-integrity evaluation remains intentionally frozen against the published `@dailephd/my-dev-kit@1.10.4` and `@dailephd/my-dev-kit-orchestrator@1.2.3` contracts; those versions are historical validation baselines, not a statement that they are the ecosystem's current releases. See [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md) for current state.
10
+
11
+ v0.8.1 (retrieval query strategy comparison) is the next planned milestone.
10
12
 
11
13
  v0.4.6 adds a supported `my-dev-kit-lab` installed CLI router (`--help`, `--version`, `security validate`, `audit`, the `experiment` family, `report render`, `plots generate`, `gallery build`, `demo final`, and the historical direct final-demo invocation form), a writable lab workspace model kept separate from the installed package and the inspected target, and a permanent packed-tarball installation/execution acceptance gate (`npm run verify:packed-package`). See [docs/ROADMAP.md](docs/ROADMAP.md) and [docs/CURRENT_STATE.md](docs/CURRENT_STATE.md) for status detail and [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the runtime path model. The "Installed CLI" section below documents the shipped command surface; the source-checkout `npm run` workflow in Quickstart remains available for contributors.
12
14
 
@@ -16,9 +18,11 @@ v0.4.6 adds a supported `my-dev-kit-lab` installed CLI router (`--help`, `--vers
16
18
  - **Measure warm-index reuse (v0.5.0–v0.5.1, released):** the `warm-index-reuse` experiment plugin builds one my-dev-kit index per benchmark project, reuses it across that project's tasks, and compares every task with a matched `raw-full-file` baseline. Reports separate one-time index-build cost from per-task retrieval cost, show amortized index cost and cumulative measurements, and include deterministic fake-agent correctness and token evidence; `plots generate` renders four warm-index SVG charts. The v0.5.1 release adds a dedicated 12-task benchmark corpus (`benchmarks/contracts/warm-index-benchmark-cases.json`: six medium and six large/mixed tasks tagged `localized`, `cross-module`, or `broad-change`) for comparing warm-index behavior as task count grows. Estimated context tokens (a character-based context-size estimate) and fake-agent total tokens (simulated harness telemetry) are reported separately, and neither is provider billing telemetry.
17
19
  - **Run selectable real-agent warm-index campaigns (v0.5.2, released):** `--campaign codex-full`, `claude-full`, or `codex-timeout-isolation` (with `--include-real-agents`) runs exactly one provider — Codex or Claude — against the exact raw and warm contexts the experiment already measured, over the frozen production corpus each preset owns. Provider outcomes (`completed`, `failed`, `timeout`, `invalid-output`, `agent-unavailable`, `agent-limit-reached`, `skipped`) are classified and reported separately from warm-index infrastructure status, so a campaign can complete its indexing/retrieval work even when provider evidence is partial or unavailable. A campaign run automatically produces the report, the same four warm-index SVG charts, and a three-item gallery (report, plots, bounded execution evidence). Its report screenshot is best-effort presentation evidence: unavailable browser runtime or failed capture is reported explicitly, no PNG is fabricated, and neither outcome fails an otherwise successful campaign. Legacy runs without `--campaign` keep the existing deterministic fake-agent, report-only behavior unchanged. See [docs/WORKFLOWS.md](docs/WORKFLOWS.md#warm-index-reuse-experiment) and [docs/METRICS.md](docs/METRICS.md#warm-index-reuse-metrics).
18
20
  - **Record index freshness evidence (v0.6.0):** a warm-index run captures an index snapshot after its one index build — the exact indexed file set from the my-dev-kit index contract, each with SHA-256 content identity, size, and modified-time metadata, plus the my-dev-kit version and index-command evidence — and assesses freshness immediately before each task's warm retrieval as `fresh`, `stale`, `partially-stale`, or `unknown`. The evidence appears in `warm-index-execution.json` and in the existing `report.json`/`report.txt`/`report.html` warm-index reports. It is observational only: it covers only files the snapshot lists (not the whole repository), never changes retrieval, execution or provider status, and adds no CLI flag, metric, plot, gallery item, or reindex recommendation in v0.6.0. See [docs/METRICS.md](docs/METRICS.md#index-freshness-evidence-v060) and [docs/WORKFLOWS.md](docs/WORKFLOWS.md#warm-index-reuse-experiment).
19
- - **Compare no-refresh, partial-refresh, and full-refresh retrieval after a controlled change (v0.6.3, previous release):** the `incremental-change-staleness` experiment plugin runs six frozen controlled-change scenario families (unrelated-file, local-implementation, exported-symbol, public-API, import-graph, and test-only changes) against four disposable target copies — `stale-index` (no refresh), `changed-files-refresh` and `affected-neighborhood-refresh` (real partial refreshes performed by my-dev-kit 1.12.5 through `index --incremental --refresh-scope`, selected internally with no Lab-level flag), and `full-refresh` (a complete new post-change index, used as a comparison reference rather than a preferred treatment). Each partial treatment truthfully records whether upstream applied the requested partial scope or fell back to a full rebuild (`APPLIED_PARTIAL` or `FALLBACK_FULL`); a fallback is not counted as partial-refresh evidence. Three comparisons against `full-refresh` are persisted with retrieval, deterministic fake-agent correctness, and required-file evidence in `incremental-change-staleness-execution.json` (schema `my-dev-kit-lab-incremental-change-staleness-execution-v2`) and the existing `report.json`/`report.txt`/`report.html`; historical v0.6.2 (V1) artifacts stay readable. There is no winner, ranking, or safety claim, and the plugin is self-only (`--target` is not accepted). `--kit-command` also accepts `incremental-change-staleness` and now defaults to my-dev-kit 1.12.5. See [docs/WORKFLOWS.md](docs/WORKFLOWS.md) and [docs/METRICS.md](docs/METRICS.md).
21
+ - **Compare no-refresh, partial-refresh, and full-refresh retrieval after a controlled change (v0.6.3, released; retained in the current package):** the `incremental-change-staleness` experiment plugin runs six frozen controlled-change scenario families (unrelated-file, local-implementation, exported-symbol, public-API, import-graph, and test-only changes) against four disposable target copies — `stale-index` (no refresh), `changed-files-refresh` and `affected-neighborhood-refresh` (real partial refreshes performed by my-dev-kit 1.12.5 through `index --incremental --refresh-scope`, selected internally with no Lab-level flag), and `full-refresh` (a complete new post-change index, used as a comparison reference rather than a preferred treatment). Each partial treatment truthfully records whether upstream applied the requested partial scope or fell back to a full rebuild (`APPLIED_PARTIAL` or `FALLBACK_FULL`); a fallback is not counted as partial-refresh evidence. Three comparisons against `full-refresh` are persisted with retrieval, deterministic fake-agent correctness, and required-file evidence in `incremental-change-staleness-execution.json` (schema `my-dev-kit-lab-incremental-change-staleness-execution-v2`) and the existing `report.json`/`report.txt`/`report.html`; historical v0.6.2 (V1) artifacts stay readable. There is no winner, ranking, or safety claim, and the plugin is self-only (`--target` is not accepted). `--kit-command` also accepts `incremental-change-staleness` and now defaults to my-dev-kit 1.12.5. See [docs/WORKFLOWS.md](docs/WORKFLOWS.md) and [docs/METRICS.md](docs/METRICS.md).
20
22
  - **Measure context-window scaling (v0.7.0, released):** the self-only `context-window-scaling` plugin compares `raw-full-file` and `my-dev-kit-guided` over 8k, 16k, 32k, 64k, or custom positive-integer estimated-token budgets. It records fit, utilization, deterministic fake-agent correctness/success, and omitted expected relevant files, with JSON/text/HTML reports and three SVG plots. `plots generate` reads `context-window-scaling-execution.json`. Token counts are a character-based estimate, not provider-tokenizer or billing data; fake-agent correctness is context-independent in the current harness. See [docs/WORKFLOWS.md](docs/WORKFLOWS.md), [docs/METRICS.md](docs/METRICS.md), and [docs/COMMANDS.md](docs/COMMANDS.md).
21
- - **Run context-window scaling over synthetic repositories (v0.7.1, current release):** `context-window-scaling` uses the bundled fixed corpus by default, or `--synthetic-config <path>` (a `SyntheticRepositoryConfigV1` JSON file) to generate disposable deterministic TypeScript/Python repositories beneath the run output. The option is a command input selector, not plugin scientific config; it is mutually exclusive with `--case`, and the scientific semantics, execution artifact, reports, and plots are unchanged. See [docs/COMMANDS.md](docs/COMMANDS.md) and [docs/WORKFLOWS.md](docs/WORKFLOWS.md).
23
+ - **Run context-window scaling over synthetic repositories (v0.7.1, released):** `context-window-scaling` uses the bundled fixed corpus by default, or `--synthetic-config <path>` (a `SyntheticRepositoryConfigV1` JSON file) to generate disposable deterministic TypeScript/Python repositories beneath the run output. The option is a command input selector, not plugin scientific config; it is mutually exclusive with `--case`, and the scientific semantics, execution artifact, reports, and plots are unchanged. See [docs/COMMANDS.md](docs/COMMANDS.md) and [docs/WORKFLOWS.md](docs/WORKFLOWS.md).
24
+ - **Run context-window scaling over a local Git repository (v0.7.2, released):** `context-window-scaling` can also run against an explicitly selected local Git repository with `--target <repository> --local-subject-config <path>` (a `LocalRepositorySubjectConfigV1` JSON file). The Lab treats the repository as read-only and compares its state before and after the run, builds contexts only from files Git does not ignore (ignored, oversized (over 1 MiB), symbolic-link, and other unsafe entries are excluded), requires the output directory to be outside the repository, and keeps the repository path, source text, and file names out of durable artifacts (file identities appear as numbered `<redacted file N>` placeholders). A `local-repository-subject-manifest.json` records the logical subject ID, the full Git commit, the branch, and aggregate size metadata. This measures operational context fit only, not retrieval precision, recall, or ranking quality. It is part of the current package. See [docs/COMMANDS.md](docs/COMMANDS.md) and [docs/WORKFLOWS.md](docs/WORKFLOWS.md).
25
+ - **Measure retrieval precision and recall (v0.8.0, released):** the `retrieval-precision-recall` plugin runs the existing my-dev-kit search, lookup, slice, and source lifecycle for each case and compares the retrieved files and symbols with a deterministic answer key, without invoking any agent. It reports file precision and recall, symbol precision and recall, fact coverage (from explicit fact-to-context mappings), irrelevant context ratio, the estimated retrieved token count, and the missed and irrelevant identities, as `retrieval-precision-recall-execution.json` plus `report.json`, `report.html`, and `report.txt`. By default it runs a bundled 12-case corpus over two benchmark projects against the Lab itself. It can also run over an explicitly selected local Git repository with `--target <repository> --local-subject-config <path>`; in that mode the repository is treated as read-only and durable outputs redact the repository path and file, symbol, and fact identities while keeping the numeric evidence. These are set-based measures with no ranking, winner, or composite score. See [docs/COMMANDS.md](docs/COMMANDS.md), [docs/WORKFLOWS.md](docs/WORKFLOWS.md), and [docs/METRICS.md](docs/METRICS.md).
22
26
  - **Assess affected-neighborhood evidence (v0.6.1, released; retained in the current package):** using the baseline my-dev-kit graph of the same prepared warm index (loaded once per session), each task's confirmed modified or missing indexed files, and the baseline symbols those files contain, are mapped to graph nodes. The affected neighborhood is those seed nodes plus their direct one-hop neighbors (edges of any kind, either direction). The task's `expectedFiles` and file-scoped `expectedSymbols` are mapped to graph nodes and compared with that neighborhood, which yields six numeric warm-side metrics (`changedFileCount`, `changedSymbolCount`, `affectedNodeCount`, `affectedEdgeCount`, `taskOverlapCount`, `taskOverlapPercent`) plus categorical evidence: a `related`, `unrelated`, or `unknown` relationship and a `recommended`, `not-indicated`, or `unknown` `reindexRecommendation`. Incomplete evidence is reported as `unknown`, never as unrelated. The assessment is recorded additively in `warm-index-execution.json` and shown in the existing `report.json`/`report.txt`/`report.html` warm-index reports. It is observational only: retrieval, execution status, and provider status are unchanged, nothing is reindexed automatically, and no CLI flag, experiment plugin, plot, or gallery item was added. See [docs/METRICS.md](docs/METRICS.md#affected-neighborhood-metrics-v061) and [docs/WORKFLOWS.md](docs/WORKFLOWS.md#warm-index-reuse-experiment).
23
27
  - **Audit repository health:** run conservative code-rot detectors for TypeScript/JavaScript, Python, Java, and Kotlin, or adapt security findings into the common audit report.
24
28
  - **Validate CLI/package security:** inspect dependencies, package contents, path and subprocess boundaries, malformed inputs, optional static scanners, and bounded fuzz targets.
@@ -238,12 +242,13 @@ See [docs/METRICS.md](docs/METRICS.md) for full metric definitions.
238
242
  - Claude and Codex token totals are used only when the CLI/run exposes them; missing provider token evidence stays explicitly unavailable (never zero, and never substituted with an estimated context-token count)
239
243
  - Codex and Claude campaign runs can produce timeouts, invalid-output, agent-unavailable, or agent-limit-reached outcomes; these are structured provider states, not warm-index infrastructure failures
240
244
  - Small projects may make raw-full-file cheaper than my-dev-kit-guided; larger localized tasks are where my-dev-kit is expected to become more useful
241
- - The generic experiment-plugin framework has four registered plugins: `context-strategy-comparison`, `warm-index-reuse`, `incremental-change-staleness`, and `context-window-scaling`. The v0.7.0 context-window-scaling plugin is released; v0.7.1 lets it also run over caller-supplied synthetic repositories; external/local repository experiments (v0.7.2), retrieval precision/recall, and agent-success plugins remain planned.
245
+ - The generic experiment-plugin framework has five registered plugins: `context-strategy-comparison`, `warm-index-reuse`, `incremental-change-staleness`, `context-window-scaling`, and `retrieval-precision-recall`. The v0.7.0 context-window-scaling plugin is released; v0.7.1 lets it also run over caller-supplied synthetic repositories; v0.7.2 lets it run over an explicitly selected local Git repository. The fifth, `retrieval-precision-recall`, was added in v0.8.0; agent-success plugins remain planned.
246
+ - `retrieval-precision-recall` (v0.8.0) measures set-based retrieval quality, not ranked retrieval: it has no ranking metrics, no retrieval-strategy comparison yet (planned for v0.8.1), no winner or composite score, and no real agents. Its lifecycle expands only the top search candidate. An external-local run fails as a whole if any case fails a safety or execution check, and then writes no normal artifact or report family. Durable external-local identities are redacted, although the console summary of a successful run can still show the physical output directory. Platform path-length limits can make a run with very long paths fail cleanly instead of executing.
242
247
  - `warm-index-reuse` without `--campaign` still uses the deterministic fake agent only. With `--campaign`, exactly one real provider (Codex or Claude) runs per campaign preset — there is no multi-agent matrix, retry, provider switching, or scheduler. The v0.5.1 expanded corpus is deterministic fake-agent benchmark evidence when run without `--campaign`. No warm-index mode calculates a token-savings percentage, break-even task, winner, or ranking, and component-duration sums are not wall-clock latency
243
248
  - The current release does not guarantee token savings; it produces auditable evidence for specific cases, targets, agents, and strategies
244
249
  - Context-window scaling uses estimated tokens (`ceil(characters / 4)`) and experiment budgets, not actual provider tokenizer or model-window limits. Its deterministic fake-agent correctness check does not measure semantic sensitivity to the supplied context.
245
250
  - Released v0.6.1 affected-neighborhood evidence is bounded to the baseline graph of the prepared index and to the snapshot-represented files: a changed symbol means the symbol was present in a confirmed changed indexed file, not that its own text was proven to change; `not-indicated` means only that this bounded analysis found no supporting evidence for reindexing, not that skipping a reindex is safe; unresolved or ambiguous expected symbols keep a task at `unknown` rather than unrelated
246
- - v0.6.3 (previous release) partial-refresh evidence is scoped to the executed deterministic scenarios and the configured my-dev-kit 1.12.5-or-later tool. A partial treatment can fall back to a full rebuild and is then reported as not comparable as partial refresh, so an applied partial refresh in one run does not guarantee the next; `no-observed-regression-relative-to-full` is not a safety claim, and full refresh is a reference rather than a winner. Correctness remains deterministic fake-agent evidence, and `incremental-change-staleness` accepts no external `--target`.
251
+ - v0.6.3 partial-refresh evidence is scoped to the executed deterministic scenarios and the configured my-dev-kit 1.12.5-or-later tool. A partial treatment can fall back to a full rebuild and is then reported as not comparable as partial refresh, so an applied partial refresh in one run does not guarantee the next; `no-observed-regression-relative-to-full` is not a safety claim, and full refresh is a reference rather than a winner. Correctness remains deterministic fake-agent evidence, and `incremental-change-staleness` accepts no external `--target`.
247
252
  - Provider telemetry dashboards, semantic LLM judging, and cloud API billing integration are not yet implemented
248
253
  - The six new stage-context strategies have no CLI flags yet, are configured programmatically, and do not yet include plots, screenshots, or gallery integration
249
254
  - The published upstream artifacts the stage-context strategies read do not expose considered-but-unselected reads or unnecessary-read evidence; those metrics report `unavailable` rather than zero
@@ -41,6 +41,32 @@
41
41
  "required": true
42
42
  }
43
43
  ],
44
+ "expectedContextTargets": [
45
+ {
46
+ "file": "src/services/importTasks.ts",
47
+ "symbols": ["importTasks"],
48
+ "required": true,
49
+ "factIds": ["warm-medium-import-validates-title-and-project", "warm-medium-import-skips-duplicates-by-project-and-normalized-title", "warm-medium-import-keeps-deterministic-task-sequences"]
50
+ },
51
+ {
52
+ "file": "src/validation/taskValidation.ts",
53
+ "symbols": ["validateImportInput"],
54
+ "required": true,
55
+ "factIds": ["warm-medium-import-validates-title-and-project"]
56
+ },
57
+ {
58
+ "file": "src/store/taskStore.ts",
59
+ "symbols": ["findDuplicate"],
60
+ "required": true,
61
+ "factIds": ["warm-medium-import-skips-duplicates-by-project-and-normalized-title"]
62
+ },
63
+ {
64
+ "file": "src/store/taskStore.ts",
65
+ "symbols": ["createTask"],
66
+ "required": true,
67
+ "factIds": ["warm-medium-import-keeps-deterministic-task-sequences"]
68
+ }
69
+ ],
44
70
  "minimumCorrectFacts": 3,
45
71
  "notes": "Cross-module retrieval spanning the import service, validation, and store logic."
46
72
  },
@@ -117,6 +143,44 @@
117
143
  "required": true
118
144
  }
119
145
  ],
146
+ "expectedContextTargets": [
147
+ {
148
+ "file": "src/services/createTask.ts",
149
+ "symbols": ["createTask"],
150
+ "required": true,
151
+ "factIds": ["warm-medium-create-validates-title", "warm-medium-create-validates-project-before-storing", "warm-medium-create-normalizes-tags", "warm-medium-create-starts-incomplete"]
152
+ },
153
+ {
154
+ "file": "src/validation/taskValidation.ts",
155
+ "symbols": ["validateTaskTitle"],
156
+ "required": true,
157
+ "factIds": ["warm-medium-create-validates-title"]
158
+ },
159
+ {
160
+ "file": "src/validation/taskValidation.ts",
161
+ "symbols": ["validateProjectId"],
162
+ "required": true,
163
+ "factIds": ["warm-medium-create-validates-project-before-storing"]
164
+ },
165
+ {
166
+ "file": "src/store/taskStore.ts",
167
+ "symbols": ["TaskWorkflowStore"],
168
+ "required": true,
169
+ "factIds": ["warm-medium-create-validates-project-before-storing", "warm-medium-create-uses-deterministic-sequence"]
170
+ },
171
+ {
172
+ "file": "src/validation/taskValidation.ts",
173
+ "symbols": ["normalizeTags"],
174
+ "required": true,
175
+ "factIds": ["warm-medium-create-normalizes-tags"]
176
+ },
177
+ {
178
+ "file": "src/utils/deterministicId.ts",
179
+ "symbols": ["createDeterministicId"],
180
+ "required": true,
181
+ "factIds": ["warm-medium-create-uses-deterministic-sequence"]
182
+ }
183
+ ],
120
184
  "minimumCorrectFacts": 4,
121
185
  "notes": "Cross-module: the create service composes validation, the store, and the deterministic id utility."
122
186
  },
@@ -163,6 +227,20 @@
163
227
  "required": true
164
228
  }
165
229
  ],
230
+ "expectedContextTargets": [
231
+ {
232
+ "file": "src/services/completeTask.ts",
233
+ "symbols": ["completeTask"],
234
+ "required": true,
235
+ "factIds": ["warm-medium-complete-targets-task-by-id", "warm-medium-complete-sets-completed-at", "warm-medium-complete-is-idempotent"]
236
+ },
237
+ {
238
+ "file": "src/store/taskStore.ts",
239
+ "symbols": ["TaskWorkflowStore"],
240
+ "required": true,
241
+ "factIds": ["warm-medium-complete-targets-task-by-id", "warm-medium-complete-unknown-task-throws"]
242
+ }
243
+ ],
166
244
  "minimumCorrectFacts": 3,
167
245
  "notes": "Localized: the behavior lives in one service plus the store update primitive."
168
246
  },
@@ -215,6 +293,26 @@
215
293
  "required": true
216
294
  }
217
295
  ],
296
+ "expectedContextTargets": [
297
+ {
298
+ "file": "src/services/filterTasks.ts",
299
+ "symbols": ["filterTasks"],
300
+ "required": true,
301
+ "factIds": ["warm-medium-filter-combines-active-predicates", "warm-medium-filter-project", "warm-medium-filter-completed-priority-tag", "warm-medium-filter-text-query", "warm-medium-filter-read-only-ordering"]
302
+ },
303
+ {
304
+ "file": "src/models/task.ts",
305
+ "symbols": ["TaskFilter"],
306
+ "required": true,
307
+ "factIds": ["warm-medium-filter-combines-active-predicates"]
308
+ },
309
+ {
310
+ "file": "src/store/taskStore.ts",
311
+ "symbols": ["TaskWorkflowStore"],
312
+ "required": true,
313
+ "factIds": ["warm-medium-filter-read-only-ordering"]
314
+ }
315
+ ],
218
316
  "minimumCorrectFacts": 4,
219
317
  "notes": "Cross-module: filter semantics depend on the TaskFilter model and store listing order."
220
318
  },
@@ -271,6 +369,32 @@
271
369
  "required": true
272
370
  }
273
371
  ],
372
+ "expectedContextTargets": [
373
+ {
374
+ "file": "src/services/summarizeTasks.ts",
375
+ "symbols": ["summarizeTasks"],
376
+ "required": true,
377
+ "factIds": ["warm-medium-summary-total-open-completed", "warm-medium-summary-by-project", "warm-medium-summary-high-priority-open", "warm-medium-summary-read-only"]
378
+ },
379
+ {
380
+ "file": "src/models/task.ts",
381
+ "symbols": ["TaskSummary"],
382
+ "required": true,
383
+ "factIds": ["warm-medium-summary-total-open-completed"]
384
+ },
385
+ {
386
+ "file": "src/store/taskStore.ts",
387
+ "symbols": ["TaskWorkflowStore"],
388
+ "required": true,
389
+ "factIds": ["warm-medium-summary-by-project", "warm-medium-summary-read-only"]
390
+ },
391
+ {
392
+ "file": "src/models/project.ts",
393
+ "symbols": ["WorkflowProject"],
394
+ "required": true,
395
+ "factIds": ["warm-medium-summary-by-project"]
396
+ }
397
+ ],
274
398
  "minimumCorrectFacts": 3,
275
399
  "notes": "Cross-module: the summary combines the store with task and project models."
276
400
  },
@@ -356,6 +480,50 @@
356
480
  }
357
481
  ],
358
482
  "forbiddenWrongClaims": ["importTasks calls the createTask service to insert imported tasks."],
483
+ "expectedContextTargets": [
484
+ {
485
+ "file": "src/services/createTask.ts",
486
+ "symbols": ["createTask"],
487
+ "required": true,
488
+ "factIds": ["warm-medium-broad-shared-storage"]
489
+ },
490
+ {
491
+ "file": "src/services/importTasks.ts",
492
+ "symbols": ["importTasks"],
493
+ "required": true,
494
+ "factIds": ["warm-medium-broad-shared-storage", "warm-medium-broad-import-adds-dedupe"]
495
+ },
496
+ {
497
+ "file": "src/store/taskStore.ts",
498
+ "symbols": ["TaskWorkflowStore"],
499
+ "required": true,
500
+ "factIds": ["warm-medium-broad-shared-storage", "warm-medium-broad-import-adds-dedupe", "warm-medium-broad-filter-read-only", "warm-medium-broad-complete-targeted", "warm-medium-broad-summary-aggregates"]
501
+ },
502
+ {
503
+ "file": "src/validation/taskValidation.ts",
504
+ "symbols": ["validateImportInput"],
505
+ "required": true,
506
+ "factIds": ["warm-medium-broad-import-adds-dedupe"]
507
+ },
508
+ {
509
+ "file": "src/services/filterTasks.ts",
510
+ "symbols": ["filterTasks"],
511
+ "required": true,
512
+ "factIds": ["warm-medium-broad-filter-read-only"]
513
+ },
514
+ {
515
+ "file": "src/services/completeTask.ts",
516
+ "symbols": ["completeTask"],
517
+ "required": true,
518
+ "factIds": ["warm-medium-broad-complete-targeted"]
519
+ },
520
+ {
521
+ "file": "src/services/summarizeTasks.ts",
522
+ "symbols": ["summarizeTasks"],
523
+ "required": true,
524
+ "factIds": ["warm-medium-broad-summary-aggregates"]
525
+ }
526
+ ],
359
527
  "minimumCorrectFacts": 4,
360
528
  "notes": "Deliberately wide-scope negative control spanning every workflow service; it is not expected to fit a small localized context."
361
529
  },
@@ -426,6 +594,26 @@
426
594
  "required": true
427
595
  }
428
596
  ],
597
+ "expectedContextTargets": [
598
+ {
599
+ "file": "ts/src/services/buildAnalyticsSnapshot.ts",
600
+ "symbols": ["buildAnalyticsSnapshot"],
601
+ "required": true,
602
+ "factIds": ["warm-large-snapshot-computes-completion-rate", "warm-large-snapshot-counts-stale-open-tasks"]
603
+ },
604
+ {
605
+ "file": "py/task_analytics/quality.py",
606
+ "symbols": ["determine_quality_label"],
607
+ "required": true,
608
+ "factIds": ["warm-large-python-quality-labels-healthy-watch-risk", "warm-large-python-reporting-renders-quality-lines"]
609
+ },
610
+ {
611
+ "file": "py/task_analytics/reporting.py",
612
+ "symbols": ["build_health_report"],
613
+ "required": true,
614
+ "factIds": ["warm-large-python-reporting-renders-quality-lines"]
615
+ }
616
+ ],
429
617
  "minimumCorrectFacts": 3,
430
618
  "notes": "Cross-module retrieval spanning TypeScript snapshot building and Python quality reporting."
431
619
  },
@@ -488,6 +676,32 @@
488
676
  "required": true
489
677
  }
490
678
  ],
679
+ "expectedContextTargets": [
680
+ {
681
+ "file": "ts/src/services/buildAnalyticsSnapshot.ts",
682
+ "symbols": ["buildAnalyticsSnapshot"],
683
+ "required": true,
684
+ "factIds": ["warm-large-snapshot-per-project-counts", "warm-large-snapshot-completion-rate-formula", "warm-large-snapshot-stale-condition", "warm-large-snapshot-empty-project", "warm-large-snapshot-totals-aggregate"]
685
+ },
686
+ {
687
+ "file": "ts/src/services/listTasksByProject.ts",
688
+ "symbols": ["listTasksByProject"],
689
+ "required": true,
690
+ "factIds": ["warm-large-snapshot-per-project-counts"]
691
+ },
692
+ {
693
+ "file": "ts/src/store/taskStore.ts",
694
+ "symbols": ["AnalyticsTaskStore"],
695
+ "required": true,
696
+ "factIds": ["warm-large-snapshot-per-project-counts"]
697
+ },
698
+ {
699
+ "file": "ts/src/models/analyticsSnapshot.ts",
700
+ "symbols": ["ProjectSnapshot"],
701
+ "required": true,
702
+ "factIds": ["warm-large-snapshot-per-project-counts", "warm-large-snapshot-empty-project", "warm-large-snapshot-totals-aggregate"]
703
+ }
704
+ ],
491
705
  "minimumCorrectFacts": 4,
492
706
  "notes": "Cross-module: the snapshot service composes the task-listing service, the task store, and the snapshot model."
493
707
  },
@@ -534,6 +748,14 @@
534
748
  "required": true
535
749
  }
536
750
  ],
751
+ "expectedContextTargets": [
752
+ {
753
+ "file": "ts/src/reporting/buildProjectLeaderboard.ts",
754
+ "symbols": ["buildProjectLeaderboard"],
755
+ "required": true,
756
+ "factIds": ["warm-large-leaderboard-completion-rate-descending", "warm-large-leaderboard-stale-ascending", "warm-large-leaderboard-project-id-final", "warm-large-leaderboard-one-based-ranks"]
757
+ }
758
+ ],
537
759
  "minimumCorrectFacts": 3,
538
760
  "notes": "Localized: the ranking rule lives in one reporting function over the ProjectSnapshot model."
539
761
  },
@@ -586,6 +808,32 @@
586
808
  "required": true
587
809
  }
588
810
  ],
811
+ "expectedContextTargets": [
812
+ {
813
+ "file": "py/task_analytics/parser.py",
814
+ "symbols": ["parse_task_rows"],
815
+ "required": true,
816
+ "factIds": ["warm-large-python-parser-task-record"]
817
+ },
818
+ {
819
+ "file": "py/task_analytics/models.py",
820
+ "symbols": ["TaskRecord"],
821
+ "required": true,
822
+ "factIds": ["warm-large-python-parser-task-record"]
823
+ },
824
+ {
825
+ "file": "py/task_analytics/metrics.py",
826
+ "symbols": ["calculate_project_metrics"],
827
+ "required": true,
828
+ "factIds": ["warm-large-python-metrics-grouped-by-project", "warm-large-python-metrics-counts", "warm-large-python-metrics-completion-rate", "warm-large-python-metrics-average-story-points"]
829
+ },
830
+ {
831
+ "file": "py/task_analytics/models.py",
832
+ "symbols": ["ProjectMetrics"],
833
+ "required": true,
834
+ "factIds": ["warm-large-python-metrics-grouped-by-project"]
835
+ }
836
+ ],
589
837
  "minimumCorrectFacts": 4,
590
838
  "notes": "Cross-module: parsing, the record models, and metric calculation live in separate Python modules."
591
839
  },
@@ -662,6 +910,38 @@
662
910
  "required": true
663
911
  }
664
912
  ],
913
+ "expectedContextTargets": [
914
+ {
915
+ "file": "py/task_analytics/pipeline.py",
916
+ "symbols": ["build_report_from_rows"],
917
+ "required": true,
918
+ "factIds": ["warm-large-pipeline-parses-first", "warm-large-pipeline-metrics-before-report", "warm-large-pipeline-composes-owners"]
919
+ },
920
+ {
921
+ "file": "py/task_analytics/parser.py",
922
+ "symbols": ["parse_task_rows"],
923
+ "required": true,
924
+ "factIds": ["warm-large-pipeline-parses-first", "warm-large-pipeline-composes-owners"]
925
+ },
926
+ {
927
+ "file": "py/task_analytics/metrics.py",
928
+ "symbols": ["calculate_project_metrics"],
929
+ "required": true,
930
+ "factIds": ["warm-large-pipeline-metrics-before-report", "warm-large-pipeline-composes-owners"]
931
+ },
932
+ {
933
+ "file": "py/task_analytics/reporting.py",
934
+ "symbols": ["build_health_report"],
935
+ "required": true,
936
+ "factIds": ["warm-large-pipeline-metrics-before-report", "warm-large-pipeline-quality-label-in-report", "warm-large-pipeline-deterministic-output", "warm-large-pipeline-composes-owners"]
937
+ },
938
+ {
939
+ "file": "py/task_analytics/quality.py",
940
+ "symbols": ["determine_quality_label"],
941
+ "required": true,
942
+ "factIds": ["warm-large-pipeline-quality-label-in-report"]
943
+ }
944
+ ],
665
945
  "minimumCorrectFacts": 4,
666
946
  "notes": "Cross-module: the pipeline composes parser, metrics, reporting, and (through reporting) quality modules."
667
947
  },
@@ -755,6 +1035,56 @@
755
1035
  "Python is a runtime backend for the TypeScript analytics implementation.",
756
1036
  "The TypeScript or Python implementation directly imports or calls the other."
757
1037
  ],
1038
+ "expectedContextTargets": [
1039
+ {
1040
+ "file": "ts/src/services/buildAnalyticsSnapshot.ts",
1041
+ "symbols": ["buildAnalyticsSnapshot"],
1042
+ "required": true,
1043
+ "factIds": ["warm-large-broad-typescript-side", "warm-large-broad-comparable-evidence", "warm-large-broad-independent-implementations", "warm-large-broad-no-cross-invocation"]
1044
+ },
1045
+ {
1046
+ "file": "ts/src/reporting/formatTaskHealthReport.ts",
1047
+ "symbols": ["formatTaskHealthReport"],
1048
+ "required": true,
1049
+ "factIds": ["warm-large-broad-typescript-side", "warm-large-broad-no-cross-invocation"]
1050
+ },
1051
+ {
1052
+ "file": "ts/src/reporting/buildProjectLeaderboard.ts",
1053
+ "symbols": ["buildProjectLeaderboard"],
1054
+ "required": true,
1055
+ "factIds": ["warm-large-broad-typescript-side", "warm-large-broad-no-cross-invocation"]
1056
+ },
1057
+ {
1058
+ "file": "py/task_analytics/parser.py",
1059
+ "symbols": ["parse_task_rows"],
1060
+ "required": true,
1061
+ "factIds": ["warm-large-broad-python-side", "warm-large-broad-no-cross-invocation"]
1062
+ },
1063
+ {
1064
+ "file": "py/task_analytics/metrics.py",
1065
+ "symbols": ["calculate_project_metrics"],
1066
+ "required": true,
1067
+ "factIds": ["warm-large-broad-python-side", "warm-large-broad-comparable-evidence", "warm-large-broad-no-cross-invocation"]
1068
+ },
1069
+ {
1070
+ "file": "py/task_analytics/quality.py",
1071
+ "symbols": ["determine_quality_label"],
1072
+ "required": true,
1073
+ "factIds": ["warm-large-broad-python-side", "warm-large-broad-no-cross-invocation"]
1074
+ },
1075
+ {
1076
+ "file": "py/task_analytics/reporting.py",
1077
+ "symbols": ["build_health_report"],
1078
+ "required": true,
1079
+ "factIds": ["warm-large-broad-python-side", "warm-large-broad-no-cross-invocation"]
1080
+ },
1081
+ {
1082
+ "file": "py/task_analytics/pipeline.py",
1083
+ "symbols": ["build_report_from_rows"],
1084
+ "required": true,
1085
+ "factIds": ["warm-large-broad-python-side", "warm-large-broad-independent-implementations", "warm-large-broad-no-cross-invocation"]
1086
+ }
1087
+ ],
758
1088
  "minimumCorrectFacts": 4,
759
1089
  "notes": "Deliberately wide-scope negative control spanning both language implementations; it is not expected to fit a small localized context."
760
1090
  },
@@ -166,17 +166,40 @@ export function renderExperimentRunHelp() {
166
166
  " --context-budgets <values> Comma-separated estimated-context-token budgets: 8k, 16k, 32k,",
167
167
  " 64k (8192/16384/32768/65536), or positive integers such as",
168
168
  " 12000 (default: 8k,16k,32k,64k). Duplicates after",
169
- " normalization are rejected. Only --out, --case,",
170
- " --synthetic-config, --context-budgets, and --kit-command are",
171
- " accepted; --case selects from the bundled four-case catalog.",
172
- " Self target only.",
169
+ " normalization are rejected. Only --out, --target, --case,",
170
+ " --synthetic-config, --local-subject-config, --context-budgets,",
171
+ " and --kit-command are accepted; --case selects from the bundled",
172
+ " four-case catalog. Bundled and synthetic modes run against the",
173
+ " Lab itself (--target is rejected there); an external --target",
174
+ " requires --local-subject-config.",
173
175
  " --synthetic-config <path> Path to a SyntheticRepositoryConfigV1 JSON file; relative paths",
174
176
  " resolve against the invocation directory. Generated",
175
177
  " repositories are written beneath the selected experiment",
176
178
  " output directory (synthetic-repositories/). Mutually exclusive",
177
179
  " with --case. Without it, the bundled four-case catalog is used.",
180
+ " --local-subject-config <path> Path to a LocalRepositorySubjectConfigV1 JSON file; applies to",
181
+ " context-window-scaling with an explicit external --target (a",
182
+ " local Git worktree root). Relative paths resolve against the",
183
+ " invocation directory. The repository is never modified; the",
184
+ " output directory must be outside it. Durable output omits the",
185
+ " repository path, source text, and file names, and adds",
186
+ " local-repository-subject-manifest.json. Mutually exclusive with",
187
+ " --case and --synthetic-config. Measures operational context fit",
188
+ " only, not retrieval precision, recall, or ranking quality.",
178
189
  " Generate plots with \"plots generate --experiment <run dir>\".",
179
190
  "",
191
+ "retrieval-precision-recall only:",
192
+ " Bundled mode (default) runs the frozen 12-case corpus and accepts",
193
+ " only --out, --case, --benchmark-project and --kit-command.",
194
+ " External-local mode requires an explicit --target together with",
195
+ " --local-subject-config and accepts only --out, --target,",
196
+ " --local-subject-config and --kit-command; --case and",
197
+ " --benchmark-project are rejected because the local-subject config",
198
+ " owns the case set. Each configured case needs a complete answer",
199
+ " key with explicit factIds mappings. One private index is built per",
200
+ " case; the repository is never modified and durable output omits its",
201
+ " path, source text, and file, symbol and fact identities.",
202
+ "",
180
203
  "warm-index-reuse only:",
181
204
  " Legacy/default mode uses the deterministic fake agent only;",
182
205
  " agent options below are not accepted by this plugin.",
@@ -130,6 +130,12 @@ function describePurpose(plugin) {
130
130
  }
131
131
  function describeTargetBehavior(plugin) {
132
132
  const supportsExternal = plugin.metadata.supportedTargets.includes("external-local");
133
+ if (plugin.metadata.id === "context-window-scaling") {
134
+ return "Three subject modes. Bundled (default): the bundled fixed scaling corpus against the Lab itself. Synthetic: caller-supplied deterministic synthetic repositories via --synthetic-config <path> (a SyntheticRepositoryConfigV1 JSON file, mutually exclusive with --case) written beneath the experiment output directory. External local repository: an explicitly selected local Git worktree via --target <path> together with --local-subject-config <path> (a LocalRepositorySubjectConfigV1 JSON file); the repository is never modified, the output directory must be outside it, and durable output omits the repository path, source text, and file names. Operational context-fit measurement only; no retrieval precision, recall, or ranking quality is measured.";
135
+ }
136
+ if (plugin.metadata.id === "retrieval-precision-recall") {
137
+ return "Two subject modes. Bundled (default): the frozen bundled 12-case warm-index corpus against the Lab itself, filterable with --case and --benchmark-project. External local repository: an explicitly selected local Git worktree via --target <path> together with --local-subject-config <path> (a LocalRepositorySubjectConfigV1 JSON file whose cases carry a complete retrieval answer key with explicit fact-to-context mappings); the repository is never modified, the output directory must be outside it, one private index is built per configured case, and durable output withholds the repository path, source text, and file, symbol and fact identities. Bundled filters are not accepted in external mode.";
138
+ }
133
139
  if (supportsExternal) {
134
140
  return "Runs against the current lab repository when --target is omitted, or against an explicit local target project when --target <path> is provided. Outputs stay under lab-controlled output directories by default.";
135
141
  }
@@ -153,15 +159,20 @@ function describeExamples(plugin) {
153
159
  `my-dev-kit-lab experiment run --experiment ${plugin.metadata.id}${agentOptions}`
154
160
  ];
155
161
  // Only advertise an explicit --target example for plugins that support external targets.
156
- if (plugin.metadata.supportedTargets.includes("external-local")) {
162
+ if (plugin.metadata.supportedTargets.includes("external-local") &&
163
+ plugin.metadata.id !== "context-window-scaling" &&
164
+ plugin.metadata.id !== "retrieval-precision-recall") {
157
165
  examples.push(`my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --target "Z:\\Users\\newuser\\Projects\\my-dev-kit-v1"${agentOptions}${screenshotOption}`);
158
166
  }
159
167
  // Only advertise campaign examples for plugins that declare the campaignPreset config field.
160
168
  if (hasConfigField(plugin, "campaignPreset")) {
161
169
  examples.push(`my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --campaign codex-full --include-real-agents --out <dir>`, `my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --campaign claude-full --include-real-agents --case warm-medium-complete-idempotent --out <dir>`);
162
170
  }
171
+ if (plugin.metadata.id === "retrieval-precision-recall") {
172
+ examples.push(`my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --case <case-id> --out <run-dir>`, `my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --target <local-git-repository> --local-subject-config <path-to-local-subject-config.json> --out <run-dir-outside-the-repository>`);
173
+ }
163
174
  if (plugin.metadata.id === "context-window-scaling") {
164
- examples.push(`my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --synthetic-config <path-to-config.json> --out <run-dir>`);
175
+ examples.push(`my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --synthetic-config <path-to-config.json> --out <run-dir>`, `my-dev-kit-lab experiment run --experiment ${plugin.metadata.id} --target <local-git-repository> --local-subject-config <path-to-local-subject-config.json> --out <run-dir-outside-the-repository>`);
165
176
  }
166
177
  return examples;
167
178
  }