qfai 0.6.3 → 0.7.1

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.
@@ -870,8 +870,8 @@ import { readFile as readFile3 } from "fs/promises";
870
870
  import path6 from "path";
871
871
  import { fileURLToPath } from "url";
872
872
  async function resolveToolVersion() {
873
- if ("0.6.3".length > 0) {
874
- return "0.6.3";
873
+ if ("0.7.1".length > 0) {
874
+ return "0.7.1";
875
875
  }
876
876
  try {
877
877
  const packagePath = resolvePackageJsonPath();
@@ -902,7 +902,7 @@ function addCheck(checks, check) {
902
902
  checks.push(check);
903
903
  }
904
904
  function summarize(checks) {
905
- const summary = { ok: 0, warning: 0, error: 0 };
905
+ const summary = { ok: 0, info: 0, warning: 0, error: 0 };
906
906
  for (const check of checks) {
907
907
  summary[check.severity] += 1;
908
908
  }
@@ -974,6 +974,20 @@ async function createDoctorData(options) {
974
974
  message: ok ? `${key} exists` : `${key} is missing (did you run 'qfai init'?)`,
975
975
  details: { path: toRelativePath(root, resolved) }
976
976
  });
977
+ if (key === "promptsDir") {
978
+ const promptsLocalDir = path7.join(
979
+ path7.dirname(resolved),
980
+ `${path7.basename(resolved)}.local`
981
+ );
982
+ const found = await exists4(promptsLocalDir);
983
+ addCheck(checks, {
984
+ id: "paths.promptsLocalDir",
985
+ severity: "info",
986
+ title: "Prompts overlay (prompts.local)",
987
+ message: found ? "prompts.local exists (overlay can be used)" : "prompts.local is optional (create it to override prompts)",
988
+ details: { path: toRelativePath(root, promptsLocalDir) }
989
+ });
990
+ }
977
991
  }
978
992
  const specsRoot = resolvePath(root, config, "specsDir");
979
993
  const entries = await collectSpecEntries(specsRoot);
@@ -1172,7 +1186,7 @@ function formatDoctorText(data) {
1172
1186
  lines.push(`[${check.severity}] ${check.id}: ${check.message}`);
1173
1187
  }
1174
1188
  lines.push(
1175
- `summary: ok=${data.summary.ok} warning=${data.summary.warning} error=${data.summary.error}`
1189
+ `summary: ok=${data.summary.ok} info=${data.summary.info} warning=${data.summary.warning} error=${data.summary.error}`
1176
1190
  );
1177
1191
  return lines.join("\n");
1178
1192
  }
@@ -1221,9 +1235,22 @@ async function copyFiles(files, sourceRoot, destRoot, options) {
1221
1235
  const copied = [];
1222
1236
  const skipped = [];
1223
1237
  const conflicts = [];
1238
+ const protectPrefixes = (options.protect ?? []).map((p) => p.replace(/^[\\/]+/, "").replace(/[\\/]+$/, "")).filter((p) => p.length > 0).map((p) => p + path9.sep);
1239
+ const isProtectedRelative = (relative) => {
1240
+ if (protectPrefixes.length === 0) {
1241
+ return false;
1242
+ }
1243
+ const normalized = relative.replace(/[\\/]+/g, path9.sep);
1244
+ return protectPrefixes.some(
1245
+ (prefix) => normalized === prefix.slice(0, -1) || normalized.startsWith(prefix)
1246
+ );
1247
+ };
1224
1248
  if (!options.force) {
1225
1249
  for (const file of files) {
1226
1250
  const relative = path9.relative(sourceRoot, file);
1251
+ if (isProtectedRelative(relative)) {
1252
+ continue;
1253
+ }
1227
1254
  const dest = path9.join(destRoot, relative);
1228
1255
  if (!await shouldWrite(dest, options.force)) {
1229
1256
  conflicts.push(dest);
@@ -1236,7 +1263,8 @@ async function copyFiles(files, sourceRoot, destRoot, options) {
1236
1263
  for (const file of files) {
1237
1264
  const relative = path9.relative(sourceRoot, file);
1238
1265
  const dest = path9.join(destRoot, relative);
1239
- if (!await shouldWrite(dest, options.force)) {
1266
+ const forceForThisFile = isProtectedRelative(relative) ? false : options.force;
1267
+ if (!await shouldWrite(dest, forceForThisFile)) {
1240
1268
  skipped.push(dest);
1241
1269
  continue;
1242
1270
  }
@@ -1331,7 +1359,8 @@ async function runInit(options) {
1331
1359
  });
1332
1360
  const qfaiResult = await copyTemplateTree(qfaiAssets, destQfai, {
1333
1361
  force: options.force,
1334
- dryRun: options.dryRun
1362
+ dryRun: options.dryRun,
1363
+ protect: ["prompts.local"]
1335
1364
  });
1336
1365
  report(
1337
1366
  [...rootResult.copied, ...qfaiResult.copied],