guardian-framework 0.1.128 → 0.1.129

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
@@ -3202,7 +3202,7 @@ __export(exports_package, {
3202
3202
  bin: () => bin,
3203
3203
  author: () => author
3204
3204
  });
3205
- var name = "guardian-framework", version = "0.1.128", 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;
3205
+ var name = "guardian-framework", version = "0.1.129", 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;
3206
3206
  var init_package = __esm(() => {
3207
3207
  exports = {
3208
3208
  ".": {
@@ -12178,6 +12178,60 @@ function answerExploration(sessionId, responseJson, options) {
12178
12178
  warnings
12179
12179
  };
12180
12180
  }
12181
+ function moduleHasImplementation(projectDir, moduleName) {
12182
+ const sanitized = (moduleName || "").toLowerCase().replace(/[^a-z0-9]/g, "");
12183
+ if (!sanitized)
12184
+ return false;
12185
+ const roots = ["src", "crates", "packages", "internal", "lib", "app", "modules"];
12186
+ const exts = ".*.(java|kt|ts|tsx|js|jsx|rs|py|go)$";
12187
+ for (const root of roots) {
12188
+ const base = path2.join(projectDir, root);
12189
+ if (!fs.existsSync(base))
12190
+ continue;
12191
+ try {
12192
+ const walk = (dir, depth) => {
12193
+ if (depth > 6)
12194
+ return false;
12195
+ let entries;
12196
+ try {
12197
+ entries = fs.readdirSync(dir, { withFileTypes: true });
12198
+ } catch {
12199
+ return false;
12200
+ }
12201
+ for (const e of entries) {
12202
+ if (e.name === "node_modules" || e.name === "target" || e.name === "dist" || e.name === ".git")
12203
+ continue;
12204
+ const full = path2.join(dir, e.name);
12205
+ if (e.isDirectory()) {
12206
+ if (e.name === sanitized && hasSourceBelow(full, depth))
12207
+ return true;
12208
+ if (walk(full, depth + 1))
12209
+ return true;
12210
+ }
12211
+ }
12212
+ return false;
12213
+ };
12214
+ const hasSourceBelow = (dir, depth) => {
12215
+ let entries;
12216
+ try {
12217
+ entries = fs.readdirSync(dir, { withFileTypes: true });
12218
+ } catch {
12219
+ return false;
12220
+ }
12221
+ for (const e of entries) {
12222
+ if (e.isFile() && new RegExp(exts).test(e.name) && !/test|spec/i.test(e.name))
12223
+ return true;
12224
+ if (e.isDirectory() && e.name !== "node_modules" && e.name !== "target" && depth < 6 && hasSourceBelow(path2.join(dir, e.name), depth + 1))
12225
+ return true;
12226
+ }
12227
+ return false;
12228
+ };
12229
+ if (walk(base, 0))
12230
+ return true;
12231
+ } catch {}
12232
+ }
12233
+ return false;
12234
+ }
12181
12235
  function readExplorationSession(sessionId, projectDir) {
12182
12236
  const root = projectDir ?? process.cwd();
12183
12237
  const filePath = path2.join(root, ".pi", "domain", "exploration", `${sessionId}.md`);
@@ -12378,11 +12432,16 @@ function scaffoldFromExploration(sessionId, options) {
12378
12432
  const invariants = bc.invariants || [];
12379
12433
  const force = options?.overwrite === true;
12380
12434
  if (!dryRun && fs.existsSync(filePath)) {
12381
- if (!force) {
12382
- warnings.push(`Module already exists, preserved (use overwrite:true to replace): ${fileName}`);
12435
+ const implemented = moduleHasImplementation(projectDir, moduleName);
12436
+ if (implemented && !force) {
12437
+ warnings.push(`Module is IMPLEMENTED, preserved (use overwrite:true to force): ${fileName}`);
12383
12438
  continue;
12384
12439
  }
12385
- warnings.push(`Module already exists, will be overwritten: ${fileName}`);
12440
+ if (implemented && force) {
12441
+ warnings.push(`Overwriting implemented module doc (--force): ${fileName}`);
12442
+ } else {
12443
+ warnings.push(`Refreshing planned module doc (no implementation yet): ${fileName}`);
12444
+ }
12386
12445
  }
12387
12446
  const aggregateRoots = contextEntities.filter((e) => e.type === "aggregate-root");
12388
12447
  const regularEntities = contextEntities.filter((e) => e.type === "entity");
@@ -13155,7 +13214,7 @@ async function runDomain(targetDir, args, options) {
13155
13214
  await runExplore(targetDir, options);
13156
13215
  break;
13157
13216
  case "scaffold":
13158
- await runScaffold(targetDir, args[1], options);
13217
+ await runScaffold(targetDir, args[1], { ...options, overwrite: args.includes("--force") });
13159
13218
  break;
13160
13219
  case "answer":
13161
13220
  await runAnswer(targetDir, args[1], args[2], options);
@@ -13262,7 +13321,8 @@ async function runScaffold(targetDir, sessionId, options) {
13262
13321
  try {
13263
13322
  const result = scaffoldFromExploration(sessionId, {
13264
13323
  projectDir: targetDir,
13265
- dryRun: options.dryRun
13324
+ dryRun: options.dryRun,
13325
+ overwrite: options.overwrite
13266
13326
  });
13267
13327
  if (options.dryRun) {
13268
13328
  outro(`Dry-run: would generate ${result.modulesGenerated} module(s)`);
package/dist/exports.js CHANGED
@@ -1987,7 +1987,7 @@ __export(exports_package, {
1987
1987
  bin: () => bin,
1988
1988
  author: () => author
1989
1989
  });
1990
- var name = "guardian-framework", version = "0.1.128", 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;
1990
+ var name = "guardian-framework", version = "0.1.129", 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;
1991
1991
  var init_package = __esm(() => {
1992
1992
  exports = {
1993
1993
  ".": {
@@ -12502,6 +12502,60 @@ function answerExploration(sessionId, responseJson, options) {
12502
12502
  warnings
12503
12503
  };
12504
12504
  }
12505
+ function moduleHasImplementation(projectDir, moduleName) {
12506
+ const sanitized = (moduleName || "").toLowerCase().replace(/[^a-z0-9]/g, "");
12507
+ if (!sanitized)
12508
+ return false;
12509
+ const roots = ["src", "crates", "packages", "internal", "lib", "app", "modules"];
12510
+ const exts = ".*.(java|kt|ts|tsx|js|jsx|rs|py|go)$";
12511
+ for (const root of roots) {
12512
+ const base = path11.join(projectDir, root);
12513
+ if (!fs12.existsSync(base))
12514
+ continue;
12515
+ try {
12516
+ const walk = (dir, depth) => {
12517
+ if (depth > 6)
12518
+ return false;
12519
+ let entries;
12520
+ try {
12521
+ entries = fs12.readdirSync(dir, { withFileTypes: true });
12522
+ } catch {
12523
+ return false;
12524
+ }
12525
+ for (const e of entries) {
12526
+ if (e.name === "node_modules" || e.name === "target" || e.name === "dist" || e.name === ".git")
12527
+ continue;
12528
+ const full = path11.join(dir, e.name);
12529
+ if (e.isDirectory()) {
12530
+ if (e.name === sanitized && hasSourceBelow(full, depth))
12531
+ return true;
12532
+ if (walk(full, depth + 1))
12533
+ return true;
12534
+ }
12535
+ }
12536
+ return false;
12537
+ };
12538
+ const hasSourceBelow = (dir, depth) => {
12539
+ let entries;
12540
+ try {
12541
+ entries = fs12.readdirSync(dir, { withFileTypes: true });
12542
+ } catch {
12543
+ return false;
12544
+ }
12545
+ for (const e of entries) {
12546
+ if (e.isFile() && new RegExp(exts).test(e.name) && !/test|spec/i.test(e.name))
12547
+ return true;
12548
+ if (e.isDirectory() && e.name !== "node_modules" && e.name !== "target" && depth < 6 && hasSourceBelow(path11.join(dir, e.name), depth + 1))
12549
+ return true;
12550
+ }
12551
+ return false;
12552
+ };
12553
+ if (walk(base, 0))
12554
+ return true;
12555
+ } catch {}
12556
+ }
12557
+ return false;
12558
+ }
12505
12559
  function readExplorationSession(sessionId, projectDir) {
12506
12560
  const root = projectDir ?? process.cwd();
12507
12561
  const filePath = path11.join(root, ".pi", "domain", "exploration", `${sessionId}.md`);
@@ -12702,11 +12756,16 @@ function scaffoldFromExploration(sessionId, options) {
12702
12756
  const invariants = bc.invariants || [];
12703
12757
  const force = options?.overwrite === true;
12704
12758
  if (!dryRun && fs12.existsSync(filePath)) {
12705
- if (!force) {
12706
- warnings.push(`Module already exists, preserved (use overwrite:true to replace): ${fileName}`);
12759
+ const implemented = moduleHasImplementation(projectDir, moduleName);
12760
+ if (implemented && !force) {
12761
+ warnings.push(`Module is IMPLEMENTED, preserved (use overwrite:true to force): ${fileName}`);
12707
12762
  continue;
12708
12763
  }
12709
- warnings.push(`Module already exists, will be overwritten: ${fileName}`);
12764
+ if (implemented && force) {
12765
+ warnings.push(`Overwriting implemented module doc (--force): ${fileName}`);
12766
+ } else {
12767
+ warnings.push(`Refreshing planned module doc (no implementation yet): ${fileName}`);
12768
+ }
12710
12769
  }
12711
12770
  const aggregateRoots = contextEntities.filter((e) => e.type === "aggregate-root");
12712
12771
  const regularEntities = contextEntities.filter((e) => e.type === "entity");
@@ -13479,7 +13538,7 @@ async function runDomain(targetDir, args, options) {
13479
13538
  await runExplore(targetDir, options);
13480
13539
  break;
13481
13540
  case "scaffold":
13482
- await runScaffold(targetDir, args[1], options);
13541
+ await runScaffold(targetDir, args[1], { ...options, overwrite: args.includes("--force") });
13483
13542
  break;
13484
13543
  case "answer":
13485
13544
  await runAnswer(targetDir, args[1], args[2], options);
@@ -13586,7 +13645,8 @@ async function runScaffold(targetDir, sessionId, options) {
13586
13645
  try {
13587
13646
  const result = scaffoldFromExploration(sessionId, {
13588
13647
  projectDir: targetDir,
13589
- dryRun: options.dryRun
13648
+ dryRun: options.dryRun,
13649
+ overwrite: options.overwrite
13590
13650
  });
13591
13651
  if (options.dryRun) {
13592
13652
  outro(`Dry-run: would generate ${result.modulesGenerated} module(s)`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardian-framework",
3
- "version": "0.1.128",
3
+ "version": "0.1.129",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -239,6 +239,45 @@ function mergeRawJson(existing: Record<string, unknown>, incoming: Record<string
239
239
  return merged;
240
240
  }
241
241
 
242
+ // True when a module has real implementation code (not just a planned doc).
243
+ function moduleHasCode(cwd: string, moduleName: string): boolean {
244
+ const sanitized = (moduleName || "").toLowerCase().replace(/[^a-z0-9]/g, "");
245
+ if (!sanitized) return false;
246
+ const roots = ["src", "crates", "packages", "internal", "lib", "app", "modules"];
247
+ const codeFile = (n: string): boolean => /.*\.(java|kt|ts|tsx|js|jsx|rs|py|go)$/.test(n) && !/test|spec/i.test(n);
248
+ const walk = (dir: string, depth: number): boolean => {
249
+ if (depth > 6) return false;
250
+ let entries;
251
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return false; }
252
+ for (const e of entries) {
253
+ if (["node_modules", "target", "dist", ".git"].includes(e.name)) continue;
254
+ const full = path.join(dir, e.name);
255
+ if (e.isFile() && codeFile(e.name)) return true;
256
+ if (e.isDirectory() && (e.name === sanitized || walk(full, depth + 1))) {
257
+ // entered the module dir: any code file below counts
258
+ if (e.name === sanitized && hasCodeBelow(full, depth)) return true;
259
+ }
260
+ }
261
+ return false;
262
+ };
263
+ const hasCodeBelow = (dir: string, depth: number): boolean => {
264
+ let entries;
265
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return false; }
266
+ for (const e of entries) {
267
+ if (["node_modules", "target", "dist"].includes(e.name)) continue;
268
+ const full = path.join(dir, e.name);
269
+ if (e.isFile() && codeFile(e.name)) return true;
270
+ if (e.isDirectory() && depth < 6 && hasCodeBelow(full, depth + 1)) return true;
271
+ }
272
+ return false;
273
+ };
274
+ for (const r of roots) {
275
+ const base = path.join(cwd, r);
276
+ if (fs.existsSync(base) && walk(base, 0)) return true;
277
+ }
278
+ return false;
279
+ }
280
+
242
281
  function buildExplorationPrompt(context: string): string {
243
282
  return [
244
283
  "You are a Domain-Driven Design expert. Analyze the following business",
@@ -1058,7 +1097,7 @@ export default function (pi: ExtensionAPI) {
1058
1097
  let scaffoldError = "";
1059
1098
 
1060
1099
  try {
1061
- const cmd = "guardian-framework domain scaffold " + sessionId + " 2>&1";
1100
+ const cmd = "guardian-framework domain scaffold " + sessionId + (forceScaffold ? " --force" : "") + " 2>&1";
1062
1101
  const shellResult = await shellExec(ctx, cmd);
1063
1102
  if (shellResult.exitCode === 0) {
1064
1103
  const outputLines = shellResult.stdout.split("\n");
@@ -1281,7 +1320,9 @@ export default function (pi: ExtensionAPI) {
1281
1320
  }
1282
1321
  const preserved: string[] = [];
1283
1322
  const moduleFiles = sessionModules.filter((f) => {
1284
- if (fs.existsSync(path.join(modulesDir, f)) && !forceEnrich) {
1323
+ const exists = fs.existsSync(path.join(modulesDir, f));
1324
+ const implemented = moduleHasCode(ctx.cwd, f.replace(/\.md$/, ""));
1325
+ if (exists && implemented && !forceEnrich) {
1285
1326
  preserved.push(f);
1286
1327
  return false;
1287
1328
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-09-06T13:11:45Z",
2
+ "timestamp": "2026-09-06T13:20:31Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {