guardian-framework 0.1.152 → 0.1.154

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
@@ -3206,7 +3206,7 @@ __export(exports_package, {
3206
3206
  bin: () => bin,
3207
3207
  author: () => author
3208
3208
  });
3209
- var name = "guardian-framework", version = "0.1.152", 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;
3209
+ var name = "guardian-framework", version = "0.1.154", 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;
3210
3210
  var init_package = __esm(() => {
3211
3211
  exports = {
3212
3212
  ".": {
@@ -3217,17 +3217,14 @@ var init_package = __esm(() => {
3217
3217
  bin = {
3218
3218
  "guardian-framework": "dist/cli.js"
3219
3219
  };
3220
- files = [
3221
- "dist/",
3222
- "templates/"
3223
- ];
3220
+ files = ["dist/", "templates/"];
3224
3221
  engines = {
3225
3222
  bun: ">=1.0.0"
3226
3223
  };
3227
3224
  scripts = {
3228
3225
  build: "bun build ./src/exports.ts --outfile ./dist/exports.js --target node --format esm && bun build ./src/cli.ts --outfile ./dist/cli.js --target bun --format esm",
3229
3226
  "build:types": "tsc --emitDeclarationOnly --outDir dist || true",
3230
- prepublishOnly: "bun run build && bun test",
3227
+ prepublishOnly: "bun run typecheck && bunx biome ci . && bun run build && bun test",
3231
3228
  test: "bun test",
3232
3229
  lint: "biome check src tests",
3233
3230
  format: "biome format . --write",
@@ -3238,15 +3235,9 @@ var init_package = __esm(() => {
3238
3235
  access: "public"
3239
3236
  };
3240
3237
  pi = {
3241
- extensions: [
3242
- "./templates/pi/extensions"
3243
- ],
3244
- skills: [
3245
- "./templates/pi/skills"
3246
- ],
3247
- prompts: [
3248
- "./templates/pi/prompts"
3249
- ]
3238
+ extensions: ["./templates/pi/extensions"],
3239
+ skills: ["./templates/pi/skills"],
3240
+ prompts: ["./templates/pi/prompts"]
3250
3241
  };
3251
3242
  repository = {
3252
3243
  type: "git",
package/dist/exports.js CHANGED
@@ -1991,7 +1991,7 @@ __export(exports_package, {
1991
1991
  bin: () => bin,
1992
1992
  author: () => author
1993
1993
  });
1994
- var name = "guardian-framework", version = "0.1.152", 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;
1994
+ var name = "guardian-framework", version = "0.1.154", 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;
1995
1995
  var init_package = __esm(() => {
1996
1996
  exports = {
1997
1997
  ".": {
@@ -2002,17 +2002,14 @@ var init_package = __esm(() => {
2002
2002
  bin = {
2003
2003
  "guardian-framework": "dist/cli.js"
2004
2004
  };
2005
- files = [
2006
- "dist/",
2007
- "templates/"
2008
- ];
2005
+ files = ["dist/", "templates/"];
2009
2006
  engines = {
2010
2007
  bun: ">=1.0.0"
2011
2008
  };
2012
2009
  scripts = {
2013
2010
  build: "bun build ./src/exports.ts --outfile ./dist/exports.js --target node --format esm && bun build ./src/cli.ts --outfile ./dist/cli.js --target bun --format esm",
2014
2011
  "build:types": "tsc --emitDeclarationOnly --outDir dist || true",
2015
- prepublishOnly: "bun run build && bun test",
2012
+ prepublishOnly: "bun run typecheck && bunx biome ci . && bun run build && bun test",
2016
2013
  test: "bun test",
2017
2014
  lint: "biome check src tests",
2018
2015
  format: "biome format . --write",
@@ -2023,15 +2020,9 @@ var init_package = __esm(() => {
2023
2020
  access: "public"
2024
2021
  };
2025
2022
  pi = {
2026
- extensions: [
2027
- "./templates/pi/extensions"
2028
- ],
2029
- skills: [
2030
- "./templates/pi/skills"
2031
- ],
2032
- prompts: [
2033
- "./templates/pi/prompts"
2034
- ]
2023
+ extensions: ["./templates/pi/extensions"],
2024
+ skills: ["./templates/pi/skills"],
2025
+ prompts: ["./templates/pi/prompts"]
2035
2026
  };
2036
2027
  repository = {
2037
2028
  type: "git",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardian-framework",
3
- "version": "0.1.152",
3
+ "version": "0.1.154",
4
4
  "description": "Token-optimized agentic framework scaffolder with pi-first architecture",
5
5
  "type": "module",
6
6
  "main": "dist/exports.js",
@@ -14,17 +14,14 @@
14
14
  "bin": {
15
15
  "guardian-framework": "dist/cli.js"
16
16
  },
17
- "files": [
18
- "dist/",
19
- "templates/"
20
- ],
17
+ "files": ["dist/", "templates/"],
21
18
  "engines": {
22
19
  "bun": ">=1.0.0"
23
20
  },
24
21
  "scripts": {
25
22
  "build": "bun build ./src/exports.ts --outfile ./dist/exports.js --target node --format esm && bun build ./src/cli.ts --outfile ./dist/cli.js --target bun --format esm",
26
23
  "build:types": "tsc --emitDeclarationOnly --outDir dist || true",
27
- "prepublishOnly": "bun run build && bun test",
24
+ "prepublishOnly": "bun run typecheck && bunx biome ci . && bun run build && bun test",
28
25
  "test": "bun test",
29
26
  "lint": "biome check src tests",
30
27
  "format": "biome format . --write",
@@ -35,15 +32,9 @@
35
32
  "access": "public"
36
33
  },
37
34
  "pi": {
38
- "extensions": [
39
- "./templates/pi/extensions"
40
- ],
41
- "skills": [
42
- "./templates/pi/skills"
43
- ],
44
- "prompts": [
45
- "./templates/pi/prompts"
46
- ]
35
+ "extensions": ["./templates/pi/extensions"],
36
+ "skills": ["./templates/pi/skills"],
37
+ "prompts": ["./templates/pi/prompts"]
47
38
  },
48
39
  "repository": {
49
40
  "type": "git",
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-11-13T16:42:50Z",
2
+ "timestamp": "2026-11-13T16:52:48Z",
3
3
  "mode": "all",
4
4
  "stages_run": [],
5
5
  "summary": {
@@ -170,13 +170,15 @@ echo ""
170
170
  # ── Dependency gate ─────────────────────────────────────────────────────────
171
171
  # A module may only run in parallel once the modules it depends on are
172
172
  # implemented. Deps inside this same batch cannot be satisfied yet either.
173
- DEP_CHECK="$(python3 - "$ROOT" ${MODULES[@]+"${MODULES[@]}"} <<'PY'
173
+ DEP_CHECK="$(python3 - "$ROOT" "$COMMON_ABS/guardian/epics.json" ${MODULES[@]+"${MODULES[@]}"} <<'PY'
174
174
  import os, re, sys
175
175
 
176
176
  root = sys.argv[1]
177
- batch = sys.argv[2:]
177
+ registry_path = sys.argv[2]
178
+ batch = sys.argv[3:]
178
179
  mods_dir = os.path.join(root, ".pi/architecture/modules")
179
180
 
181
+
180
182
  def doc_path(slug):
181
183
  p = os.path.join(mods_dir, f"{slug}.md")
182
184
  return p if os.path.exists(p) else None
@@ -199,63 +201,128 @@ def status_of(slug):
199
201
  return "planned"
200
202
 
201
203
  def deps_of(slug):
204
+ """Modules this one depends on.
205
+
206
+ Module docs use several shapes, all of which appear in real projects:
207
+ **Depends On:** none.
208
+ **Depends On:** Alpha, Beta
209
+ ### Depends On
210
+ | Module | What it provides |
211
+ | **Mandate** | ... |
212
+
213
+ Critically, a doc may also carry a "Used By" table listing its CONSUMERS.
214
+ Those must never be read as dependencies (that would invert the graph and
215
+ block a module on the work that depends on it).
216
+ """
202
217
  p = doc_path(slug)
203
218
  if not p:
204
219
  return []
205
- text = open(p, encoding="utf-8", errors="ignore").read()
206
- m = re.search(r"\*\*Depends On:\*\*(.*?)(?:\n##|\Z)", text, re.S | re.I)
207
- if not m:
208
- m = re.search(r"##\s*Dependencies(.*?)(?:\n##|\Z)", text, re.S | re.I)
209
- if not m:
220
+ lines = open(p, encoding="utf-8", errors="ignore").read().splitlines()
221
+
222
+ # Scope: the "## Dependencies" section if present, else the whole doc.
223
+ scope, sec = list(lines), None
224
+ for i, ln in enumerate(lines):
225
+ if re.match(r"^##\s+Dependencies\b", ln, re.I):
226
+ sec = i
227
+ break
228
+ if sec is not None:
229
+ scope = []
230
+ for ln in lines[sec + 1:]:
231
+ if re.match(r"^##\s+", ln):
232
+ break
233
+ scope.append(ln)
234
+
235
+ # Inside that scope, take only the "Depends On" sub-block.
236
+ block, in_deps = [], False
237
+ for ln in scope:
238
+ label = ln.strip()
239
+ heading = re.match(r"^#{2,4}\s*Depends On\b(.*)$", label, re.I)
240
+ bold = re.match(r"^\*\*Depends On:?\*\*(.*)$", label, re.I)
241
+ if heading or bold:
242
+ in_deps = True
243
+ rest = (heading.group(1) if heading else bold.group(1)).strip()
244
+ if rest:
245
+ block.append(rest)
246
+ continue
247
+ if in_deps and re.match(r"^#{2,4}\s", label):
248
+ in_deps = False # next sibling section, e.g. "### Used By"
249
+ continue
250
+ if in_deps:
251
+ block.append(label)
252
+
253
+ if not block:
210
254
  return []
211
- block = m.group(1)
212
- if re.search(r"\bnone\b", block, re.I):
255
+
256
+ # An explicit "none" anywhere in the Depends On block means: no dependencies.
257
+ joined = " ".join(block)
258
+ if re.search(r"\bnone\b", joined, re.I):
213
259
  return []
260
+
214
261
  found = []
215
- # Inline form: '**Depends On:** Alpha, Beta' or 'Alpha' (single line, no table)
216
- first = next((ln.strip() for ln in block.splitlines() if ln.strip()), "")
217
- if first and not first.startswith("|") and not first.startswith("-"):
218
- for part in re.split(r"[,;]", first):
219
- nm = part.strip().strip(chr(96) + "* ").rstrip(".")
220
- if nm and not nm.lower().startswith("none"):
221
- found.append(nm)
222
- for line in block.splitlines():
223
- line = line.strip()
224
- if not line.startswith("|"):
262
+ for ln in block:
263
+ if not ln:
225
264
  continue
226
- cells = [c.strip() for c in line.strip("|").split("|")]
227
- if not cells:
228
- continue
229
- name = cells[0].replace(chr(96), "").replace("*", "").strip()
230
- if not name or name.lower() in ("module", "modules") or set(name) <= set("-: "):
231
- continue
232
- found.append(name)
233
- # also allow "- Name" bullets
234
- for line in block.splitlines():
235
- line = line.strip()
236
- if line.startswith("- "):
237
- name = line[2:].split("—")[0].split(":")[0].strip().strip(chr(96) + "* ")
265
+ if ln.startswith("|"):
266
+ cells = [c.strip() for c in ln.strip("|").split("|")]
267
+ if not cells:
268
+ continue
269
+ name = cells[0].replace(chr(96), "").replace("*", "").strip()
270
+ if not name or name.lower() in ("module", "modules") or set(name) <= set("-: "):
271
+ continue
272
+ found.append(name)
273
+ elif ln.startswith("- "):
274
+ name = ln[2:].split("\u2014")[0].split(":")[0].strip().strip(chr(96) + "* ")
238
275
  if name and name.lower() != "none":
239
276
  found.append(name)
277
+ else:
278
+ # inline list: "Alpha, Beta"
279
+ for part in re.split(r"[,;]", ln):
280
+ nm = part.strip().strip(chr(96) + "* ").rstrip(".")
281
+ if nm and not nm.lower().startswith("none") and len(nm) < 60:
282
+ found.append(nm)
240
283
  return found
241
284
 
285
+
242
286
  def slugify(name):
243
287
  return re.sub(r"[^a-z0-9]+", "-", name.lower()).strip("-")
244
288
 
245
- batch_slugs = set(batch)
289
+ # Registry state: which modules have frozen contracts. Freeze is the gate for
290
+ # parallel work ("merge the contract-freeze issue first"), implementation the
291
+ # stricter also-accepted case. Loaded here because it needs slugify().
292
+ frozen = set()
293
+ try:
294
+ import json
295
+ _reg = json.load(open(registry_path, encoding="utf-8"))
296
+ for _mod, _entry in (_reg.get("epics") or {}).items():
297
+ if isinstance(_entry, dict) and _entry.get("contractFrozen"):
298
+ frozen.add(slugify(_mod))
299
+ except Exception:
300
+ frozen = set()
301
+
246
302
  problems = []
247
- for slug in batch:
303
+ for idx, slug in enumerate(batch):
248
304
  for dep_name in deps_of(slug):
249
305
  dep = slugify(dep_name)
250
306
  st = status_of(dep)
251
- if st in ("implemented",):
307
+ if st == "implemented":
308
+ continue
309
+ if dep in frozen:
252
310
  continue
253
- if dep in batch_slugs:
254
- problems.append(f"{slug}: depends on '{dep_name}' which is in this same batch — start it in an earlier batch")
311
+ if dep in batch and batch.index(dep) < idx:
312
+ continue # frozen earlier in this very run
313
+ if dep in batch:
314
+ problems.append(
315
+ f"{slug}: depends on '{dep_name}', which comes later in this batch — "
316
+ f"reorder so it starts first")
255
317
  elif st == "unknown":
256
- problems.append(f"{slug}: depends on '{dep_name}' which has no module doc under .pi/architecture/modules/")
318
+ problems.append(
319
+ f"{slug}: depends on '{dep_name}' with no module doc under "
320
+ f".pi/architecture/modules/")
257
321
  else:
258
- problems.append(f"{slug}: depends on '{dep_name}' ({st}) — not implemented yet")
322
+ problems.append(
323
+ f"{slug}: depends on '{dep_name}' ({st}) and its contracts are not "
324
+ f"frozen — merge its contract-freeze issue, then: "
325
+ f"bash .pi/scripts/epic-registry.sh freeze \"{dep_name}\" --frozen")
259
326
 
260
327
  if problems:
261
328
  print("\n".join(problems))