@dailephd/my-dev-kit-lab 0.6.1 → 0.6.3
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.
- package/CHANGELOG.md +32 -0
- package/README.md +9 -7
- package/benchmarks/contracts/incremental-change-staleness-scenarios.json +360 -0
- package/dist/src/cli/help.js +16 -9
- package/dist/src/commands/runExperimentDescribeCommand.js +5 -2
- package/dist/src/commands/runExperimentRunCommand.js +4 -7
- package/dist/src/evaluation/affectedNeighborhoodMetrics.js +51 -0
- package/dist/src/evaluation/benchmarkMetadata.js +5 -1
- package/dist/src/evaluation/parseAgentAnswer.js +172 -24
- package/dist/src/evaluation/runMyDevKitRetrieval.js +120 -7
- package/dist/src/experiments/defaultRegistry.js +2 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/comparison.js +101 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/comparisonV2.js +49 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/config.js +67 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/disposableTarget.js +125 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/execution.js +430 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionArtifact.js +160 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionArtifactV2.js +289 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionV2.js +195 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/index.js +13 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/indexClone.js +76 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecycle.js +308 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecyclePolicy.js +154 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecyclePolicyV2.js +78 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecycleV2.js +298 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/mutationExecution.js +144 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/plugin.js +475 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/scenarioCatalog.js +42 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/scenarioMutation.js +116 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/scenarioSelection.js +79 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/scenarioTypes.js +37 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/scenarioValidation.js +168 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/sourceState.js +145 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/treatmentSession.js +6 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/treatmentSessionV2.js +5 -0
- package/dist/src/experiments/plugins/index.js +1 -0
- package/dist/src/experiments/plugins/warmIndexReuse/metrics.js +17 -20
- package/dist/src/experiments/plugins/warmIndexReuse/warmIndexSession.js +3 -1
- package/dist/src/mobile/android/advancedSecurity/candidateEvidence.js +9 -2
- package/dist/src/mobile/android/advancedSecurity/redaction.js +19 -10
- package/dist/src/mobile/android/advancedSecurity/secretCandidates/analyzeSecretCandidates.js +12 -2
- package/dist/src/mobile/android/advancedSecurity/signingConfiguration/analyzeSigningConfiguration.js +1 -1
- package/dist/src/mobile/android/advancedSecurity/signingConfiguration/extractSigningConfigurations.js +7 -7
- package/dist/src/report/experiments/buildIncrementalChangeStalenessPluginReport.js +33 -0
- package/dist/src/report/experiments/buildIncrementalChangeStalenessReport.js +112 -0
- package/dist/src/report/experiments/buildIncrementalChangeStalenessReportV2.js +80 -0
- package/dist/src/report/experiments/buildPluginExperimentReport.js +3 -0
- package/dist/src/report/experiments/incrementalChangeStalenessReportModel.js +4 -0
- package/dist/src/report/experiments/incrementalChangeStalenessReportModelV2.js +3 -0
- package/dist/src/report/experiments/incrementalChangeStalenessReportRowsV2.js +146 -0
- package/dist/src/report/experiments/index.js +6 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessHtml.js +243 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessHtmlV2.js +111 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessTextV2.js +96 -0
- package/dist/src/report/experiments/renderPluginExperimentReportHtml.js +3 -0
- package/dist/src/report/experiments/renderPluginExperimentReportText.js +144 -0
- package/dist/src/securityValidation/staticScans/codeql.js +8 -8
- package/docs/METRICS.md +67 -1
- package/examples/tutorial-browser/prepare.mjs +13 -13
- package/examples/tutorial-browser/server.mjs +13 -13
- package/package.json +1 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { runSecurityCommand } from "../commandRunner.js";
|
|
2
2
|
import { resolveCommand } from "../../core/resolveCommand.js";
|
|
3
3
|
import { skippedCheck } from "../cliAdversarial/runAdversarialCheck.js";
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// This local check only verifies CodeQL CLI availability and integration.
|
|
5
|
+
// Full CodeQL analysis is owned by .github/workflows/codeql.yml.
|
|
6
|
+
// Release readiness requires successful GitHub analysis for the exact candidate SHA.
|
|
7
7
|
export async function runCodeqlCheck(options) {
|
|
8
8
|
const { cwd, timeoutMs } = options;
|
|
9
9
|
const resolved = resolveCommand("codeql", { cwd, env: process.env });
|
|
10
10
|
if (resolved.resolutionKind === "unavailable") {
|
|
11
11
|
return skippedCheck({
|
|
12
12
|
id: "codeql-scan",
|
|
13
|
-
name: "CodeQL
|
|
13
|
+
name: "CodeQL CLI availability preflight",
|
|
14
14
|
category: "static-scan",
|
|
15
|
-
reason: "CodeQL CLI
|
|
15
|
+
reason: "Local CodeQL CLI is unavailable, so the local availability preflight is skipped. Full release-readiness coverage requires a successful GitHub CodeQL advanced-setup analysis for the exact candidate SHA.",
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
const startedAt = new Date().toISOString();
|
|
@@ -29,7 +29,7 @@ export async function runCodeqlCheck(options) {
|
|
|
29
29
|
if (versionCmd.exitCode !== 0 || versionCmd.exitCode === null) {
|
|
30
30
|
return {
|
|
31
31
|
id: "codeql-scan",
|
|
32
|
-
name: "CodeQL
|
|
32
|
+
name: "CodeQL CLI availability preflight",
|
|
33
33
|
category: "static-scan",
|
|
34
34
|
status: "failed",
|
|
35
35
|
severity: "major",
|
|
@@ -50,10 +50,10 @@ export async function runCodeqlCheck(options) {
|
|
|
50
50
|
command: "codeql version --format terse",
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
// CLI is present and functional
|
|
53
|
+
// The CLI is present and functional; this is not repository-wide analysis.
|
|
54
54
|
return {
|
|
55
55
|
id: "codeql-scan",
|
|
56
|
-
name: "CodeQL
|
|
56
|
+
name: "CodeQL CLI availability preflight",
|
|
57
57
|
category: "static-scan",
|
|
58
58
|
status: "passed",
|
|
59
59
|
severity: "informational",
|
package/docs/METRICS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Metrics
|
|
2
2
|
|
|
3
|
-
This document is the canonical metric glossary for my-dev-kit-lab. It defines every metric that appears in benchmark profiles, prompt variants, controlled experiment artifacts, and rendered reports.
|
|
3
|
+
This document is the canonical metric glossary for my-dev-kit-lab. It defines every metric that appears in benchmark profiles, prompt variants, controlled experiment artifacts, and rendered reports across the registered experiment plugins (`context-strategy-comparison`, `warm-index-reuse`, and `incremental-change-staleness`).
|
|
4
4
|
|
|
5
5
|
Related documentation:
|
|
6
6
|
- [ARCHITECTURE.md](ARCHITECTURE.md) — how metrics flow through the pipeline
|
|
@@ -595,3 +595,69 @@ All six metrics are warm-side only (they are not on the raw-full-file side, beca
|
|
|
595
595
|
**Report presentation.** `report.warmIndexReuse.affectedNeighborhoodSummary` holds presentation counts (assessed and unassessed tasks; complete, partial, and unavailable assessments; related, unrelated, and unknown relationships; recommended, not-indicated, and unknown recommendations). They are counts, not metric formulas. Each task's `affectedNeighborhood` block shows the statuses, the six metric objects, the relationship, the recommendation with a fixed explanation, and bounded lists (at most 20 affected node IDs, 20 edge IDs, 10 unresolved and 10 ambiguous task mappings, and 10 warnings, each with its total and omitted count). The full identity arrays stay in `warm-index-execution.json`.
|
|
596
596
|
|
|
597
597
|
**Observational only.** The evidence never triggers reindexing, suppresses or alters warm retrieval, or changes execution, provider, agent, correctness, or token-evidence status. It uses only the baseline graph of the prepared index: there is no graph-diff, refreshed-index, or stale-versus-refreshed comparison.
|
|
598
|
+
|
|
599
|
+
## Incremental-change and staleness evidence (v0.6.2)
|
|
600
|
+
|
|
601
|
+
The `incremental-change-staleness` plugin reuses the six existing v0.6.1 affected-neighborhood numeric metrics unchanged (`changedFileCount`, `changedSymbolCount`, `affectedNodeCount`, `affectedEdgeCount`, `taskOverlapCount`, `taskOverlapPercent`; see "Affected-neighborhood metrics (v0.6.1)" above) and adds no new numeric formula.
|
|
602
|
+
|
|
603
|
+
**Correctness relation** (per scenario, comparing the `stale-index` and `full-refresh` treatments' deterministic fake-agent correctness):
|
|
604
|
+
|
|
605
|
+
- `stale-worse`: `stale-index` correctness is lower than `full-refresh` correctness.
|
|
606
|
+
- `same`: both treatments have available, equal correctness.
|
|
607
|
+
- `stale-better`: `stale-index` correctness is higher than `full-refresh` correctness.
|
|
608
|
+
- `unknown`: either treatment's correctness is unavailable.
|
|
609
|
+
|
|
610
|
+
**Required-file status** (per treatment, an answer-key file-presence check against that treatment's actual retrieved-files evidence — not retrieval precision, recall, F1, MRR, NDCG, or symbol recall):
|
|
611
|
+
|
|
612
|
+
- `present`: every required file was observed.
|
|
613
|
+
- `missing`: at least one required file was not observed, and the observed-files evidence was complete.
|
|
614
|
+
- `unknown`: the actual-files-read evidence was not complete enough to establish presence or absence.
|
|
615
|
+
|
|
616
|
+
**Required-file relation** (per scenario, comparing the two treatments' required-file status):
|
|
617
|
+
|
|
618
|
+
- `stale-worse`: `stale-index` is `missing` while `full-refresh` is `present`.
|
|
619
|
+
- `same`: both treatments have the same status (including `missing`/`missing`).
|
|
620
|
+
- `stale-better`: `stale-index` is `present` while `full-refresh` is `missing`.
|
|
621
|
+
- `unknown`: either treatment's status is `unknown`.
|
|
622
|
+
|
|
623
|
+
**Stale-risk classification** (per scenario, the frozen precedence over the two relations above):
|
|
624
|
+
|
|
625
|
+
1. `observed-stale-regression` — the correctness relation or the required-file relation is `stale-worse`.
|
|
626
|
+
2. `inconclusive` — otherwise, if the correctness relation or the required-file relation is `unknown`.
|
|
627
|
+
3. `no-observed-stale-regression` — otherwise.
|
|
628
|
+
|
|
629
|
+
`staleRiskClassification` is not a numeric risk score, not a winner, not a ranking, and not an automatic reindex decision. `no-observed-stale-regression` means only that this matched scenario did not observe a stale-specific regression under these two frozen evidence dimensions; it does not establish that stale indexes are generally safe. `reindexRecommendation` (the released v0.6.1 categorical evidence) remains separate observational evidence about the affected-neighborhood analysis; it does not select or trigger either treatment and is not an input to the stale-risk classification above.
|
|
630
|
+
|
|
631
|
+
**Report presentation.** `report.incrementalChangeStaleness` holds `scenarioCount`, `readyScenarioCount`, `failedScenarioCount`, `observedStaleRegressionCount`, `noObservedStaleRegressionCount`, `inconclusiveCount`, per-scenario evidence (lifecycle, both treatments in order, and the comparison), and fixed limitations text. There is no overall score, grade, winner, best-treatment, or safe-to-skip-reindex field anywhere in the report or the persisted execution artifact.
|
|
632
|
+
|
|
633
|
+
### Partial-refresh treatment evidence (v0.6.3, current release)
|
|
634
|
+
|
|
635
|
+
The `incremental-change-staleness` plugin now compares four treatments (`stale-index`, `changed-files-refresh`, `affected-neighborhood-refresh`, `full-refresh`). It defines no new formula. Two evidence families must not be merged:
|
|
636
|
+
|
|
637
|
+
- **Lab task-relationship affected-neighborhood evidence** (released v0.6.1, unchanged): the six numeric metrics `changedFileCount`, `changedSymbolCount`, `affectedNodeCount`, `affectedEdgeCount`, `taskOverlapCount`, `taskOverlapPercent`, plus the categorical `relationship` and `reindexRecommendation`. They describe the baseline graph neighborhood of the controlled change relative to the task. `changedSymbolCount` still means baseline symbol identities belonging to confirmed changed indexed files, not proof that any symbol body changed, and `reindexRecommendation` stays observational: it selects and executes no treatment.
|
|
638
|
+
- **Upstream refresh execution evidence** (new): what my-dev-kit actually did during a partial refresh invocation. It does not depend on the task and is not a task-relevance measure.
|
|
639
|
+
|
|
640
|
+
**Numeric upstream-refresh metrics** (unit `count`; emitted as `ExperimentMetric` entries on the outcome of an incremental treatment, `changed-files-refresh` or `affected-neighborhood-refresh`, and never on `stale-index` or `full-refresh`):
|
|
641
|
+
|
|
642
|
+
| Metric ID | Meaning |
|
|
643
|
+
|---|---|
|
|
644
|
+
| `upstream-refresh-fresh-extraction-file-count` | Files upstream freshly re-extracted during the refresh invocation. |
|
|
645
|
+
| `upstream-refresh-reused-file-count` | Files upstream reused from the previous index. |
|
|
646
|
+
| `upstream-refresh-forced-neighbor-reanalysis-file-count` | Neighboring files upstream forced to re-analyze during the refresh. |
|
|
647
|
+
| `upstream-refresh-seed-file-count` | Seed files upstream selected for the affected-neighborhood refresh. |
|
|
648
|
+
| `upstream-refresh-seed-symbol-count` | Seed symbols upstream selected. |
|
|
649
|
+
| `upstream-refresh-affected-node-count` | Graph nodes upstream treated as affected. |
|
|
650
|
+
| `upstream-refresh-affected-edge-count` | Graph edges upstream treated as affected. |
|
|
651
|
+
|
|
652
|
+
Availability: the first three are always present for a validated incremental treatment. The seed, node, and edge counts appear only when upstream supplied a non-null value; a `null` upstream value is unavailable evidence and the metric is omitted, never emitted as zero. These counts describe upstream execution only: they do not prove a treatment is better, faster, safer, or more accurate, and they are distinct from the Lab `affectedNodeCount`/`affectedEdgeCount` above (different metric IDs).
|
|
653
|
+
|
|
654
|
+
**Categorical refresh evidence** (not numeric metrics, never converted to numbers): `requestedScope` (`changed-files` or `affected-neighborhood`), `appliedScope` (the scope upstream actually applied: `changed-files`, `affected-neighborhood`, `full`, or `none`), `selectionStatus` (`applied`, `fallback-full`, or `not-needed`), `fallbackReason` (an upstream reason or `null`), `forcedNeighborSample` (a bounded sample of path strings, capped by upstream, so its length can be less than the forced-neighbor count), and the Lab `refreshRealization` (`NO_REFRESH`, `APPLIED_PARTIAL`, `FALLBACK_FULL`, `FULL_REFRESH`). Only `changed-files-refresh` and `affected-neighborhood-refresh` can be `APPLIED_PARTIAL` or `FALLBACK_FULL`.
|
|
655
|
+
|
|
656
|
+
**Reference comparisons** (exactly three per ready scenario, each against `full-refresh`):
|
|
657
|
+
|
|
658
|
+
- `stale-index` vs `full-refresh` uses the v0.6.2 stale-risk vocabulary and precedence unchanged (`observed-stale-regression`, `no-observed-stale-regression`, `inconclusive`).
|
|
659
|
+
- `changed-files-refresh` vs `full-refresh` and `affected-neighborhood-refresh` vs `full-refresh` use neutral candidate relations (`candidate-worse`, `same`, `candidate-better`, `unknown`) for deterministic fake-agent correctness and for the required-file status, with the frozen precedence: (1) `not-comparable-as-partial-refresh` if the candidate fell back to a full rebuild (`FALLBACK_FULL`); (2) `observed-regression-relative-to-full` if correctness or required-file presence is `candidate-worse`; (3) `inconclusive` if either relation is `unknown`; (4) otherwise `no-observed-regression-relative-to-full`.
|
|
660
|
+
|
|
661
|
+
`no-observed-regression-relative-to-full` means only that the executed scenario showed no regression under those two evidence dimensions. It does not establish equivalence or safety and does not show that full refresh is unnecessary. `not-comparable-as-partial-refresh` says the run gives no evidence about the requested partial behavior. There is no winner, ranking, composite score, safety score, safe-to-skip-refresh flag, or stale-risk percentage. Ordinary per-treatment correctness `score` remains the existing deterministic fake-agent evidence.
|
|
662
|
+
|
|
663
|
+
**Report presentation.** `report.incrementalChangeStaleness` (schema `my-dev-kit-lab-incremental-change-staleness-report-v2`) holds the summary counts (including per-treatment applied-partial, fallback, and classification counts), per-scenario lifecycle, four treatments and three comparisons identified by explicit treatment IDs, and fixed limitations text. Unavailable evidence is written as `unavailable` or `not applicable`, never zero. Historical V1 reports keep their original two-treatment presentation.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
|
|
5
|
-
const sourceRoot = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
const targetRoot = process.argv[2];
|
|
7
|
-
if (!targetRoot) {
|
|
8
|
-
console.error("prepare requires a target root argument");
|
|
9
|
-
process.exit(2);
|
|
10
|
-
}
|
|
11
|
-
fs.mkdirSync(path.join(targetRoot, "app"), { recursive: true });
|
|
12
|
-
fs.mkdirSync(path.join(targetRoot, "out"), { recursive: true });
|
|
13
|
-
for (const file of ["index.html", "server.mjs"]) fs.copyFileSync(path.join(sourceRoot, file), path.join(targetRoot, "app", file));
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const sourceRoot = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const targetRoot = process.argv[2];
|
|
7
|
+
if (!targetRoot) {
|
|
8
|
+
console.error("prepare requires a target root argument");
|
|
9
|
+
process.exit(2);
|
|
10
|
+
}
|
|
11
|
+
fs.mkdirSync(path.join(targetRoot, "app"), { recursive: true });
|
|
12
|
+
fs.mkdirSync(path.join(targetRoot, "out"), { recursive: true });
|
|
13
|
+
for (const file of ["index.html", "server.mjs"]) fs.copyFileSync(path.join(sourceRoot, file), path.join(targetRoot, "app", file));
|
|
14
14
|
fs.writeFileSync(path.join(targetRoot, "out", "report.json"), JSON.stringify({ prepared: true, counts: { widgets: 3 } }, null, 2), "utf8");
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
const root = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const port = Number(process.env.TUTORIAL_FIXTURE_PORT || 0);
|
|
8
|
-
const server = http.createServer((req, res) => {
|
|
9
|
-
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
10
|
-
if (url.pathname === "/api/status") { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ ok: true, widgets: 3 })); return; }
|
|
11
|
-
const filePath = url.pathname === "/" ? path.join(root, "index.html") : path.join(root, url.pathname);
|
|
12
|
-
fs.readFile(filePath, (error, contents) => { if (error) { res.writeHead(404); res.end("not found"); return; } res.writeHead(200, { "content-type": filePath.endsWith(".html") ? "text/html" : "application/octet-stream" }); res.end(contents); });
|
|
13
|
-
});
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
const root = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const port = Number(process.env.TUTORIAL_FIXTURE_PORT || 0);
|
|
8
|
+
const server = http.createServer((req, res) => {
|
|
9
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
10
|
+
if (url.pathname === "/api/status") { res.writeHead(200, { "content-type": "application/json" }); res.end(JSON.stringify({ ok: true, widgets: 3 })); return; }
|
|
11
|
+
const filePath = url.pathname === "/" ? path.join(root, "index.html") : path.join(root, url.pathname);
|
|
12
|
+
fs.readFile(filePath, (error, contents) => { if (error) { res.writeHead(404); res.end("not found"); return; } res.writeHead(200, { "content-type": filePath.endsWith(".html") ? "text/html" : "application/octet-stream" }); res.end(contents); });
|
|
13
|
+
});
|
|
14
14
|
server.listen(port, "127.0.0.1", () => console.log("tutorial fixture listening on " + server.address().port));
|