@iamu-dev/iamu 0.3.0-beta.0 → 0.3.0-beta.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.
- package/dist/bin.js +424 -44
- package/dist/commands/set-entity.d.ts +32 -5
- package/dist/index.js +424 -44
- package/dist/templates/skills/iamu-findings.md +55 -34
- package/dist/templates/skills/iamu-run.md +70 -50
- package/dist/templates/skills/iamu-setup.md +32 -33
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5459,10 +5459,20 @@ async function readTestability(projectRoot) {
|
|
|
5459
5459
|
body: parsed.body
|
|
5460
5460
|
};
|
|
5461
5461
|
}
|
|
5462
|
+
async function writeTestability(projectRoot, input, body) {
|
|
5463
|
+
const p = testabilityPath(projectRoot);
|
|
5464
|
+
const isLocalDoc = "frontmatter" in input && typeof input.frontmatter === "object";
|
|
5465
|
+
const fm = isLocalDoc ? input.frontmatter : input;
|
|
5466
|
+
const effectiveBody = body !== void 0 ? body : isLocalDoc ? input.body : "";
|
|
5467
|
+
const validated = testabilityFrontmatterSchema.parse(fm);
|
|
5468
|
+
const serialized = serializeFrontmatter(validated, effectiveBody);
|
|
5469
|
+
await atomicWriteFile(p, serialized);
|
|
5470
|
+
}
|
|
5462
5471
|
var init_testability2 = __esm({
|
|
5463
5472
|
"../../packages/local-store/dist/testability.js"() {
|
|
5464
5473
|
"use strict";
|
|
5465
5474
|
init_dist();
|
|
5475
|
+
init_atomic();
|
|
5466
5476
|
init_markdown();
|
|
5467
5477
|
init_paths();
|
|
5468
5478
|
}
|
|
@@ -8621,7 +8631,7 @@ function formatRefError(err) {
|
|
|
8621
8631
|
const dir = ENTITY_DIRS[err.missing_ref];
|
|
8622
8632
|
const hint = MISSING_REF_HINTS[err.missing_ref] ?? "";
|
|
8623
8633
|
if (!err.missing_slug) {
|
|
8624
|
-
const fieldHint = err.missing_ref === "capability" && err.entity_type === "outline" ?
|
|
8634
|
+
const fieldHint = err.missing_ref === "capability" && err.entity_type === "outline" ? `run \`iamu set outline ${err.entity_slug ?? "<slug>"} --capability <slug>\`` : `add a \`${err.missing_ref}:\` field to the file`;
|
|
8625
8635
|
return `${err.entity_type} ${err.entity_slug || err.entity_id}: ${err.missing_ref} slug is missing from frontmatter \u2014 ${fieldHint}`;
|
|
8626
8636
|
}
|
|
8627
8637
|
return `${err.entity_type} ${err.entity_slug || err.entity_id}: \`${err.missing_slug}\` not found in iamu/${dir}/${hint}`;
|
|
@@ -8635,7 +8645,7 @@ var init_refs = __esm({
|
|
|
8635
8645
|
init_sync_tracking();
|
|
8636
8646
|
init_walkthrough_mirror();
|
|
8637
8647
|
MISSING_REF_HINTS = {
|
|
8638
|
-
capability: " \u2014 create it with `iamu new capability` or
|
|
8648
|
+
capability: " \u2014 create it with `iamu new capability` or set with `iamu set outline <slug> --capability <slug>`",
|
|
8639
8649
|
outline: " \u2014 create it with `iamu new` or verify the slug matches a file in iamu/outlines/",
|
|
8640
8650
|
persona: " \u2014 create it with `iamu new persona` or check the slug",
|
|
8641
8651
|
scenario: " \u2014 verify the scenario exists locally with `iamu list scenarios`"
|
|
@@ -13581,8 +13591,8 @@ import { dirname as dirname3, join as join4, resolve as resolve2 } from "path";
|
|
|
13581
13591
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13582
13592
|
import chalk6 from "chalk";
|
|
13583
13593
|
function getVersion() {
|
|
13584
|
-
if ("0.3.0-beta.
|
|
13585
|
-
return "0.3.0-beta.
|
|
13594
|
+
if ("0.3.0-beta.1") {
|
|
13595
|
+
return "0.3.0-beta.1";
|
|
13586
13596
|
}
|
|
13587
13597
|
try {
|
|
13588
13598
|
const thisDir = dirname3(fileURLToPath2(import.meta.url));
|
|
@@ -20818,6 +20828,15 @@ function validateFile(filePath, raw, projectRoot) {
|
|
|
20818
20828
|
);
|
|
20819
20829
|
}
|
|
20820
20830
|
}
|
|
20831
|
+
if (type2 === "outline" && zodResult.success) {
|
|
20832
|
+
const fm = zodResult.data;
|
|
20833
|
+
if (!fm.primary_capability && !fm.capability) {
|
|
20834
|
+
result.warnings = result.warnings ?? [];
|
|
20835
|
+
result.warnings.push(
|
|
20836
|
+
`outline has no primary capability \u2014 sync will require one (run \`iamu set outline ${fm.slug ?? "<slug>"} --capability <slug>\`)`
|
|
20837
|
+
);
|
|
20838
|
+
}
|
|
20839
|
+
}
|
|
20821
20840
|
return result;
|
|
20822
20841
|
}
|
|
20823
20842
|
async function buildRepairLookups(projectRoot) {
|
|
@@ -21386,6 +21405,15 @@ async function newEntity(type2, opts) {
|
|
|
21386
21405
|
);
|
|
21387
21406
|
return;
|
|
21388
21407
|
}
|
|
21408
|
+
if (entityType === "outline" && !opts.capability) {
|
|
21409
|
+
try {
|
|
21410
|
+
const { entities } = await listEntities(projectRoot, "capability");
|
|
21411
|
+
if (entities.length === 1 && typeof entities[0].frontmatter.slug === "string") {
|
|
21412
|
+
opts.capability = entities[0].frontmatter.slug;
|
|
21413
|
+
}
|
|
21414
|
+
} catch {
|
|
21415
|
+
}
|
|
21416
|
+
}
|
|
21389
21417
|
const id = randomUUID10();
|
|
21390
21418
|
const frontmatter = defaultFrontmatter(entityType, id, slug, opts.name, opts);
|
|
21391
21419
|
const body = opts.body ?? (entityType === "outline" ? "" : opts.narrative) ?? "";
|
|
@@ -21504,6 +21532,42 @@ function applyChanges(type2, fm, opts) {
|
|
|
21504
21532
|
put("paths", paths);
|
|
21505
21533
|
}
|
|
21506
21534
|
if (opts.area !== void 0) put("area", opts.area || null);
|
|
21535
|
+
} else if (type2 === "outline") {
|
|
21536
|
+
if (opts.capability === false) {
|
|
21537
|
+
put("primary_capability", null);
|
|
21538
|
+
put("capability", null);
|
|
21539
|
+
} else if (opts.capability !== void 0) {
|
|
21540
|
+
put("primary_capability", opts.capability || null);
|
|
21541
|
+
put("capability", opts.capability || null);
|
|
21542
|
+
}
|
|
21543
|
+
if (opts.additionalCapabilities === false) {
|
|
21544
|
+
put("additional_capabilities", []);
|
|
21545
|
+
} else if (opts.additionalCapabilities !== void 0) {
|
|
21546
|
+
const caps = typeof opts.additionalCapabilities === "string" ? splitList(opts.additionalCapabilities) : Array.isArray(opts.additionalCapabilities) ? opts.additionalCapabilities : [];
|
|
21547
|
+
put("additional_capabilities", caps);
|
|
21548
|
+
}
|
|
21549
|
+
} else if (type2 === "testability") {
|
|
21550
|
+
if (opts.target !== void 0) put("target_url", opts.target || null);
|
|
21551
|
+
if (opts.devCommand !== void 0)
|
|
21552
|
+
put("dev_command", opts.devCommand || null);
|
|
21553
|
+
if (opts.authStrategy !== void 0)
|
|
21554
|
+
put("auth_strategy", opts.authStrategy || null);
|
|
21555
|
+
if (opts.access !== void 0) put("access", opts.access || null);
|
|
21556
|
+
if (opts.harnesses !== void 0) {
|
|
21557
|
+
put("harnesses", opts.harnesses ? splitList(opts.harnesses) : null);
|
|
21558
|
+
}
|
|
21559
|
+
if (opts.untestableBoundaries !== void 0) {
|
|
21560
|
+
put(
|
|
21561
|
+
"untestable_boundaries",
|
|
21562
|
+
opts.untestableBoundaries ? splitList(opts.untestableBoundaries) : null
|
|
21563
|
+
);
|
|
21564
|
+
}
|
|
21565
|
+
} else if (type2 === "context") {
|
|
21566
|
+
if (opts.domain !== void 0) put("domain", opts.domain || null);
|
|
21567
|
+
if (opts.industry !== void 0) put("industry", opts.industry || null);
|
|
21568
|
+
if (opts.jurisdiction !== void 0)
|
|
21569
|
+
put("jurisdiction", opts.jurisdiction || null);
|
|
21570
|
+
if (opts.notes !== void 0) put("notes", opts.notes || null);
|
|
21507
21571
|
}
|
|
21508
21572
|
return changed;
|
|
21509
21573
|
}
|
|
@@ -21519,6 +21583,15 @@ async function setEntity(type2, slug, opts) {
|
|
|
21519
21583
|
);
|
|
21520
21584
|
return;
|
|
21521
21585
|
}
|
|
21586
|
+
if (type2 !== "testability" && type2 !== "context" && !slug) {
|
|
21587
|
+
commandError(`A slug is required when setting a ${type2}.`, {
|
|
21588
|
+
...opts,
|
|
21589
|
+
code: "missing_slug",
|
|
21590
|
+
fix: `iamu set ${type2} <slug>`
|
|
21591
|
+
});
|
|
21592
|
+
return;
|
|
21593
|
+
}
|
|
21594
|
+
const effectiveSlug = slug || type2;
|
|
21522
21595
|
const foreign = Object.keys(FLAG_NAMES).filter(
|
|
21523
21596
|
(k) => !allowed.includes(k) && given(opts, k)
|
|
21524
21597
|
);
|
|
@@ -21528,7 +21601,7 @@ async function setEntity(type2, slug, opts) {
|
|
|
21528
21601
|
{
|
|
21529
21602
|
...opts,
|
|
21530
21603
|
code: "invalid_field_combination",
|
|
21531
|
-
fix: `iamu set ${type2} ${
|
|
21604
|
+
fix: `iamu set ${type2} ${effectiveSlug} ${FLAG_NAMES[allowed[0]]} ...`
|
|
21532
21605
|
}
|
|
21533
21606
|
);
|
|
21534
21607
|
return;
|
|
@@ -21569,7 +21642,38 @@ async function setEntity(type2, slug, opts) {
|
|
|
21569
21642
|
const allowedPatchKeys = {
|
|
21570
21643
|
scenario: ["entry", "entry_path", "target", "target_url", "state"],
|
|
21571
21644
|
persona: ["access"],
|
|
21572
|
-
capability: ["paths", "addPath", "removePath", "area"]
|
|
21645
|
+
capability: ["paths", "addPath", "removePath", "area"],
|
|
21646
|
+
outline: [
|
|
21647
|
+
"capability",
|
|
21648
|
+
"primary_capability",
|
|
21649
|
+
"additional_capabilities",
|
|
21650
|
+
"additionalCapabilities"
|
|
21651
|
+
],
|
|
21652
|
+
testability: [
|
|
21653
|
+
"target",
|
|
21654
|
+
"target_url",
|
|
21655
|
+
"devCommand",
|
|
21656
|
+
"dev_command",
|
|
21657
|
+
"authStrategy",
|
|
21658
|
+
"auth_strategy",
|
|
21659
|
+
"access",
|
|
21660
|
+
"harnesses",
|
|
21661
|
+
"untestableBoundaries",
|
|
21662
|
+
"untestable_boundaries",
|
|
21663
|
+
"body"
|
|
21664
|
+
],
|
|
21665
|
+
context: [
|
|
21666
|
+
"domain",
|
|
21667
|
+
"industry",
|
|
21668
|
+
"jurisdiction",
|
|
21669
|
+
"notes",
|
|
21670
|
+
"description",
|
|
21671
|
+
"name",
|
|
21672
|
+
"governed_by",
|
|
21673
|
+
"actors",
|
|
21674
|
+
"terminology",
|
|
21675
|
+
"body"
|
|
21676
|
+
]
|
|
21573
21677
|
};
|
|
21574
21678
|
const foreignPatchKeys = Object.keys(parsed).filter(
|
|
21575
21679
|
(k) => !allowedPatchKeys[type2]?.includes(k)
|
|
@@ -21628,6 +21732,65 @@ async function setEntity(type2, slug, opts) {
|
|
|
21628
21732
|
if (effectiveOpts.area === void 0 && parsed.area !== void 0) {
|
|
21629
21733
|
effectiveOpts.area = parsed.area === null || parsed.area === false ? false : String(parsed.area);
|
|
21630
21734
|
}
|
|
21735
|
+
} else if (type2 === "outline") {
|
|
21736
|
+
if (effectiveOpts.capability === void 0 && (parsed.capability !== void 0 || parsed.primary_capability !== void 0)) {
|
|
21737
|
+
const v = parsed.capability ?? parsed.primary_capability;
|
|
21738
|
+
effectiveOpts.capability = v === null || v === false ? false : String(v);
|
|
21739
|
+
}
|
|
21740
|
+
if (effectiveOpts.additionalCapabilities === void 0 && (parsed.additionalCapabilities !== void 0 || parsed.additional_capabilities !== void 0)) {
|
|
21741
|
+
const v = parsed.additionalCapabilities ?? parsed.additional_capabilities;
|
|
21742
|
+
effectiveOpts.additionalCapabilities = v === null || v === false ? false : Array.isArray(v) ? v.join(",") : String(v);
|
|
21743
|
+
}
|
|
21744
|
+
} else if (type2 === "testability") {
|
|
21745
|
+
if (effectiveOpts.target === void 0 && (parsed.target !== void 0 || parsed.target_url !== void 0)) {
|
|
21746
|
+
const v = parsed.target ?? parsed.target_url;
|
|
21747
|
+
effectiveOpts.target = v === null || v === false ? false : String(v);
|
|
21748
|
+
}
|
|
21749
|
+
if (effectiveOpts.devCommand === void 0 && (parsed.devCommand !== void 0 || parsed.dev_command !== void 0)) {
|
|
21750
|
+
const v = parsed.devCommand ?? parsed.dev_command;
|
|
21751
|
+
effectiveOpts.devCommand = v === null || v === false ? false : String(v);
|
|
21752
|
+
}
|
|
21753
|
+
if (effectiveOpts.authStrategy === void 0 && (parsed.authStrategy !== void 0 || parsed.auth_strategy !== void 0)) {
|
|
21754
|
+
const v = parsed.authStrategy ?? parsed.auth_strategy;
|
|
21755
|
+
effectiveOpts.authStrategy = v === null || v === false ? false : String(v);
|
|
21756
|
+
}
|
|
21757
|
+
if (effectiveOpts.access === void 0 && parsed.access !== void 0) {
|
|
21758
|
+
effectiveOpts.access = parsed.access === null || parsed.access === false ? false : String(parsed.access);
|
|
21759
|
+
}
|
|
21760
|
+
if (effectiveOpts.harnesses === void 0 && parsed.harnesses !== void 0) {
|
|
21761
|
+
effectiveOpts.harnesses = parsed.harnesses === null || parsed.harnesses === false ? false : Array.isArray(parsed.harnesses) ? parsed.harnesses.join(",") : String(parsed.harnesses);
|
|
21762
|
+
}
|
|
21763
|
+
if (effectiveOpts.untestableBoundaries === void 0 && (parsed.untestableBoundaries !== void 0 || parsed.untestable_boundaries !== void 0)) {
|
|
21764
|
+
const b = parsed.untestableBoundaries ?? parsed.untestable_boundaries;
|
|
21765
|
+
effectiveOpts.untestableBoundaries = b === null || b === false ? false : Array.isArray(b) ? b.join(",") : String(b);
|
|
21766
|
+
}
|
|
21767
|
+
if (effectiveOpts.body === void 0 && parsed.body !== void 0) {
|
|
21768
|
+
effectiveOpts.body = String(parsed.body);
|
|
21769
|
+
}
|
|
21770
|
+
} else if (type2 === "context") {
|
|
21771
|
+
if (effectiveOpts.domain === void 0 && parsed.domain !== void 0) {
|
|
21772
|
+
effectiveOpts.domain = parsed.domain === null || parsed.domain === false ? false : String(parsed.domain);
|
|
21773
|
+
}
|
|
21774
|
+
if (effectiveOpts.industry === void 0 && parsed.industry !== void 0) {
|
|
21775
|
+
effectiveOpts.industry = parsed.industry === null || parsed.industry === false ? false : String(parsed.industry);
|
|
21776
|
+
}
|
|
21777
|
+
if (effectiveOpts.jurisdiction === void 0 && parsed.jurisdiction !== void 0) {
|
|
21778
|
+
effectiveOpts.jurisdiction = parsed.jurisdiction === null || parsed.jurisdiction === false ? false : String(parsed.jurisdiction);
|
|
21779
|
+
}
|
|
21780
|
+
if (effectiveOpts.notes === void 0 && parsed.notes !== void 0) {
|
|
21781
|
+
effectiveOpts.notes = parsed.notes === null || parsed.notes === false ? false : String(parsed.notes);
|
|
21782
|
+
}
|
|
21783
|
+
if (effectiveOpts.description === void 0 && parsed.description !== void 0) {
|
|
21784
|
+
effectiveOpts.description = parsed.description === null || parsed.description === false ? false : String(parsed.description);
|
|
21785
|
+
}
|
|
21786
|
+
if (effectiveOpts.name === void 0 && parsed.name !== void 0) {
|
|
21787
|
+
effectiveOpts.name = parsed.name === null || parsed.name === false ? false : String(parsed.name);
|
|
21788
|
+
}
|
|
21789
|
+
if (effectiveOpts.body === void 0 && parsed.body !== void 0) {
|
|
21790
|
+
effectiveOpts.body = String(parsed.body);
|
|
21791
|
+
} else if (effectiveOpts.body === void 0 && effectiveOpts.description !== void 0) {
|
|
21792
|
+
effectiveOpts.body = effectiveOpts.description ? String(effectiveOpts.description) : "";
|
|
21793
|
+
}
|
|
21631
21794
|
}
|
|
21632
21795
|
}
|
|
21633
21796
|
if (!allowed.some((k) => given(effectiveOpts, k))) {
|
|
@@ -21636,11 +21799,112 @@ async function setEntity(type2, slug, opts) {
|
|
|
21636
21799
|
{
|
|
21637
21800
|
...opts,
|
|
21638
21801
|
code: "nothing_to_set",
|
|
21639
|
-
fix: `iamu set ${type2} ${
|
|
21802
|
+
fix: `iamu set ${type2}${type2 === "testability" || type2 === "context" ? "" : ` ${effectiveSlug}`} ${FLAG_NAMES[allowed[0]]} ...`
|
|
21640
21803
|
}
|
|
21641
21804
|
);
|
|
21642
21805
|
return;
|
|
21643
21806
|
}
|
|
21807
|
+
if (type2 === "testability") {
|
|
21808
|
+
const doc = await readTestability(projectRoot) ?? {
|
|
21809
|
+
frontmatter: {
|
|
21810
|
+
schema_version: 1,
|
|
21811
|
+
status: "draft",
|
|
21812
|
+
target_url: "http://localhost:3000"
|
|
21813
|
+
},
|
|
21814
|
+
body: ""
|
|
21815
|
+
};
|
|
21816
|
+
const fm2 = { ...doc.frontmatter };
|
|
21817
|
+
const changed2 = applyChanges(type2, fm2, effectiveOpts);
|
|
21818
|
+
let body = doc.body;
|
|
21819
|
+
if (effectiveOpts.body !== void 0) {
|
|
21820
|
+
body = effectiveOpts.body;
|
|
21821
|
+
changed2.push("body");
|
|
21822
|
+
}
|
|
21823
|
+
const writtenPath2 = testabilityPath(projectRoot);
|
|
21824
|
+
try {
|
|
21825
|
+
await writeTestability(
|
|
21826
|
+
projectRoot,
|
|
21827
|
+
fm2,
|
|
21828
|
+
body
|
|
21829
|
+
);
|
|
21830
|
+
} catch (err) {
|
|
21831
|
+
const message = err instanceof ZodError2 ? err.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ") : err instanceof Error ? err.message : String(err);
|
|
21832
|
+
commandError(`Could not set testability: ${message}`, {
|
|
21833
|
+
...opts,
|
|
21834
|
+
code: "testability_write_error",
|
|
21835
|
+
fix: "iamu set testability --target <url>"
|
|
21836
|
+
});
|
|
21837
|
+
return;
|
|
21838
|
+
}
|
|
21839
|
+
if (opts.json) {
|
|
21840
|
+
console.log(
|
|
21841
|
+
JSON.stringify({
|
|
21842
|
+
slug: "testability",
|
|
21843
|
+
type: "testability",
|
|
21844
|
+
path: writtenPath2,
|
|
21845
|
+
changed: changed2
|
|
21846
|
+
})
|
|
21847
|
+
);
|
|
21848
|
+
return;
|
|
21849
|
+
}
|
|
21850
|
+
console.log();
|
|
21851
|
+
console.log(
|
|
21852
|
+
` ${symbols.success} Updated testability: ${changed2.join(", ")}`
|
|
21853
|
+
);
|
|
21854
|
+
console.log(` ${chalk28.dim("path:")} ${writtenPath2}`);
|
|
21855
|
+
console.log();
|
|
21856
|
+
return;
|
|
21857
|
+
}
|
|
21858
|
+
if (type2 === "context") {
|
|
21859
|
+
const doc = await readContext(projectRoot) ?? {
|
|
21860
|
+
frontmatter: {
|
|
21861
|
+
schema_version: SCHEMA_VERSION,
|
|
21862
|
+
status: "draft"
|
|
21863
|
+
},
|
|
21864
|
+
notes_body: ""
|
|
21865
|
+
};
|
|
21866
|
+
const fm2 = { ...doc.frontmatter };
|
|
21867
|
+
const changed2 = applyChanges(type2, fm2, effectiveOpts);
|
|
21868
|
+
let body = doc.notes_body;
|
|
21869
|
+
if (effectiveOpts.body !== void 0) {
|
|
21870
|
+
body = effectiveOpts.body;
|
|
21871
|
+
changed2.push("body");
|
|
21872
|
+
} else if (effectiveOpts.description !== void 0) {
|
|
21873
|
+
body = effectiveOpts.description ? String(effectiveOpts.description) : "";
|
|
21874
|
+
changed2.push("body");
|
|
21875
|
+
}
|
|
21876
|
+
const writtenPath2 = contextPath(projectRoot);
|
|
21877
|
+
try {
|
|
21878
|
+
await writeContext(projectRoot, {
|
|
21879
|
+
frontmatter: fm2,
|
|
21880
|
+
notes_body: body
|
|
21881
|
+
});
|
|
21882
|
+
} catch (err) {
|
|
21883
|
+
const message = err instanceof ZodError2 ? err.issues.map((i) => `${i.path.join(".") || "root"}: ${i.message}`).join("; ") : err instanceof Error ? err.message : String(err);
|
|
21884
|
+
commandError(`Could not set context: ${message}`, {
|
|
21885
|
+
...opts,
|
|
21886
|
+
code: "context_write_error",
|
|
21887
|
+
fix: "iamu set context --domain <domain>"
|
|
21888
|
+
});
|
|
21889
|
+
return;
|
|
21890
|
+
}
|
|
21891
|
+
if (opts.json) {
|
|
21892
|
+
console.log(
|
|
21893
|
+
JSON.stringify({
|
|
21894
|
+
slug: "context",
|
|
21895
|
+
type: "context",
|
|
21896
|
+
path: writtenPath2,
|
|
21897
|
+
changed: changed2
|
|
21898
|
+
})
|
|
21899
|
+
);
|
|
21900
|
+
return;
|
|
21901
|
+
}
|
|
21902
|
+
console.log();
|
|
21903
|
+
console.log(` ${symbols.success} Updated context: ${changed2.join(", ")}`);
|
|
21904
|
+
console.log(` ${chalk28.dim("path:")} ${writtenPath2}`);
|
|
21905
|
+
console.log();
|
|
21906
|
+
return;
|
|
21907
|
+
}
|
|
21644
21908
|
if (type2 === "capability") {
|
|
21645
21909
|
const candidatePaths = [
|
|
21646
21910
|
...typeof effectiveOpts.paths === "string" ? splitList(effectiveOpts.paths) : [],
|
|
@@ -21653,7 +21917,7 @@ async function setEntity(type2, slug, opts) {
|
|
|
21653
21917
|
{
|
|
21654
21918
|
...opts,
|
|
21655
21919
|
code: "invalid_route_prefix",
|
|
21656
|
-
fix: `iamu set ${type2} ${
|
|
21920
|
+
fix: `iamu set ${type2} ${effectiveSlug} --paths /${invalid[0]?.replace(/^\/+/, "") || ""}`
|
|
21657
21921
|
}
|
|
21658
21922
|
);
|
|
21659
21923
|
return;
|
|
@@ -21726,7 +21990,25 @@ var init_set_entity = __esm({
|
|
|
21726
21990
|
"state"
|
|
21727
21991
|
],
|
|
21728
21992
|
persona: ["access"],
|
|
21729
|
-
capability: ["paths", "addPath", "removePath", "area"]
|
|
21993
|
+
capability: ["paths", "addPath", "removePath", "area"],
|
|
21994
|
+
outline: ["capability", "additionalCapabilities"],
|
|
21995
|
+
testability: [
|
|
21996
|
+
"target",
|
|
21997
|
+
"devCommand",
|
|
21998
|
+
"authStrategy",
|
|
21999
|
+
"access",
|
|
22000
|
+
"harnesses",
|
|
22001
|
+
"untestableBoundaries",
|
|
22002
|
+
"body"
|
|
22003
|
+
],
|
|
22004
|
+
context: [
|
|
22005
|
+
"domain",
|
|
22006
|
+
"industry",
|
|
22007
|
+
"jurisdiction",
|
|
22008
|
+
"notes",
|
|
22009
|
+
"description",
|
|
22010
|
+
"body"
|
|
22011
|
+
]
|
|
21730
22012
|
};
|
|
21731
22013
|
FLAG_NAMES = {
|
|
21732
22014
|
entry: "--entry",
|
|
@@ -21738,7 +22020,20 @@ var init_set_entity = __esm({
|
|
|
21738
22020
|
paths: "--paths",
|
|
21739
22021
|
addPath: "--add-path",
|
|
21740
22022
|
removePath: "--remove-path",
|
|
21741
|
-
area: "--area"
|
|
22023
|
+
area: "--area",
|
|
22024
|
+
capability: "--capability",
|
|
22025
|
+
additionalCapabilities: "--additional-capabilities",
|
|
22026
|
+
devCommand: "--dev-command",
|
|
22027
|
+
authStrategy: "--auth-strategy",
|
|
22028
|
+
harnesses: "--harnesses",
|
|
22029
|
+
untestableBoundaries: "--untestable-boundaries",
|
|
22030
|
+
domain: "--domain",
|
|
22031
|
+
industry: "--industry",
|
|
22032
|
+
jurisdiction: "--jurisdiction",
|
|
22033
|
+
notes: "--notes",
|
|
22034
|
+
description: "--description",
|
|
22035
|
+
name: "--name",
|
|
22036
|
+
body: "--body"
|
|
21742
22037
|
};
|
|
21743
22038
|
}
|
|
21744
22039
|
});
|
|
@@ -22999,7 +23294,7 @@ __export(instructions_walk_exports, {
|
|
|
22999
23294
|
revisitSection: () => revisitSection,
|
|
23000
23295
|
viewportLine: () => viewportLine
|
|
23001
23296
|
});
|
|
23002
|
-
import { existsSync as existsSync16, readFileSync as readFileSync9 } from "fs";
|
|
23297
|
+
import { existsSync as existsSync16, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "fs";
|
|
23003
23298
|
import { join as join9 } from "path";
|
|
23004
23299
|
import chalk31 from "chalk";
|
|
23005
23300
|
function selfCommand() {
|
|
@@ -23386,8 +23681,17 @@ async function instructionsWalk(opts) {
|
|
|
23386
23681
|
state: sfm.state ?? null,
|
|
23387
23682
|
context: contextYml,
|
|
23388
23683
|
untestableBoundaries
|
|
23389
|
-
}) : null
|
|
23684
|
+
}) : null,
|
|
23685
|
+
walker_prompt_path: null
|
|
23390
23686
|
};
|
|
23687
|
+
if (runDirPath && result.walker_prompt) {
|
|
23688
|
+
try {
|
|
23689
|
+
const promptPath = join9(runDirPath, "walker_prompt.txt");
|
|
23690
|
+
writeFileSync4(promptPath, result.walker_prompt, "utf-8");
|
|
23691
|
+
result.walker_prompt_path = promptPath;
|
|
23692
|
+
} catch {
|
|
23693
|
+
}
|
|
23694
|
+
}
|
|
23391
23695
|
if (opts.json) {
|
|
23392
23696
|
console.log(JSON.stringify(result, null, 2));
|
|
23393
23697
|
return;
|
|
@@ -24408,13 +24712,25 @@ async function evaluateRecord(runId, opts) {
|
|
|
24408
24712
|
});
|
|
24409
24713
|
return;
|
|
24410
24714
|
}
|
|
24715
|
+
const defaultVerdictsPath = path34.join(runDirPath, "verdicts.json");
|
|
24411
24716
|
if (!opts.file && !opts.data) {
|
|
24412
|
-
|
|
24413
|
-
|
|
24414
|
-
|
|
24415
|
-
|
|
24416
|
-
}
|
|
24417
|
-
|
|
24717
|
+
let hasExisting = false;
|
|
24718
|
+
try {
|
|
24719
|
+
await fs32.access(defaultVerdictsPath);
|
|
24720
|
+
hasExisting = true;
|
|
24721
|
+
} catch {
|
|
24722
|
+
hasExisting = false;
|
|
24723
|
+
}
|
|
24724
|
+
if (hasExisting) {
|
|
24725
|
+
opts.file = defaultVerdictsPath;
|
|
24726
|
+
} else {
|
|
24727
|
+
commandError("Either --file <path> or --data <json> is required", {
|
|
24728
|
+
...opts,
|
|
24729
|
+
code: "missing_verdicts_input",
|
|
24730
|
+
fix: `iamu evaluate-record ${runId} --data '<json>'`
|
|
24731
|
+
});
|
|
24732
|
+
return;
|
|
24733
|
+
}
|
|
24418
24734
|
}
|
|
24419
24735
|
let parsedFile;
|
|
24420
24736
|
try {
|
|
@@ -25371,13 +25687,25 @@ async function matchRecord(runId, opts) {
|
|
|
25371
25687
|
});
|
|
25372
25688
|
const manifest = await completedManifest2(runDirPath, runId, opts);
|
|
25373
25689
|
if (!manifest) return;
|
|
25690
|
+
const defaultMatchesPath = path36.join(runDirPath, "matches.json");
|
|
25374
25691
|
if (!opts.file && !opts.data) {
|
|
25375
|
-
|
|
25376
|
-
|
|
25377
|
-
|
|
25378
|
-
|
|
25379
|
-
}
|
|
25380
|
-
|
|
25692
|
+
let hasExisting = false;
|
|
25693
|
+
try {
|
|
25694
|
+
await fs34.access(defaultMatchesPath);
|
|
25695
|
+
hasExisting = true;
|
|
25696
|
+
} catch {
|
|
25697
|
+
hasExisting = false;
|
|
25698
|
+
}
|
|
25699
|
+
if (hasExisting) {
|
|
25700
|
+
opts.file = defaultMatchesPath;
|
|
25701
|
+
} else {
|
|
25702
|
+
commandError("Either --file <path> or --data <json> is required", {
|
|
25703
|
+
...opts,
|
|
25704
|
+
code: "missing_matches_input",
|
|
25705
|
+
fix: `iamu match-record ${runId} --data '<json>'`
|
|
25706
|
+
});
|
|
25707
|
+
return;
|
|
25708
|
+
}
|
|
25381
25709
|
}
|
|
25382
25710
|
let answer;
|
|
25383
25711
|
try {
|
|
@@ -25811,12 +26139,12 @@ function registerProjectCommands(program) {
|
|
|
25811
26139
|
await newEntity2(type2, opts);
|
|
25812
26140
|
}
|
|
25813
26141
|
);
|
|
25814
|
-
program.command("set <type>
|
|
25815
|
-
"Change how an entity is staged: a scenario's start path, target and starting state, a persona's access key, a capability's routes (scenario, persona, capability)"
|
|
26142
|
+
program.command("set <type> [slug]").helpGroup("Project:").description(
|
|
26143
|
+
"Change how an entity is staged: a scenario's start path, target and starting state, a persona's access key, a capability's routes, or project testability / context (scenario, persona, capability, testability, context)"
|
|
25816
26144
|
).option(
|
|
25817
26145
|
"--entry <path>",
|
|
25818
26146
|
"Where the walk starts, as a path on the product (scenario)"
|
|
25819
|
-
).option("--no-entry", "Clear the start path (scenario)").option("--target <url>", "Default target URL (scenario)").option("--no-target", "Clear the default target URL (scenario)").option(
|
|
26147
|
+
).option("--no-entry", "Clear the start path (scenario)").option("--target <url>", "Default target URL (scenario, testability)").option("--no-target", "Clear the default target URL (scenario)").option(
|
|
25820
26148
|
"--state-description <text>",
|
|
25821
26149
|
"What the world must contain, in domain words (scenario)"
|
|
25822
26150
|
).option(
|
|
@@ -25824,8 +26152,8 @@ function registerProjectCommands(program) {
|
|
|
25824
26152
|
"How the walker picks the closest record when the exact one is missing (scenario)"
|
|
25825
26153
|
).option("--no-state", "Clear the starting state (scenario)").option(
|
|
25826
26154
|
"--access <key>",
|
|
25827
|
-
"Account, role or switcher key this persona uses (persona)"
|
|
25828
|
-
).option("--no-access", "Clear the access key (persona)").option(
|
|
26155
|
+
"Account, role or switcher key this persona uses (persona, testability)"
|
|
26156
|
+
).option("--no-access", "Clear the access key (persona, testability)").option(
|
|
25829
26157
|
"--paths <paths>",
|
|
25830
26158
|
"Route prefixes, comma-separated; replaces the list (capability)"
|
|
25831
26159
|
).option("--no-paths", "Clear route prefixes (capability)").option(
|
|
@@ -25836,12 +26164,27 @@ function registerProjectCommands(program) {
|
|
|
25836
26164
|
"--remove-path <path>",
|
|
25837
26165
|
"Remove a route prefix (capability, repeatable)",
|
|
25838
26166
|
(val, prev = []) => [...prev, val]
|
|
25839
|
-
).option("--area <name>", "Visual grouping category (capability)").option("--no-area", "Clear the area (capability)").option(
|
|
26167
|
+
).option("--area <name>", "Visual grouping category (capability)").option("--no-area", "Clear the area (capability)").option("--capability <slug>", "Primary capability slug (outline)").option("--no-capability", "Clear primary capability (outline)").option(
|
|
26168
|
+
"--additional-capabilities <slugs>",
|
|
26169
|
+
"Secondary capability slugs, comma-separated (outline)"
|
|
26170
|
+
).option(
|
|
26171
|
+
"--no-additional-capabilities",
|
|
26172
|
+
"Clear secondary capabilities (outline)"
|
|
26173
|
+
).option("--dev-command <cmd>", "Dev startup command (testability)").option("--no-dev-command", "Clear dev startup command (testability)").option("--auth-strategy <strategy>", "Auth strategy (testability)").option("--no-auth-strategy", "Clear auth strategy (testability)").option(
|
|
26174
|
+
"--harnesses <list>",
|
|
26175
|
+
"Mock frameworks or seed scripts, comma-separated (testability)"
|
|
26176
|
+
).option("--no-harnesses", "Clear harnesses (testability)").option(
|
|
26177
|
+
"--untestable-boundaries <list>",
|
|
26178
|
+
"Forbidden external endpoints, comma-separated (testability)"
|
|
26179
|
+
).option(
|
|
26180
|
+
"--no-untestable-boundaries",
|
|
26181
|
+
"Clear untestable boundaries (testability)"
|
|
26182
|
+
).option("--domain <text>", "Domain name (context)").option("--industry <text>", "Industry category (context)").option("--jurisdiction <text>", "Jurisdiction or region (context)").option("--notes <text>", "Orientation notes (context)").option("--description <text>", "Project description (context)").option("--name <text>", "Project name (context)").option("--body <text>", "Markdown narrative body (testability, context)").option(
|
|
25840
26183
|
"--file <path>",
|
|
25841
26184
|
"JSON patch file to apply staging fields (or - for stdin)"
|
|
25842
26185
|
).option("--json", "Output as JSON").addHelpText(
|
|
25843
26186
|
"after",
|
|
25844
|
-
'\nWhat a scenario is about (narrative, tension, human tests, brief) is not set here.\n\nExamples:\n $ iamu set scenario maria--handoff --entry /incidents --state-description "Five open incidents at one site"\n $ iamu set persona maria --access coordinator@site-a.test\n $ iamu set capability team-access --add-path /team\n $ iamu set scenario maria--handoff --file patch.json'
|
|
26187
|
+
'\nWhat a scenario is about (narrative, tension, human tests, brief) is not set here.\n\nExamples:\n $ iamu set scenario maria--handoff --entry /incidents --state-description "Five open incidents at one site"\n $ iamu set persona maria --access coordinator@site-a.test\n $ iamu set outline shift-handoff --capability incident-reporting\n $ iamu set capability team-access --add-path /team\n $ iamu set testability --target http://localhost:5173 --dev-command "./dev" --auth-strategy dev_switcher\n $ iamu set context --domain "Workplace safety" --industry "Manufacturing" --description "..."\n $ iamu set scenario maria--handoff --file patch.json'
|
|
25845
26188
|
).action(
|
|
25846
26189
|
async (type2, slug, opts) => {
|
|
25847
26190
|
const { setEntity: setEntity2 } = await Promise.resolve().then(() => (init_set_entity(), set_entity_exports));
|
|
@@ -25960,41 +26303,65 @@ function registerWalkthroughCommands(program) {
|
|
|
25960
26303
|
"--surface <text>",
|
|
25961
26304
|
`"browse" (default) for iamu browse, or a description of your own browser tool \u2014 becomes the walker prompt's Driving surface section`
|
|
25962
26305
|
).option("--json", "Output as JSON").action(
|
|
25963
|
-
async (phase, slug, opts) => {
|
|
26306
|
+
async (phase, slug, opts, cmd) => {
|
|
26307
|
+
const effectiveOpts = {
|
|
26308
|
+
...cmd.optsWithGlobals(),
|
|
26309
|
+
...opts
|
|
26310
|
+
};
|
|
25964
26311
|
const { instructions: instructions2 } = await Promise.resolve().then(() => (init_instructions(), instructions_exports));
|
|
25965
|
-
await instructions2(phase, slug,
|
|
26312
|
+
await instructions2(phase, slug, effectiveOpts);
|
|
25966
26313
|
}
|
|
25967
26314
|
);
|
|
25968
26315
|
instrCmd.command("walk [scenario-slug]").description("Compose walking prompt from scenario + persona + outline").option("--scenario <slug>", "Scenario slug (default: active scenario)").option("--run <run-id>", "Run ID (resolves target URL from manifest)").option(
|
|
25969
26316
|
"--surface <text>",
|
|
25970
26317
|
`"browse" (default) for iamu browse, or a description of your own browser tool \u2014 becomes the walker prompt's Driving surface section`
|
|
25971
26318
|
).option("--json", "Output as JSON").action(
|
|
25972
|
-
async (scenarioSlug, opts) => {
|
|
26319
|
+
async (scenarioSlug, opts, cmd) => {
|
|
26320
|
+
const effectiveOpts = {
|
|
26321
|
+
...cmd.parent?.opts(),
|
|
26322
|
+
...cmd.optsWithGlobals(),
|
|
26323
|
+
...opts
|
|
26324
|
+
};
|
|
25973
26325
|
const { instructionsWalk: instructionsWalk2 } = await Promise.resolve().then(() => (init_instructions_walk(), instructions_walk_exports));
|
|
25974
26326
|
await instructionsWalk2({
|
|
25975
|
-
...
|
|
25976
|
-
scenario: scenarioSlug ??
|
|
26327
|
+
...effectiveOpts,
|
|
26328
|
+
scenario: scenarioSlug ?? effectiveOpts.scenario
|
|
25977
26329
|
});
|
|
25978
26330
|
}
|
|
25979
26331
|
);
|
|
25980
26332
|
instrCmd.command("stage [scenario-slug]").description(
|
|
25981
26333
|
"Dynamic staging instructions: persona, outline, tension, boundaries"
|
|
25982
26334
|
).option("--json", "Output as JSON").action(
|
|
25983
|
-
async (scenarioSlug, opts) => {
|
|
26335
|
+
async (scenarioSlug, opts, cmd) => {
|
|
26336
|
+
const effectiveOpts = {
|
|
26337
|
+
...cmd.parent?.opts(),
|
|
26338
|
+
...cmd.optsWithGlobals(),
|
|
26339
|
+
...opts
|
|
26340
|
+
};
|
|
25984
26341
|
const { instructionsStage: instructionsStage2 } = await Promise.resolve().then(() => (init_instructions(), instructions_exports));
|
|
25985
|
-
await instructionsStage2(scenarioSlug,
|
|
26342
|
+
await instructionsStage2(scenarioSlug, effectiveOpts);
|
|
25986
26343
|
}
|
|
25987
26344
|
);
|
|
25988
|
-
instrCmd.command("setup").description("Dynamic project setup instructions & prerequisite checks").option("--json", "Output as JSON").action(async (opts) => {
|
|
26345
|
+
instrCmd.command("setup").description("Dynamic project setup instructions & prerequisite checks").option("--json", "Output as JSON").action(async (opts, cmd) => {
|
|
26346
|
+
const effectiveOpts = {
|
|
26347
|
+
...cmd.parent?.opts(),
|
|
26348
|
+
...cmd.optsWithGlobals(),
|
|
26349
|
+
...opts
|
|
26350
|
+
};
|
|
25989
26351
|
const { instructionsSetup: instructionsSetup2 } = await Promise.resolve().then(() => (init_instructions(), instructions_exports));
|
|
25990
|
-
await instructionsSetup2(
|
|
26352
|
+
await instructionsSetup2(effectiveOpts);
|
|
25991
26353
|
});
|
|
25992
26354
|
instrCmd.command("triage [run-or-scenario-slug]").description(
|
|
25993
26355
|
"Dynamic triage instructions: finding triage, confirmation, dismissal guidance"
|
|
25994
26356
|
).option("--run <run-id>", "Run ID to triage findings for").option("--json", "Output as JSON").action(
|
|
25995
|
-
async (slug, opts) => {
|
|
26357
|
+
async (slug, opts, cmd) => {
|
|
26358
|
+
const effectiveOpts = {
|
|
26359
|
+
...cmd.parent?.opts(),
|
|
26360
|
+
...cmd.optsWithGlobals(),
|
|
26361
|
+
...opts
|
|
26362
|
+
};
|
|
25996
26363
|
const { instructionsTriage: instructionsTriage2 } = await Promise.resolve().then(() => (init_instructions(), instructions_exports));
|
|
25997
|
-
await instructionsTriage2(slug,
|
|
26364
|
+
await instructionsTriage2(slug, effectiveOpts);
|
|
25998
26365
|
}
|
|
25999
26366
|
);
|
|
26000
26367
|
program.command("browse <command> [args...]").helpGroup("Walkthrough:").description(
|
|
@@ -26132,7 +26499,14 @@ function registerWalkthroughCommands(program) {
|
|
|
26132
26499
|
);
|
|
26133
26500
|
program.command("match-record <run-id>").helpGroup("Walkthrough:").description(
|
|
26134
26501
|
"Record finding matches and re-derive the run's since-last-run delta"
|
|
26135
|
-
).option("--file <path>", "Path to matches JSON file (or - for stdin)").option("--data <json>", "Inline matches JSON string").option("--json", "Output match results as JSON").
|
|
26502
|
+
).option("--file <path>", "Path to matches JSON file (or - for stdin)").option("--data <json>", "Inline matches JSON string").option("--json", "Output match results as JSON").addHelpText(
|
|
26503
|
+
"after",
|
|
26504
|
+
`
|
|
26505
|
+
Examples:
|
|
26506
|
+
$ iamu match-record <run-id> --data '{"matches":[]}'
|
|
26507
|
+
$ iamu match-record <run-id> --file matches.json
|
|
26508
|
+
$ iamu match-record <run-id> --json`
|
|
26509
|
+
).action(
|
|
26136
26510
|
async (runId, opts) => {
|
|
26137
26511
|
const { matchRecord: matchRecord2 } = await Promise.resolve().then(() => (init_match(), match_exports));
|
|
26138
26512
|
await matchRecord2(runId, opts);
|
|
@@ -26146,7 +26520,13 @@ function registerWalkthroughCommands(program) {
|
|
|
26146
26520
|
);
|
|
26147
26521
|
program.command("evaluate-record <run-id>").helpGroup("Walkthrough:").description("Record evaluation verdicts into the run's verdicts.json").option("--file <path>", "Path to verdicts JSON file (or - for stdin)").option("--data <json>", "Inline verdicts JSON string").option("--json", "Output summary as JSON").option("-y, --yes", "Skip interactive prompts").option("--no-prompt", "Skip interactive prompt to view results").option("--no-push", "Skip pushing the updated run to Iamu Cloud").option("--view", "Open results in browser immediately without prompt").addHelpText(
|
|
26148
26522
|
"after",
|
|
26149
|
-
|
|
26523
|
+
`
|
|
26524
|
+
Examples:
|
|
26525
|
+
$ iamu evaluate-record <run-id> --data '{"verdicts":[]}' --no-prompt --no-push
|
|
26526
|
+
$ iamu evaluate-record <run-id> --file verdicts.json
|
|
26527
|
+
$ iamu evaluate-record <run-id> --file verdicts.json --no-prompt
|
|
26528
|
+
$ iamu evaluate-record <run-id> --file verdicts.json --no-push
|
|
26529
|
+
$ iamu evaluate-record <run-id> --file verdicts.json --json`
|
|
26150
26530
|
).action(
|
|
26151
26531
|
async (runId, opts) => {
|
|
26152
26532
|
const { evaluateRecord: evaluateRecord2 } = await Promise.resolve().then(() => (init_evaluate(), evaluate_exports));
|