Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -958,4 +958,7 @@ This file is append-only. Never rewrite or delete an existing review record; app
| 2026-07-25 | execute-audit-code-remediation (PR #1162) | f07c711a0e1ee853b128733a51db182d8192c3c4 | CI unblock after Bugbot | Fixed Prettier (11 files), restored package-lock/.npmrc to main so blocking npm audit is advisory (lockfile_changed=false), updated mobile-composer-reserve contract for answer-home hero breakpoint. Prior tip e5c8c49c had Static/Safety/Unit failures. | format:check; focused Vitest 41; ci-change-scope lockfile_changed=false; no provider-backed checks. |
| 2026-07-25 | execute-audit-code-remediation (PR #1162) | 1de1b32f562c0a972997750a5dc97a02ab1a9c15 | Production UI fix | Fixed ui-tools services referral header test (H1/quick-filters contract). Prior tip 09c6eb2d had Static/Safety/Unit/Migration green; only Production UI failed. | Local Playwright chromium services referral test PASS; no provider-backed checks. |
| 2026-07-25 | execute-audit-code-remediation (PR #1162) | b9b56c140eb14cbba5a2c2230e3fa28d3a791add | CI unblock after bot sync | Tip 96188eca had PR required SUCCESS (Static/Safety/Unit/Build/Migration/Production UI). Hosted pr-branch-sync then merged main (a420b86b/b9b56c14), leaving CI action_required for bot-authored runs. Pushing agent commit to re-trigger non-bot CI. | Prior tip 96188eca hosted CI green; local services referral Playwright PASS; no provider-backed checks. |
| 2026-07-25 | PR supersede #1186 / `cursor/pr1186-audit-remediation-c94c` | `a38e83860510a4229d5658960657cd7448aff278` | Clean main-based port of intentional #1186 audit fixes | SUPERSEDE #1186 (do not merge old PR). Ported intentional 16-file delta onto current main; dropped conflicted checkpoint tree and placeholder skills. Fixed eval single results binding; async run-heavy so lock heartbeat fires; branch:cleanup dry-run default + argv-safe deletes; skill-create interface YAML. Close #1186. | Focused Vitest tooling+lock 6/6; check:skills 33; prettier on touched files; no provider/live eval runs. |
| 2026-07-25 | `cursor/ledger-066-067-519b` | f04392a408eceee14215c15169cbd6b70ac2041c | Close stale ledger #066/#067 (+ drop resolved #030/#075 from queue) | READY. #066 proven on main via #1174; #067 already fixed in #1191 in-process preflight. Docs-only ledger sync; no code change. | Local proof: `git show`/`log` for #1174/#1191; preflight test already in-process on main; ledger integrity asserts. No providers. |
| 2026-07-25 | execute-audit-remediation-plan (PR #1188) | 8b8639113925601e1687bfe4f1f29c44a4308b61 | Bugbot/diff-review: maintainability remediation tip | BLOCK: tip tree carries unresolved conflict markers (answer/upload APIs, clinical-dashboard, services, tests); invalid `async export function sha256Hex` in indexing-v3 utils; ClinicalDashboard still calls removed `renderSystemNotice`; merge-tree vs main conflicts in check-github-action-pins.mjs + ui-primitives.tsx. Intended notices extraction/dynamic imports look mostly sound; search-scope/migration not in three-dot product delta. | `git grep` conflict markers on tip (none on origin/main); `git show` for ClinicalDashboard:3824 + utils.ts:191; `git merge-tree --write-tree origin/main 8b8639113`; no provider-backed checks. |
| 2026-07-25 | PR #1209 / `cursor/pr1186-audit-remediation-c94c` | `4cb22e45dfe46b1975fa15ddd028c7e14ceb5fab` | Close #1186 + babysit #1209 CI | DONE. Closed #1186 as superseded. Synced origin/main (MERGEABLE/CLEAN). Fixed PR-policy RAG impact line. Hosted PR required SUCCESS (Static/Safety/Unit/Build/Production UI/Advisory UI/containers) on pre-ledger tip; docs-only follow-up pushed. Ready to merge; auto-merge not enabled. | gh pr checks; local policy ok; no provider/eval runs. |
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@
"workflow:rag-lab": "node scripts/productivity-workflow.mjs rag-lab",
"workflow:operator-closeout": "node scripts/productivity-workflow.mjs operator-closeout",
"workflow:lifecycle": "node scripts/productivity-workflow.mjs lifecycle",
"skill:create": "node scripts/skill-create.mjs",
"branch:cleanup": "node scripts/sweep-merged-branches.mjs",
"skills": "node scripts/list-database-skills.mjs",
"skills:sync": "node scripts/sync-skills.mjs",
"check:skills": "node scripts/list-database-skills.mjs --check",
Expand Down
149 changes: 85 additions & 64 deletions scripts/eval-retrieval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,6 @@ async function main() {
? allCases.filter((item) => item.query.toLowerCase().includes(args.query!.toLowerCase()) || item.id === args.query)
: allCases;
const cases = filteredCases.slice(0, args.limit ?? filteredCases.length);
const results: GoldenRetrievalResult[] = [];
const readinessWarnings = await visualReadinessWarnings(supabase, cases);

if (!args.json) {
Expand All @@ -912,71 +911,93 @@ async function main() {
for (const warning of readinessWarnings) console.warn(`WARN ${warning}`);
}

for (let caseIndex = 0; caseIndex < cases.length; caseIndex += 1) {
const testCase = cases[caseIndex]!;
await pauseBetweenEvalCases({
caseIndex,
forceEmbedding: testCase.forceEmbedding || args.forceEmbedding,
});
const startedAt = Date.now();
const searchPromise = withProviderBackoff(`retrieval:${testCase.id}`, () =>
searchChunksWithTelemetry({
query: testCase.query,
ownerId,
topK: retrievalLimitForGoldenCase(testCase),
minSimilarity: 0.12,
skipCache: args.mode !== "latency",
forceEmbedding: testCase.forceEmbedding || args.forceEmbedding,
}),
);
const searchOutcome = await withCaseTimeout(searchPromise, args.caseTimeoutMs);
const search = searchOutcome.timedOut
? {
results: [] as SearchResult[],
telemetry: {
query_class: testCase.expectedQueryClass,
retrieval_strategy: "timeout",
embedding_skipped: false,
text_fast_path_latency_ms: 0,
embedding_latency_ms: 0,
supabase_rpc_latency_ms: args.caseTimeoutMs,
rerank_latency_ms: 0,
retrieval_layer_counts: {},
retrieval_layer_top_scores: {},
retrieval_layer_latencies_ms: {},
},
}
: searchOutcome.value;
const latencyMs = searchOutcome.timedOut
? args.caseTimeoutMs
: latencyFromTelemetry(search.telemetry) || Date.now() - startedAt;
const latencyFailures = latencyFailuresForCase({ latencyMs, timedOut: searchOutcome.timedOut }, args);
const result = evaluateGoldenRetrievalCase({
testCase,
results: search.results,
telemetry: search.telemetry,
latencyMs,
timedOut: searchOutcome.timedOut,
latencyFailures,
globalForceEmbedding: args.forceEmbedding,
});
results.push(result);

if (!args.json) {
const status =
args.mode === "latency"
? result.latencyFailures?.length
? "SLOW"
: "OK"
: result.failures.length
? "FAIL"
: "PASS";
console.log(
`${status} ${result.id} hit@${result.topK}=${result.hitAtK ? "1" : "0"} docRecall@5=${result.documentRecallAt5.toFixed(2)} contentRecall@5=${result.contentRecallAt5.toFixed(2)} rr@10=${result.reciprocalRankAt10.toFixed(2)} contentRR@10=${result.contentReciprocalRankAt10.toFixed(2)} ndcg@10=${result.ndcgAt10.toFixed(2)} irrelevant@10=${result.irrelevantSourceRateAt10.toFixed(2)} signalCoverage@10=${result.requiredSignalCoverageAt10.toFixed(2)} latency=${result.latencyMs}ms strategy=${result.retrievalStrategy ?? "none"} gate=${result.coverageGateReason ?? "none"} layers=${JSON.stringify(result.retrievalLayerCounts ?? {})}`,
);
}
function pLimit(concurrency: number) {
let active = 0;
const queue: Array<() => void> = [];
return async <T>(fn: () => Promise<T>): Promise<T> => {
if (active >= concurrency) await new Promise<void>((resolve) => queue.push(resolve));
active += 1;
try {
return await fn();
} finally {
active -= 1;
queue.shift()?.();
}
};
}

// Latency mode stays serial so p50/p90 timing is not distorted by concurrent load.
const concurrency = args.mode === "latency" ? 1 : 5;
const limitEvaluations = pLimit(concurrency);

const results: GoldenRetrievalResult[] = await Promise.all(
cases.map((testCase, caseIndex) =>
limitEvaluations(async () => {
await pauseBetweenEvalCases({
caseIndex,
forceEmbedding: testCase.forceEmbedding || args.forceEmbedding,
});
const startedAt = Date.now();
const searchPromise = withProviderBackoff(`retrieval:${testCase.id}`, () =>
searchChunksWithTelemetry({
query: testCase.query,
ownerId,
topK: retrievalLimitForGoldenCase(testCase),
minSimilarity: 0.12,
skipCache: args.mode !== "latency",
forceEmbedding: testCase.forceEmbedding || args.forceEmbedding,
}),
);
const searchOutcome = await withCaseTimeout(searchPromise, args.caseTimeoutMs);
const search = searchOutcome.timedOut
? {
results: [] as SearchResult[],
telemetry: {
query_class: testCase.expectedQueryClass,
retrieval_strategy: "timeout",
embedding_skipped: false,
text_fast_path_latency_ms: 0,
embedding_latency_ms: 0,
supabase_rpc_latency_ms: args.caseTimeoutMs,
rerank_latency_ms: 0,
retrieval_layer_counts: {},
retrieval_layer_top_scores: {},
retrieval_layer_latencies_ms: {},
},
}
: searchOutcome.value;
const latencyMs = searchOutcome.timedOut
? args.caseTimeoutMs
: latencyFromTelemetry(search.telemetry) || Date.now() - startedAt;
const latencyFailures = latencyFailuresForCase({ latencyMs, timedOut: searchOutcome.timedOut }, args);
const result = evaluateGoldenRetrievalCase({
testCase,
results: search.results,
telemetry: search.telemetry,
latencyMs,
timedOut: searchOutcome.timedOut,
latencyFailures,
globalForceEmbedding: args.forceEmbedding,
});

if (!args.json) {
const status =
args.mode === "latency"
? result.latencyFailures?.length
? "SLOW"
: "OK"
: result.failures.length
? "FAIL"
: "PASS";
console.log(
`${status} ${result.id} hit@${result.topK}=${result.hitAtK ? "1" : "0"} docRecall@5=${result.documentRecallAt5.toFixed(2)} contentRecall@5=${result.contentRecallAt5.toFixed(2)} rr@10=${result.reciprocalRankAt10.toFixed(2)} contentRR@10=${result.contentReciprocalRankAt10.toFixed(2)} ndcg@10=${result.ndcgAt10.toFixed(2)} irrelevant@10=${result.irrelevantSourceRateAt10.toFixed(2)} signalCoverage@10=${result.requiredSignalCoverageAt10.toFixed(2)} latency=${result.latencyMs}ms strategy=${result.retrievalStrategy ?? "none"} gate=${result.coverageGateReason ?? "none"} layers=${JSON.stringify(result.retrievalLayerCounts ?? {})}`,
);
}
return result;
}),
),
);

const summary = summarizeGoldenRetrievalResults(results);
const latencyThresholdFailures =
args.mode === "latency"
Expand Down
35 changes: 26 additions & 9 deletions scripts/run-heavy.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import { spawn } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { childProcessExitCode } from "./child-process-result.mjs";
Expand All @@ -13,25 +13,42 @@ if (args[0] !== "--npm-script" || !args[1]) {
}

const script = args[1];
const forwarded = args.slice(2);
const lock = acquireHeavyRunLock({ projectRoot, command: `npm run ${script}` });
let exitCode = 1;
try {
const rawForwarded = args.slice(2);
const forceLockRelease = rawForwarded.includes("--force-lock-release");
const forwarded = rawForwarded.filter((argument) => argument !== "--force-lock-release");
const lock = acquireHeavyRunLock({
projectRoot,
command: `npm run ${script}`,
forceLockRelease,
});

function runNpmScript() {
const npmExecPath = process.env.npm_execpath;
const result = npmExecPath
? spawnSync(process.execPath, [npmExecPath, "run", script, ...(forwarded.length ? ["--", ...forwarded] : [])], {
const child = npmExecPath
? spawn(process.execPath, [npmExecPath, "run", script, ...(forwarded.length ? ["--", ...forwarded] : [])], {
cwd: projectRoot,
env: lock.environment,
stdio: "inherit",
})
: spawnSync(
: spawn(
process.platform === "win32" ? "cmd.exe" : "npm",
process.platform === "win32"
? ["/d", "/s", "/c", `npm run ${script}`]
: ["run", script, ...(forwarded.length ? ["--", ...forwarded] : [])],
{ cwd: projectRoot, env: lock.environment, stdio: "inherit" },
);
exitCode = childProcessExitCode(result);

return new Promise((resolve, reject) => {
child.on("error", reject);
child.on("close", (status, signal) => {
resolve(childProcessExitCode({ status, signal }));
});
});
}

let exitCode = 1;
try {
exitCode = await runNpmScript();
} finally {
lock.release();
}
Expand Down
81 changes: 81 additions & 0 deletions scripts/skill-create.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
const repositoryRoot = path.resolve(scriptDirectory, "..");
const skillsRoot = path.join(repositoryRoot, ".agents", "skills");
const catalogPath = path.join(skillsRoot, "catalog.json");

function toDisplayName(skillName) {
return skillName
.split("-")
.filter(Boolean)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
}

function createSkill(skillName) {
if (!/^[a-z0-9-]+$/.test(skillName)) {
console.error(`Invalid skill name: ${skillName}. Only lowercase letters, numbers, and dashes are allowed.`);
process.exit(1);
}

const skillDir = path.join(skillsRoot, skillName);
if (fs.existsSync(skillDir)) {
console.error(`Skill directory already exists: ${skillDir}`);
process.exit(1);
}

fs.mkdirSync(path.join(skillDir, "agents"), { recursive: true });

const displayName = toDisplayName(skillName);
const shortDescription = `Run the ${displayName} Database skill workflow`.slice(0, 64);
const paddedShortDescription =
shortDescription.length < 25 ? `${shortDescription} for this repository task` : shortDescription;

const skillMdContent = `---
name: ${skillName}
description: ${displayName} helper for Database work. Use this skill when the task matches ${skillName}.
---
# ${displayName}

1. Inspect the current branch, status, and touched paths.
2. Apply the smallest safe change for ${skillName}.
3. Run the narrowest local verification before widening.
`;
fs.writeFileSync(path.join(skillDir, "SKILL.md"), skillMdContent, "utf8");

const openaiYamlContent = `interface:
display_name: "${displayName}"
short_description: "${paddedShortDescription}"
default_prompt: "Use $${skillName} for this Database task."
`;
fs.writeFileSync(path.join(skillDir, "agents", "openai.yaml"), openaiYamlContent, "utf8");

const catalog = JSON.parse(fs.readFileSync(catalogPath, "utf8"));
const everydayCategory = catalog.categories.find((category) => category.name === "Everyday");
if (!everydayCategory) {
console.error('Catalog is missing the "Everyday" category.');
process.exit(1);
}
if (!everydayCategory.skills.includes(skillName)) {
everydayCategory.skills.push(skillName);
fs.writeFileSync(catalogPath, `${JSON.stringify(catalog, null, 2)}\n`, "utf8");
}

const canonicalCount = new Set(catalog.categories.flatMap((category) => category.skills)).size;
console.log(`Successfully created skill: ${skillName}`);
console.log(`Catalog now lists ${canonicalCount} canonical skills.`);
console.log("Next: refine SKILL.md, then update AGENTS.md and tests/database-skills.test.ts counts if needed.");
console.log("Verify with: npm run check:skills");
}

const args = process.argv.slice(2);
if (args.length !== 1) {
console.error("Usage: npm run skill:create -- <skill-name>");
process.exit(1);
}

createSkill(args[0]);
75 changes: 75 additions & 0 deletions scripts/sweep-merged-branches.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env node
import { spawnSync } from "node:child_process";

function runGit(args) {
const result = spawnSync("git", args, { encoding: "utf8" });
if (result.error) throw result.error;
if (result.status !== 0) {
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
throw new Error(stderr || `git ${args.join(" ")} failed with status ${result.status}`);
}
return (result.stdout || "").trim();
}

function parseArgs(argv) {
const apply = argv.includes("--apply");
const prune = !argv.includes("--no-prune");
if (argv.includes("--help") || argv.includes("-h")) {
console.log(`Usage: node scripts/sweep-merged-branches.mjs [--apply] [--no-prune]

Dry-run by default. Lists local branches already merged into main.
Pass --apply to delete those local branches with git branch -d.
Remote branches are never deleted.`);
process.exit(0);
}
return { apply, prune };
}

function main() {
const { apply, prune } = parseArgs(process.argv.slice(2));

if (prune) {
runGit(["remote", "prune", "origin"]);
}

const currentBranch = runGit(["rev-parse", "--abbrev-ref", "HEAD"]);
const mergedBranches = runGit(["branch", "--merged", "main"])
.split("\n")
.map((line) => line.trim().replace(/^\*\s+/, ""))
.filter(Boolean);

const protectedBranches = new Set(["main", "master", "develop", currentBranch]);
const branchesToDelete = mergedBranches.filter(
(branch) => !protectedBranches.has(branch) && !branch.startsWith("release/"),
);

if (branchesToDelete.length === 0) {
console.log("No merged local branches to clean up.");
return;
}

if (!apply) {
console.log("Dry-run only. Candidates that would be deleted with --apply:");
for (const branch of branchesToDelete) console.log(`- ${branch}`);
console.log(`\nRe-run with --apply to delete ${branchesToDelete.length} local branch(es).`);
return;
}

for (const branch of branchesToDelete) {
console.log(`Deleting merged branch: ${branch}`);
try {
runGit(["branch", "-d", branch]);
} catch (error) {
console.warn(`Failed to delete branch ${branch}: ${error.message}`);
}
}

console.log("Branch cleanup complete.");
}

try {
main();
} catch (error) {
console.error(`Error cleaning up branches: ${error.message}`);
process.exit(1);
}
Loading
Loading