qfai 1.0.3 → 1.0.5

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 (99) hide show
  1. package/README.md +53 -74
  2. package/assets/init/.qfai/README.md +17 -82
  3. package/assets/init/.qfai/assistant/README.md +9 -0
  4. package/assets/init/.qfai/assistant/agents/README.md +34 -0
  5. package/assets/init/.qfai/assistant/agents/architect.md +73 -0
  6. package/assets/init/.qfai/assistant/agents/backend-engineer.md +73 -0
  7. package/assets/init/.qfai/assistant/agents/code-reviewer.md +73 -0
  8. package/assets/init/.qfai/assistant/agents/contract-designer.md +73 -0
  9. package/assets/init/.qfai/assistant/agents/devops-ci-engineer.md +73 -0
  10. package/assets/init/.qfai/assistant/agents/facilitator.md +74 -0
  11. package/assets/init/.qfai/assistant/agents/frontend-engineer.md +73 -0
  12. package/assets/init/.qfai/assistant/agents/interviewer.md +72 -0
  13. package/assets/init/.qfai/assistant/agents/planner.md +73 -0
  14. package/assets/init/.qfai/assistant/agents/qa-engineer.md +73 -0
  15. package/assets/init/.qfai/assistant/agents/requirements-analyst.md +73 -0
  16. package/assets/init/.qfai/assistant/agents/test-engineer.md +73 -0
  17. package/assets/init/.qfai/assistant/instructions/README.md +6 -0
  18. package/assets/init/.qfai/assistant/instructions/constitution.md +131 -0
  19. package/assets/init/.qfai/assistant/instructions/workflow.md +75 -0
  20. package/assets/init/.qfai/assistant/prompts/README.md +19 -0
  21. package/assets/init/.qfai/assistant/prompts/qfai-discuss.md +173 -0
  22. package/assets/init/.qfai/assistant/prompts/qfai-implement.md +239 -0
  23. package/assets/init/.qfai/assistant/prompts/qfai-pr.md +218 -0
  24. package/assets/init/.qfai/assistant/prompts/qfai-require.md +273 -0
  25. package/assets/init/.qfai/assistant/prompts/qfai-scenario-test.md +229 -0
  26. package/assets/init/.qfai/assistant/prompts/qfai-spec.md +287 -0
  27. package/assets/init/.qfai/assistant/prompts/qfai-unit-test.md +202 -0
  28. package/assets/init/.qfai/assistant/prompts/qfai-verify.md +231 -0
  29. package/assets/init/.qfai/assistant/prompts.local/README.md +6 -0
  30. package/assets/init/.qfai/assistant/steering/README.md +33 -0
  31. package/assets/init/.qfai/assistant/steering/product.md +32 -0
  32. package/assets/init/.qfai/assistant/steering/structure.md +34 -0
  33. package/assets/init/.qfai/assistant/steering/tech.md +37 -0
  34. package/assets/init/.qfai/contracts/README.md +7 -87
  35. package/assets/init/.qfai/contracts/api/README.md +8 -0
  36. package/assets/init/.qfai/contracts/db/README.md +8 -0
  37. package/assets/init/.qfai/contracts/ui/README.md +8 -0
  38. package/assets/init/.qfai/report/README.md +13 -0
  39. package/assets/init/.qfai/require/README.md +4 -26
  40. package/assets/init/.qfai/require/require.md +74 -0
  41. package/assets/init/.qfai/specs/README.md +6 -57
  42. package/assets/init/root/.github/workflows/qfai.yml +1 -1
  43. package/assets/init/root/qfai.config.yaml +3 -4
  44. package/dist/cli/index.cjs +313 -472
  45. package/dist/cli/index.cjs.map +1 -1
  46. package/dist/cli/index.mjs +295 -454
  47. package/dist/cli/index.mjs.map +1 -1
  48. package/dist/index.cjs +37 -63
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +0 -1
  51. package/dist/index.d.ts +0 -1
  52. package/dist/index.mjs +37 -63
  53. package/dist/index.mjs.map +1 -1
  54. package/package.json +1 -1
  55. package/assets/init/.qfai/contracts/api/api-0001-sample.yaml +0 -15
  56. package/assets/init/.qfai/contracts/db/db-0001-sample.sql +0 -7
  57. package/assets/init/.qfai/contracts/ui/assets/thema-001-facebook-like/assets.yaml +0 -6
  58. package/assets/init/.qfai/contracts/ui/assets/thema-001-facebook-like/palette.png +0 -0
  59. package/assets/init/.qfai/contracts/ui/assets/ui-0001-sample/assets.yaml +0 -6
  60. package/assets/init/.qfai/contracts/ui/assets/ui-0001-sample/snapshots/login__desktop__light__default.png +0 -0
  61. package/assets/init/.qfai/contracts/ui/thema-001-facebook-like.yml +0 -13
  62. package/assets/init/.qfai/contracts/ui/ui-0001-sample.yaml +0 -17
  63. package/assets/init/.qfai/out/README.md +0 -17
  64. package/assets/init/.qfai/promptpack/commands/implement.md +0 -8
  65. package/assets/init/.qfai/promptpack/commands/plan.md +0 -11
  66. package/assets/init/.qfai/promptpack/commands/release.md +0 -6
  67. package/assets/init/.qfai/promptpack/commands/review.md +0 -7
  68. package/assets/init/.qfai/promptpack/constitution.md +0 -15
  69. package/assets/init/.qfai/promptpack/modes/change.md +0 -5
  70. package/assets/init/.qfai/promptpack/modes/compatibility.md +0 -6
  71. package/assets/init/.qfai/promptpack/roles/qa.md +0 -4
  72. package/assets/init/.qfai/promptpack/roles/spec.md +0 -4
  73. package/assets/init/.qfai/promptpack/roles/test.md +0 -4
  74. package/assets/init/.qfai/promptpack/steering/compatibility-vs-change.md +0 -42
  75. package/assets/init/.qfai/promptpack/steering/naming.md +0 -7
  76. package/assets/init/.qfai/promptpack/steering/traceability.md +0 -25
  77. package/assets/init/.qfai/prompts/README.md +0 -70
  78. package/assets/init/.qfai/prompts/analyze/README.md +0 -21
  79. package/assets/init/.qfai/prompts/analyze/scenario_test_consistency.md +0 -8
  80. package/assets/init/.qfai/prompts/analyze/scenario_to_test.md +0 -56
  81. package/assets/init/.qfai/prompts/analyze/spec_contract_consistency.md +0 -8
  82. package/assets/init/.qfai/prompts/analyze/spec_scenario_consistency.md +0 -8
  83. package/assets/init/.qfai/prompts/analyze/spec_to_contract.md +0 -54
  84. package/assets/init/.qfai/prompts/analyze/spec_to_scenario.md +0 -56
  85. package/assets/init/.qfai/prompts/makeBusinessFlow.md +0 -34
  86. package/assets/init/.qfai/prompts/makeOverview.md +0 -27
  87. package/assets/init/.qfai/prompts/qfai-classify-change.md +0 -33
  88. package/assets/init/.qfai/prompts/qfai-generate-test-globs.md +0 -29
  89. package/assets/init/.qfai/prompts/qfai-maintain-contracts.md +0 -35
  90. package/assets/init/.qfai/prompts/qfai-maintain-traceability.md +0 -36
  91. package/assets/init/.qfai/prompts/require-to-spec.md +0 -41
  92. package/assets/init/.qfai/prompts.local/README.md +0 -31
  93. package/assets/init/.qfai/rules/conventions.md +0 -27
  94. package/assets/init/.qfai/rules/pnpm.md +0 -29
  95. package/assets/init/.qfai/samples/analyze/analysis.md +0 -38
  96. package/assets/init/.qfai/samples/analyze/input_bundle.md +0 -54
  97. package/assets/init/.qfai/specs/spec-0001/delta.md +0 -30
  98. package/assets/init/.qfai/specs/spec-0001/scenario.feature +0 -11
  99. package/assets/init/.qfai/specs/spec-0001/spec.md +0 -40
