feat(init): auto-seed PREFERENCES.md with detected verification_commands
Without this, every fresh project inherits sf's user-level dogfooding
defaults (npm run typecheck:extensions, test:sf-light) — which run sf's
own dev scripts against unrelated repos and produce universal false
negatives. Hit in dr-repo (Go): T01-VERIFY.json showed all_fail because
those npm scripts don't exist there, even though T01's actual work passed
verification per its SUMMARY.
- ensurePreferences() now calls detectProjectSignals() and embeds the
auto-detected commands in the YAML frontmatter on first init. Detection
failure is non-fatal — falls back to the bare template.
- detectVerificationCommands() Go branch now handles multi-module repos
(no root go.mod, only nested ones — common pattern for repos like
dr-repo/{dr-agent,portal,gateway,installer,cmd/installer}). Generates
a per-module loop instead of running go vet/test from the repo root,
which would fail since each subdir is its own Go module.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
58b1d7c601
commit
6248e79a7a
2 changed files with 44 additions and 3 deletions
|
|
@ -760,8 +760,30 @@ function detectVerificationCommands(
|
|||
|
||||
if (detectedFiles.includes("go.mod")) {
|
||||
// Limit parallelism: Go's default is GOMAXPROCS which can be very high.
|
||||
commands.push("go test -parallel 2 ./...");
|
||||
commands.push("go vet ./...");
|
||||
const rootHasGoMod = existsSync(join(basePath, "go.mod"));
|
||||
if (rootHasGoMod) {
|
||||
commands.push("go test -parallel 2 ./...");
|
||||
commands.push("go vet ./...");
|
||||
} else {
|
||||
// Multi-module repo (no root go.mod, only nested ones — common in
|
||||
// monorepos like dr-repo/{dr-agent,portal,gateway,...}). Find each
|
||||
// module dir and emit a per-module loop so commands work from the
|
||||
// repo root regardless of which modules exist.
|
||||
const scanned = scanProjectFiles(basePath);
|
||||
const moduleDirs = scanned
|
||||
.filter((f) => f.endsWith("/go.mod") || f === "go.mod")
|
||||
.map((f) => (f === "go.mod" ? "." : f.slice(0, -"/go.mod".length)))
|
||||
.filter((d) => d.length > 0 && !d.includes(".."));
|
||||
if (moduleDirs.length > 0) {
|
||||
const dirsArg = moduleDirs.map((d) => `"${d}"`).join(" ");
|
||||
commands.push(
|
||||
`bash -c 'set -e; for d in ${dirsArg}; do (cd "$d" && go vet ./...); done'`,
|
||||
);
|
||||
commands.push(
|
||||
`bash -c 'set -e; for d in ${dirsArg}; do (cd "$d" && go test -parallel 2 ./...); done'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, lstatSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { yamlSafeString } from "./commands-prefs-wizard.js";
|
||||
import { detectProjectSignals } from "./detection.js";
|
||||
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
||||
import { nativeLsFiles, nativeRmCached } from "./native-git-bridge.js";
|
||||
import { sfRoot } from "./paths.js";
|
||||
|
|
@ -271,9 +273,26 @@ export function ensurePreferences(basePath: string): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Auto-detect project type and seed verification_commands. Without this,
|
||||
// projects fall back to the user-level defaults — which point at sf's own
|
||||
// dev scripts (npm run typecheck:extensions, test:sf-light) and produce
|
||||
// false negatives on every non-Node project. Detection failure is non-fatal.
|
||||
let verifySection = "";
|
||||
try {
|
||||
const signals = detectProjectSignals(basePath);
|
||||
if (signals.verificationCommands.length > 0) {
|
||||
const lines = signals.verificationCommands.map(
|
||||
(c) => ` - ${yamlSafeString(c)}`,
|
||||
);
|
||||
verifySection = `verification_commands:\n${lines.join("\n")}\n`;
|
||||
}
|
||||
} catch {
|
||||
// fall through to bare template
|
||||
}
|
||||
|
||||
const template = `---
|
||||
version: 1
|
||||
always_use_skills: []
|
||||
${verifySection}always_use_skills: []
|
||||
prefer_skills: []
|
||||
avoid_skills: []
|
||||
skill_rules: []
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue