guardian-framework 0.1.3 → 0.1.4

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/dist/cli.js CHANGED
@@ -1335,7 +1335,7 @@ __export(exports_package, {
1335
1335
  bin: () => bin,
1336
1336
  author: () => author
1337
1337
  });
1338
- var name = "guardian-framework", version = "0.1.3", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1338
+ var name = "guardian-framework", version = "0.1.4", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
1339
1339
  var init_package = __esm(() => {
1340
1340
  exports = {
1341
1341
  ".": {
package/dist/exports.js CHANGED
@@ -995,7 +995,7 @@ __export(exports_package, {
995
995
  bin: () => bin,
996
996
  author: () => author
997
997
  });
998
- var name = "guardian-framework", version = "0.1.3", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
998
+ var name = "guardian-framework", version = "0.1.4", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
999
999
  var init_package = __esm(() => {
1000
1000
  exports = {
1001
1001
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardian-framework",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -224,12 +224,28 @@ export function readGroupId(cwd: string): string {
224
224
  export function findModuleByName(cwd: string, name: string): string | null {
225
225
  const files = discoverModules(cwd);
226
226
  const nameLower = name.toLowerCase().replace(/[^a-z0-9]/g, "");
227
+
228
+ // Pass 1: exact match only (preferred)
227
229
  for (const f of files) {
228
230
  const key = f.replace(".md", "").toLowerCase().replace(/[^a-z0-9]/g, "");
229
- if (key === nameLower || nameLower.includes(key) || key.includes(nameLower)) {
231
+ if (key === nameLower) {
230
232
  return f;
231
233
  }
232
234
  }
235
+
236
+ // Pass 2: substring match — only if unambiguous (exactly one match)
237
+ const substringMatches: string[] = [];
238
+ for (const f of files) {
239
+ const key = f.replace(".md", "").toLowerCase().replace(/[^a-z0-9]/g, "");
240
+ if (nameLower.includes(key) || key.includes(nameLower)) {
241
+ substringMatches.push(f);
242
+ }
243
+ }
244
+ if (substringMatches.length === 1) {
245
+ return substringMatches[0];
246
+ }
247
+
248
+ // Ambiguous or no match — let caller decide
233
249
  return null;
234
250
  }
235
251
 
@@ -308,12 +308,28 @@ function readGroupId(cwd: string): string {
308
308
  function findModuleByName(cwd: string, name: string): string | null {
309
309
  const files = discoverModules(cwd);
310
310
  const nameLower = name.toLowerCase().replace(/[^a-z0-9]/g, "");
311
+
312
+ // Pass 1: exact match only (preferred)
311
313
  for (const f of files) {
312
314
  const key = f.replace(".md", "").toLowerCase().replace(/[^a-z0-9]/g, "");
313
- if (key === nameLower || nameLower.includes(key) || key.includes(nameLower)) {
315
+ if (key === nameLower) {
314
316
  return f;
315
317
  }
316
318
  }
319
+
320
+ // Pass 2: substring match — only if unambiguous (exactly one match)
321
+ const substringMatches: string[] = [];
322
+ for (const f of files) {
323
+ const key = f.replace(".md", "").toLowerCase().replace(/[^a-z0-9]/g, "");
324
+ if (nameLower.includes(key) || key.includes(nameLower)) {
325
+ substringMatches.push(f);
326
+ }
327
+ }
328
+ if (substringMatches.length === 1) {
329
+ return substringMatches[0];
330
+ }
331
+
332
+ // Ambiguous or no match — let caller decide
317
333
  return null;
318
334
  }
319
335
 
@@ -1021,10 +1037,21 @@ class EpicManager {
1021
1037
  const planned = components.filter((c: ModuleComponent) => c.status === "planned");
1022
1038
  if (planned.length > 0) {
1023
1039
  slice = { module: matchedModule.replace(".md", ""), components, nextLogicalSlice: planned };
1040
+ } else {
1041
+ ctx.ui.notify(
1042
+ `Module "${matchedModule}" found for epic "${name}" but has no parseable components. ` +
1043
+ `Make sure its \`## Components\` section uses sub-headings (\`### ComponentName\`) with \`status:\` markers. ` +
1044
+ `Falling back to first module with planned components.`,
1045
+ "warn",
1046
+ );
1024
1047
  }
1025
1048
  }
1026
1049
  // Fallback: first module with planned components
1027
1050
  if (!slice) {
1051
+ ctx.ui.notify(
1052
+ `No exact module match with planned components for "${name}". Using first available module instead.`,
1053
+ "warn",
1054
+ );
1028
1055
  slice = findNextLogicalSlice(this.cwd, moduleFiles);
1029
1056
  }
1030
1057
  if (!slice) {
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-02T16:34:18Z",
2
+ "timestamp": "2026-07-02T18:42:54Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -8,7 +8,7 @@
8
8
  "failed": 1,
9
9
  "skipped": 12
10
10
  },
11
- "duration_seconds": 1,
11
+ "duration_seconds": 0,
12
12
  "results": [
13
13
  {
14
14
  "name": "check_mr_traceability.sh",