package/dist/index.cjs CHANGED
@@ -63,9 +63,8 @@ var defaultConfig = {
63
63
  paths: {
64
64
  contractsDir: ".qfai/contracts",
65
65
  specsDir: ".qfai/specs",
66
- rulesDir: ".qfai/rules",
67
- outDir: ".qfai/out",
68
- promptsDir: ".qfai/prompts",
66
+ outDir: ".qfai/report",
67
+ promptsDir: ".qfai/assistant/prompts",
69
68
  srcDir: "src",
70
69
  testsDir: "tests"
71
70
  },
@@ -93,7 +92,7 @@ var defaultConfig = {
93
92
  }
94
93
  },
95
94
  output: {
96
- validateJsonPath: ".qfai/out/validate.json"
95
+ validateJsonPath: ".qfai/report/validate.json"
97
96
  }
98
97
  };
99
98
  function getConfigPath(root) {
@@ -176,13 +175,6 @@ function normalizePaths(raw, configPath, issues) {
176
175
  configPath,
177
176
  issues
178
177
  ),
179
- rulesDir: readString(
180
- raw.rulesDir,
181
- base.rulesDir,
182
- "paths.rulesDir",
183
- configPath,
184
- issues
185
- ),
186
178
  outDir: readString(
187
179
  raw.outDir,
188
180
  base.outDir,
@@ -1298,8 +1290,8 @@ var import_promises7 = require("fs/promises");
1298
1290
  var import_node_path8 = __toESM(require("path"), 1);
1299
1291
  var import_node_url = require("url");
1300
1292
  async function resolveToolVersion() {
1301
- if ("1.0.3".length > 0) {
1302
- return "1.0.3";
1293
+ if ("1.0.5".length > 0) {
1294
+ return "1.0.5";
1303
1295
  }
1304
1296
  try {
1305
1297
  const packagePath = resolvePackageJsonPath();
@@ -2048,11 +2040,6 @@ function issue(code, message, severity, file, rule, refs, category = "compatibil
2048
2040
  // src/core/validators/delta.ts
2049
2041
  var import_promises9 = require("fs/promises");
2050
2042
  var import_node_path11 = __toESM(require("path"), 1);
2051
- var SECTION_RE = /^##\s+変更区分/m;
2052
- var COMPAT_LINE_RE = /^\s*-\s*\[[ xX]\]\s*Compatibility\b/m;
2053
- var CHANGE_LINE_RE = /^\s*-\s*\[[ xX]\]\s*Change\/Improvement\b/m;
2054
- var COMPAT_CHECKED_RE = /^\s*-\s*\[[xX]\]\s*Compatibility\b/m;
2055
- var CHANGE_CHECKED_RE = /^\s*-\s*\[[xX]\]\s*Change\/Improvement\b/m;
2056
2043
  async function validateDeltas(root, config) {
2057
2044
  const specsRoot = resolvePath(root, config, "specsDir");
2058
2045
  const packs = await collectSpecPackDirs(specsRoot);
@@ -2062,9 +2049,8 @@ async function validateDeltas(root, config) {
2062
2049
  const issues = [];
2063
2050
  for (const pack of packs) {
2064
2051
  const deltaPath = import_node_path11.default.join(pack, "delta.md");
2065
- let text;
2066
2052
  try {
2067
- text = await (0, import_promises9.readFile)(deltaPath, "utf-8");
2053
+ await (0, import_promises9.readFile)(deltaPath, "utf-8");
2068
2054
  } catch (error) {
2069
2055
  if (isMissingFileError2(error)) {
2070
2056
  issues.push(
@@ -2073,41 +2059,16 @@ async function validateDeltas(root, config) {
2073
2059
  "delta.md \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
2074
2060
  "error",
2075
2061
  deltaPath,
2076
- "delta.exists"
2062
+ "delta.exists",
2063
+ void 0,
2064
+ "change",
2065
+ "spec-xxxx/delta.md \u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u30C6\u30F3\u30D7\u30EC\u306F init \u751F\u6210\u7269\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\uFF09\u3002"
2077
2066
  )
2078
2067
  );
2079
2068
  continue;
2080
2069
  }
2081
2070
  throw error;
2082
2071
  }
2083
- const hasSection = SECTION_RE.test(text);
2084
- const hasCompatibility = COMPAT_LINE_RE.test(text);
2085
- const hasChange = CHANGE_LINE_RE.test(text);
2086
- if (!hasSection || !hasCompatibility || !hasChange) {
2087
- issues.push(
2088
- issue2(
2089
- "QFAI-DELTA-002",
2090
- "delta.md \u306E\u5909\u66F4\u533A\u5206\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059\u3002`## \u5909\u66F4\u533A\u5206` \u3068\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\uFF08Compatibility / Change/Improvement\uFF09\u3092\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
2091
- "error",
2092
- deltaPath,
2093
- "delta.section"
2094
- )
2095
- );
2096
- continue;
2097
- }
2098
- const compatibilityChecked = COMPAT_CHECKED_RE.test(text);
2099
- const changeChecked = CHANGE_CHECKED_RE.test(text);
2100
- if (compatibilityChecked === changeChecked) {
2101
- issues.push(
2102
- issue2(
2103
- "QFAI-DELTA-003",
2104
- "delta.md \u306E\u5909\u66F4\u533A\u5206\u306F\u3069\u3061\u3089\u304B1\u3064\u3060\u3051\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4E21\u65B9ON/\u4E21\u65B9OFF\u306F\u7121\u52B9\u3067\u3059\uFF09\u3002",
2105
- "error",
2106
- deltaPath,
2107
- "delta.classification"
2108
- )
2109
- );
2110
- }
2111
2072
  }
2112
2073
  return issues;
2113
2074
  }
@@ -2264,11 +2225,25 @@ function getInitAssetsDir() {
2264
2225
  }
2265
2226
 
2266
2227
  // src/core/promptsIntegrity.ts
2267
- async function diffProjectPromptsAgainstInitAssets(root) {
2268
- const promptsDir = import_node_path14.default.resolve(root, ".qfai", "prompts");
2228
+ var LEGACY_OK_EXTRA = /* @__PURE__ */ new Set(["qfai-classify-change.md"]);
2229
+ async function diffProjectPromptsAgainstInitAssets(root, config) {
2230
+ const promptsDirConfig = config.paths.promptsDir;
2231
+ const promptsDir = import_node_path14.default.isAbsolute(promptsDirConfig) ? promptsDirConfig : import_node_path14.default.resolve(root, promptsDirConfig);
2269
2232
  let templateDir;
2270
2233
  try {
2271
- templateDir = import_node_path14.default.join(getInitAssetsDir(), ".qfai", "prompts");
2234
+ const rel = import_node_path14.default.isAbsolute(promptsDirConfig) ? import_node_path14.default.relative(root, promptsDirConfig) : promptsDirConfig;
2235
+ const normalized = rel.replace(/^[\\/]+/, "");
2236
+ if (normalized.length === 0 || normalized.startsWith("..")) {
2237
+ return {
2238
+ status: "skipped_missing_assets",
2239
+ promptsDir,
2240
+ templateDir: "",
2241
+ missing: [],
2242
+ extra: [],
2243
+ changed: []
2244
+ };
2245
+ }
2246
+ templateDir = import_node_path14.default.join(getInitAssetsDir(), normalized);
2272
2247
  } catch {
2273
2248
  return {
2274
2249
  status: "skipped_missing_assets",
@@ -2312,6 +2287,7 @@ async function diffProjectPromptsAgainstInitAssets(root) {
2312
2287
  extra.push(rel);
2313
2288
  }
2314
2289
  }
2290
+ const filteredExtra = extra.filter((rel) => !LEGACY_OK_EXTRA.has(rel));
2315
2291
  const common = intersectKeys(templateByRel, projectByRel);
2316
2292
  for (const rel of common) {
2317
2293
  const templateAbs = templateByRel.get(rel);
@@ -2331,13 +2307,13 @@ async function diffProjectPromptsAgainstInitAssets(root) {
2331
2307
  changed.push(rel);
2332
2308
  }
2333
2309
  }
2334
- const status = missing.length > 0 || extra.length > 0 || changed.length > 0 ? "modified" : "ok";
2310
+ const status = missing.length > 0 || filteredExtra.length > 0 || changed.length > 0 ? "modified" : "ok";
2335
2311
  return {
2336
2312
  status,
2337
2313
  promptsDir,
2338
2314
  templateDir,
2339
2315
  missing: missing.sort(),
2340
- extra: extra.sort(),
2316
+ extra: filteredExtra.sort(),
2341
2317
  changed: changed.sort()
2342
2318
  };
2343
2319
  }
@@ -2359,8 +2335,8 @@ function intersectKeys(a, b) {
2359
2335
  }
2360
2336
 
2361
2337
  // src/core/validators/promptsIntegrity.ts
2362
- async function validatePromptsIntegrity(root) {
2363
- const diff = await diffProjectPromptsAgainstInitAssets(root);
2338
+ async function validatePromptsIntegrity(root, config) {
2339
+ const diff = await diffProjectPromptsAgainstInitAssets(root, config);
2364
2340
  if (diff.status !== "modified") {
2365
2341
  return [];
2366
2342
  }
@@ -2377,11 +2353,11 @@ async function validatePromptsIntegrity(root) {
2377
2353
  code: "QFAI-PROMPTS-001",
2378
2354
  severity: "error",
2379
2355
  category: "change",
2380
- message: `\u6A19\u6E96\u8CC7\u7523 '.qfai/prompts/**' \u304C\u6539\u5909\u3055\u308C\u3066\u3044\u307E\u3059\uFF08${hints || `\u5DEE\u5206=${total}`}\uFF09\u3002${sampleText}`,
2356
+ message: `\u6A19\u6E96\u8CC7\u7523 '.qfai/assistant/prompts/**' \u304C\u6539\u5909\u3055\u308C\u3066\u3044\u307E\u3059\uFF08${hints || `\u5DEE\u5206=${total}`}\uFF09\u3002${sampleText}`,
2381
2357
  suggested_action: [
2382
2358
  "prompts \u306E\u76F4\u7DE8\u96C6\u306F\u975E\u63A8\u5968\u3067\u3059\uFF08\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8/\u518D init \u3067\u4E0A\u66F8\u304D\u3055\u308C\u5F97\u307E\u3059\uFF09\u3002",
2383
2359
  "\u6B21\u306E\u3044\u305A\u308C\u304B\u3092\u5B9F\u65BD\u3057\u3066\u304F\u3060\u3055\u3044:",
2384
- "- \u5909\u66F4\u3057\u305F\u3044\u5834\u5408: \u540C\u4E00\u76F8\u5BFE\u30D1\u30B9\u3067 '.qfai/prompts.local/**' \u306B\u7F6E\u3044\u3066 overlay",
2360
+ "- \u5909\u66F4\u3057\u305F\u3044\u5834\u5408: \u540C\u4E00\u76F8\u5BFE\u30D1\u30B9\u3067 '.qfai/assistant/prompts.local/**' \u306B\u7F6E\u3044\u3066 overlay",
2385
2361
  "- \u6A19\u6E96\u72B6\u614B\u3078\u623B\u3059\u5834\u5408: 'qfai init --force' \u3092\u5B9F\u884C\uFF08prompts \u306E\u307F\u4E0A\u66F8\u304D\u3001prompts.local \u306F\u4FDD\u8B77\uFF09"
2386
2362
  ].join("\n"),
2387
2363
  rule: "prompts.integrity"
@@ -3252,7 +3228,7 @@ async function validateProject(root, configResult) {
3252
3228
  const { config, issues: configIssues } = resolved;
3253
3229
  const issues = [
3254
3230
  ...configIssues,
3255
- ...await validatePromptsIntegrity(root),
3231
+ ...await validatePromptsIntegrity(root, config),
3256
3232
  ...await validateSpecs(root, config),
3257
3233
  ...await validateDeltas(root, config),
3258
3234
  ...await validateScenarios(root, config),
@@ -3774,11 +3750,9 @@ function formatReportMarkdown(data, options = {}) {
3774
3750
  "- issue \u306F\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u904B\u7528\u30C6\u30F3\u30D7\u30EC\u306B\u6CBF\u3063\u3066\u7D99\u7D9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
3775
3751
  );
3776
3752
  }
3753
+ lines.push("- \u5909\u66F4\u5185\u5BB9\u30FB\u53D7\u5165\u89B3\u70B9\u306F `.qfai/specs/*/delta.md` \u306B\u8A18\u9332\u3057\u307E\u3059\u3002");
3777
3754
  lines.push(
3778
- "- \u5909\u66F4\u533A\u5206\uFF08Compatibility / Change/Improvement\uFF09\u306F `.qfai/specs/*/delta.md` \u306B\u8A18\u9332\u3057\u307E\u3059\u3002"
3779
- );
3780
- lines.push(
3781
- "- \u53C2\u7167\u30EB\u30FC\u30EB\u306E\u6B63\u672C: `.qfai/promptpack/steering/traceability.md` / `.qfai/promptpack/steering/compatibility-vs-change.md`"
3755
+ "- \u53C2\u7167\u30EB\u30FC\u30EB\u306E\u6B63\u672C: `.qfai/assistant/instructions/constitution.md`"
3782
3756
  );
3783
3757
  return lines.join("\n");
3784
3758
  }