@iamu-dev/iamu 0.2.0-beta.2 → 0.2.0-beta.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/bin.js CHANGED
@@ -11896,7 +11896,7 @@ var init_credentials = __esm({
11896
11896
  "use strict";
11897
11897
  init_dist2();
11898
11898
  init_dist();
11899
- DEFAULT_API_URL = "https://api.iamu.dev";
11899
+ DEFAULT_API_URL = "https://app.iamu.dev";
11900
11900
  CredentialsFileError = class extends IamuConfigError {
11901
11901
  /**
11902
11902
  * @param path - The unreadable credentials file.
@@ -11993,7 +11993,7 @@ async function resolveCloudProject(opts) {
11993
11993
  commandError("Not cloud-linked. Run `iamu auth login` to connect.", opts);
11994
11994
  return null;
11995
11995
  }
11996
- const apiUrl = ctx.config.cloud_api_url ?? "https://api.iamu.dev";
11996
+ const apiUrl = ctx.config.cloud_api_url ?? DEFAULT_API_URL;
11997
11997
  try {
11998
11998
  assertSecureApiUrl(apiUrl, "cloud_api_url");
11999
11999
  } catch (err) {
@@ -13502,12 +13502,24 @@ async function browserLogin(apiUrl, opts, t) {
13502
13502
  chalk8.red(`
13503
13503
  Auth session expired or failed (HTTP ${result.status}).`)
13504
13504
  );
13505
+ console.error(
13506
+ chalk8.dim(" Re-run `iamu auth login` to start a new login session.\n")
13507
+ );
13505
13508
  process.exitCode = 1;
13506
13509
  return null;
13507
13510
  }
13508
13511
  if (result.kind === "timeout") {
13509
13512
  s.stop("Authentication timed out.");
13510
- console.error(chalk8.red("\n Authentication timed out. Try again."));
13513
+ console.error(
13514
+ chalk8.red(
13515
+ "\n Authentication timed out (no approval received within 2 minutes)."
13516
+ )
13517
+ );
13518
+ console.error(
13519
+ chalk8.dim(
13520
+ " \u2022 Complete browser authorization faster, or authenticate non-interactively with --token <key>.\n \u2022 Local setup is unaffected \u2014 re-run `iamu auth login` anytime.\n"
13521
+ )
13522
+ );
13511
13523
  process.exitCode = 1;
13512
13524
  return null;
13513
13525
  }
@@ -13533,7 +13545,12 @@ async function startAuthSession(apiUrl, timeoutMs) {
13533
13545
  if (!res.ok) {
13534
13546
  console.error(
13535
13547
  chalk8.red(
13536
- ` Failed to start auth session: ${res.text || `HTTP ${res.status}`}`
13548
+ ` Failed to start auth session at ${apiUrl}: ${res.text || `HTTP ${res.status}`}`
13549
+ )
13550
+ );
13551
+ console.error(
13552
+ chalk8.dim(
13553
+ " \u2022 The cloud service may be experiencing downtime or maintenance.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13537
13554
  )
13538
13555
  );
13539
13556
  process.exitCode = 1;
@@ -13547,7 +13564,13 @@ async function startAuthSession(apiUrl, timeoutMs) {
13547
13564
  return { sessionId: data.sessionId, loginUrl: data.loginUrl };
13548
13565
  } catch (err) {
13549
13566
  console.error(
13550
- chalk8.red(" Cannot reach Iamu Cloud.") + chalk8.dim(` (${errorMessage(err)})`)
13567
+ chalk8.red(` Cannot reach Iamu Cloud (${apiUrl}).`) + chalk8.dim(`
13568
+ Reason: ${errorMessage(err)}`)
13569
+ );
13570
+ console.error(
13571
+ chalk8.dim(
13572
+ "\n \u2022 Check your internet connection or proxy settings.\n \u2022 If using a custom instance, pass --url <api-url> or set IAMU_API_URL.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13573
+ )
13551
13574
  );
13552
13575
  process.exitCode = 1;
13553
13576
  return null;
@@ -18393,7 +18416,8 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
18393
18416
  ...base,
18394
18417
  name,
18395
18418
  role: opts.role ?? "TODO",
18396
- ...opts.disposition ? { disposition: opts.disposition } : {}
18419
+ ...opts.disposition ? { disposition: opts.disposition } : {},
18420
+ ...opts.access ? { access: opts.access } : {}
18397
18421
  };
18398
18422
  case "outline":
18399
18423
  return { ...base, title: name, ...description };
@@ -18462,7 +18486,7 @@ async function newEntity(type2, opts) {
18462
18486
  }
18463
18487
  const id = randomUUID9();
18464
18488
  const frontmatter = defaultFrontmatter(entityType, id, slug, opts.name, opts);
18465
- const body = "";
18489
+ const body = opts.body ?? opts.narrative ?? "";
18466
18490
  try {
18467
18491
  const record = await writeEntity(
18468
18492
  projectRoot,
@@ -20464,7 +20488,7 @@ function registerCloudCommands(program2) {
20464
20488
  "Connect to local cloud stack (default port: 3000)"
20465
20489
  ).addOption(
20466
20490
  new Option("-s, --staging", "Connect to staging cloud stack").hideHelp()
20467
- ).option("-t, --token <token>", "Authenticate directly with API token / key").option("--web-url <url>", "Custom web dashboard URL").option("--url <api-url>", "API URL (default: https://api.iamu.dev)").option("-y, --yes", "Accept default project without interactive selection").option(
20491
+ ).option("-t, --token <token>", "Authenticate directly with API token / key").option("--web-url <url>", "Custom web dashboard URL").option("--url <api-url>", "API URL (default: https://app.iamu.dev)").option("-y, --yes", "Accept default project without interactive selection").option(
20468
20492
  "--project <project-id>",
20469
20493
  "Cloud project ID to link to, or `new` to create one. Required in a non-interactive shell when cloud projects exist"
20470
20494
  ).option("--no-browser", "Do not launch browser automatically").addHelpText(
@@ -20620,6 +20644,9 @@ function registerProjectCommands(program2) {
20620
20644
  program2.command("new <type>").helpGroup("Project:").description(
20621
20645
  "Create a new entity (persona, outline, capability, source, scenario)"
20622
20646
  ).requiredOption("--name <name>", "Entity name").option("--slug <slug>", "Custom entity slug (defaults to slugified name)").option("--role <role>", "Role description (persona only)").option("--disposition <text>", "Disposition / attitude (persona only)").option(
20647
+ "--access <role>",
20648
+ "Access role or testing account key (persona only)"
20649
+ ).option("--body <text>", "Markdown body / narrative content").option("--narrative <text>", "Alias for --body").option(
20623
20650
  "--description <text>",
20624
20651
  "One-line description (capability, outline)"
20625
20652
  ).option("--outline <slug>", "Outline slug (scenario only)").option("--persona <slug>", "Persona slug (scenario only)").option(
package/dist/index.js CHANGED
@@ -11968,7 +11968,7 @@ var init_credentials = __esm({
11968
11968
  "use strict";
11969
11969
  init_dist2();
11970
11970
  init_dist();
11971
- DEFAULT_API_URL = "https://api.iamu.dev";
11971
+ DEFAULT_API_URL = "https://app.iamu.dev";
11972
11972
  CredentialsFileError = class extends IamuConfigError {
11973
11973
  /**
11974
11974
  * @param path - The unreadable credentials file.
@@ -12118,7 +12118,7 @@ async function resolveCloudProject(opts) {
12118
12118
  commandError("Not cloud-linked. Run `iamu auth login` to connect.", opts);
12119
12119
  return null;
12120
12120
  }
12121
- const apiUrl = ctx.config.cloud_api_url ?? "https://api.iamu.dev";
12121
+ const apiUrl = ctx.config.cloud_api_url ?? DEFAULT_API_URL;
12122
12122
  try {
12123
12123
  assertSecureApiUrl(apiUrl, "cloud_api_url");
12124
12124
  } catch (err) {
@@ -13481,12 +13481,24 @@ async function browserLogin(apiUrl, opts, t) {
13481
13481
  chalk8.red(`
13482
13482
  Auth session expired or failed (HTTP ${result.status}).`)
13483
13483
  );
13484
+ console.error(
13485
+ chalk8.dim(" Re-run `iamu auth login` to start a new login session.\n")
13486
+ );
13484
13487
  process.exitCode = 1;
13485
13488
  return null;
13486
13489
  }
13487
13490
  if (result.kind === "timeout") {
13488
13491
  s.stop("Authentication timed out.");
13489
- console.error(chalk8.red("\n Authentication timed out. Try again."));
13492
+ console.error(
13493
+ chalk8.red(
13494
+ "\n Authentication timed out (no approval received within 2 minutes)."
13495
+ )
13496
+ );
13497
+ console.error(
13498
+ chalk8.dim(
13499
+ " \u2022 Complete browser authorization faster, or authenticate non-interactively with --token <key>.\n \u2022 Local setup is unaffected \u2014 re-run `iamu auth login` anytime.\n"
13500
+ )
13501
+ );
13490
13502
  process.exitCode = 1;
13491
13503
  return null;
13492
13504
  }
@@ -13512,7 +13524,12 @@ async function startAuthSession(apiUrl, timeoutMs) {
13512
13524
  if (!res.ok) {
13513
13525
  console.error(
13514
13526
  chalk8.red(
13515
- ` Failed to start auth session: ${res.text || `HTTP ${res.status}`}`
13527
+ ` Failed to start auth session at ${apiUrl}: ${res.text || `HTTP ${res.status}`}`
13528
+ )
13529
+ );
13530
+ console.error(
13531
+ chalk8.dim(
13532
+ " \u2022 The cloud service may be experiencing downtime or maintenance.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13516
13533
  )
13517
13534
  );
13518
13535
  process.exitCode = 1;
@@ -13526,7 +13543,13 @@ async function startAuthSession(apiUrl, timeoutMs) {
13526
13543
  return { sessionId: data.sessionId, loginUrl: data.loginUrl };
13527
13544
  } catch (err) {
13528
13545
  console.error(
13529
- chalk8.red(" Cannot reach Iamu Cloud.") + chalk8.dim(` (${errorMessage(err)})`)
13546
+ chalk8.red(` Cannot reach Iamu Cloud (${apiUrl}).`) + chalk8.dim(`
13547
+ Reason: ${errorMessage(err)}`)
13548
+ );
13549
+ console.error(
13550
+ chalk8.dim(
13551
+ "\n \u2022 Check your internet connection or proxy settings.\n \u2022 If using a custom instance, pass --url <api-url> or set IAMU_API_URL.\n \u2022 Local setup is unaffected; continue with local workflows or retry later with `iamu auth login`.\n"
13552
+ )
13530
13553
  );
13531
13554
  process.exitCode = 1;
13532
13555
  return null;
@@ -18372,7 +18395,8 @@ function defaultFrontmatter(type2, id, slug, name, opts) {
18372
18395
  ...base,
18373
18396
  name,
18374
18397
  role: opts.role ?? "TODO",
18375
- ...opts.disposition ? { disposition: opts.disposition } : {}
18398
+ ...opts.disposition ? { disposition: opts.disposition } : {},
18399
+ ...opts.access ? { access: opts.access } : {}
18376
18400
  };
18377
18401
  case "outline":
18378
18402
  return { ...base, title: name, ...description };
@@ -18441,7 +18465,7 @@ async function newEntity(type2, opts) {
18441
18465
  }
18442
18466
  const id = randomUUID9();
18443
18467
  const frontmatter = defaultFrontmatter(entityType, id, slug, opts.name, opts);
18444
- const body = "";
18468
+ const body = opts.body ?? opts.narrative ?? "";
18445
18469
  try {
18446
18470
  const record = await writeEntity(
18447
18471
  projectRoot,
@@ -20435,7 +20459,7 @@ function registerCloudCommands(program) {
20435
20459
  "Connect to local cloud stack (default port: 3000)"
20436
20460
  ).addOption(
20437
20461
  new Option("-s, --staging", "Connect to staging cloud stack").hideHelp()
20438
- ).option("-t, --token <token>", "Authenticate directly with API token / key").option("--web-url <url>", "Custom web dashboard URL").option("--url <api-url>", "API URL (default: https://api.iamu.dev)").option("-y, --yes", "Accept default project without interactive selection").option(
20462
+ ).option("-t, --token <token>", "Authenticate directly with API token / key").option("--web-url <url>", "Custom web dashboard URL").option("--url <api-url>", "API URL (default: https://app.iamu.dev)").option("-y, --yes", "Accept default project without interactive selection").option(
20439
20463
  "--project <project-id>",
20440
20464
  "Cloud project ID to link to, or `new` to create one. Required in a non-interactive shell when cloud projects exist"
20441
20465
  ).option("--no-browser", "Do not launch browser automatically").addHelpText(
@@ -20591,6 +20615,9 @@ function registerProjectCommands(program) {
20591
20615
  program.command("new <type>").helpGroup("Project:").description(
20592
20616
  "Create a new entity (persona, outline, capability, source, scenario)"
20593
20617
  ).requiredOption("--name <name>", "Entity name").option("--slug <slug>", "Custom entity slug (defaults to slugified name)").option("--role <role>", "Role description (persona only)").option("--disposition <text>", "Disposition / attitude (persona only)").option(
20618
+ "--access <role>",
20619
+ "Access role or testing account key (persona only)"
20620
+ ).option("--body <text>", "Markdown body / narrative content").option("--narrative <text>", "Alias for --body").option(
20594
20621
  "--description <text>",
20595
20622
  "One-line description (capability, outline)"
20596
20623
  ).option("--outline <slug>", "Outline slug (scenario only)").option("--persona <slug>", "Persona slug (scenario only)").option(
@@ -44,33 +44,48 @@ Explore the codebase automatically — do NOT ask the user what files to read. B
44
44
 
45
45
  Extract these key dimensions:
46
46
 
47
- 1. **Domain** — what does this product do, in one phrase (mandatory).
48
- 2. **Jurisdiction** — country / region (optional — only include if evident from codebase/locale/terms or if legal frameworks apply).
49
- 3. **Regulations (`governed_by`)** — specific compliance frameworks (AFS 2023:2, GDPR, HIPAA, ISO 27001, etc.). **Strictly optional:** only extract if the repo explicitly references legal or compliance standards. Most software is not in a regulated domain; do NOT invent or guess regulations for standard SaaS/apps.
50
- 4. **Primary Personas** — determine the 1–2 most important user archetypes that stress-test this product (e.g. End User / Consumer vs. Admin / Operator, or First-Timer vs. Power User). Propose:
47
+ 1. **Domain & Purpose** — what this product does, core workflows, and problem space (mandatory).
48
+ 2. **Jurisdiction & Regulations (`governed_by`)** — country/region and specific compliance frameworks (AFS 2023:2, GDPR, HIPAA, ISO 27001, etc.). **Strictly optional:** only extract if the repo explicitly references legal or compliance standards. Do NOT invent regulations for standard apps.
49
+ 3. **Key Actors & Roles** — the main user archetypes and roles discovered in the codebase (auth models, routes, permissions).
50
+ 4. **Dev Access & Auth** — how personas switch or log in during local dev/test (e.g. dev persona switcher, seeded accounts, storage key, mock headers). Essential for walkthrough automation.
51
+ 5. **Key Terminology (`glossary`)** — 2–4 domain-specific terms or acronyms found in the codebase.
52
+ 6. **Primary Personas** — determine the 1–2 most critical user archetypes that stress-test this product (e.g. End User / Frontline vs. Admin / Compliance, or First-Timer vs. Power User). Propose:
51
53
  - Name and Role
52
54
  - Disposition / perspective (patience level, tech literacy, primary friction triggers)
53
55
 
54
- Also collect silently (write to `context.yml` but do NOT present for confirmation):
55
- - **Actors** — all identified roles and their responsibilities.
56
- - **Glossary** — domain-specific terms (helps persona language fidelity).
57
- - **Access** — if the project documents how to switch user or role in a dev or test environment (a persona switcher, seeded accounts, a storage key), record that mechanism as `access`. It is what lets a walkthrough run as the persona instead of as whoever happens to be signed in. Never record passwords or tokens — name where they live.
58
-
59
- Do NOT collect architecture (agent reads the codebase directly — tech stack doesn't affect walkthroughs).
56
+ Do NOT collect code architecture (agent reads the codebase directly — tech stack doesn't affect walkthroughs).
60
57
 
61
58
  **If there is no code (greenfield, design phase):** ask the user: what does this project do, who are the users, what domain, and are there any specific regulations?
62
59
 
63
- **Present a short proposal for confirmation:**
60
+ **Present the proposal with clean, structured Markdown for confirmation:**
64
61
 
65
- ```
66
- Your project: <domain> (<jurisdiction if known>)
67
- [Regulations: <reg1>, <reg2>] <-- omit line entirely if none
62
+ ```markdown
63
+ ### 📋 Discovered Project Context
64
+
65
+ - **Domain & Purpose:** <Concise description of the product and problem space>
66
+ - **Jurisdiction & Rules:** <Country/region and compliance frameworks, or "None identified">
67
+ - **Key Roles Identified:** <List of detected roles and their responsibilities>
68
+ - **Dev Access & Auth:** <Detected mechanism to switch/assume personas in dev, or "Standard login">
69
+ - **Domain Terminology:** <2–4 key terms/acronyms found in the codebase, if any>
70
+
71
+ ---
72
+
73
+ ### 🎭 Proposed Primary Personas
68
74
 
69
- Proposed primary personas:
70
- 1. <Name> (<Role>) — <Key disposition & perspective>
71
- 2. <Name> (<Role>) — <Key disposition & perspective>
75
+ #### 1. <Name> — *<Role / Title>*
76
+ - **Context & Usage:** <Where and how they use the app (e.g., mobile on the floor vs. desktop in office)>
77
+ - **Disposition:** <Patience level, technical confidence, key motivations>
78
+ - **Friction Triggers:** <Specific interactions that cause friction, drop-off, or failure>
72
79
 
73
- Confirm context & scaffold these personas? (yes / edit / suggest-others / skip-personas)
80
+ #### 2. <Name> — *<Role / Title>*
81
+ - **Context & Usage:** <Where and how they use the app>
82
+ - **Disposition:** <Patience level, technical confidence, key motivations>
83
+ - **Friction Triggers:** <Specific interactions that cause friction, drop-off, or failure>
84
+
85
+ ---
86
+
87
+ **Next step:**
88
+ Reply **"yes"** to save this context to `iamu/context.yml` and scaffold these personas, or tell me what to adjust (e.g., change roles, edit domain, or add/skip personas).
74
89
  ```
75
90
 
76
91
  Wait for the user to confirm or correct before writing. The user only needs to verify domain and choose whether to accept, edit, suggest alternative personas, or defer persona creation.
@@ -122,16 +137,17 @@ Persist the step-2 summary as structured fields so every scenario draft and walk
122
137
 
123
138
  4. **Scaffold confirmed personas (unless `skip-personas` selected):**
124
139
 
125
- Always use the CLI to scaffold valid persona entities with schema-compliant UUIDs, slugs, and timestamps:
140
+ Use the CLI to scaffold valid persona entities with schema-compliant UUIDs, slugs, frontmatter, and narrative body in a single command:
126
141
  ```bash
127
- iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" --json
142
+ iamu new persona --name "<Name>" --role "<Role>" --disposition "<Disposition>" --body "<2-4 sentence narrative detailing technical habits, patience level, and specific friction triggers>" [--access "<account-or-role>"] --json
128
143
  ```
129
144
 
130
- Then open the created file (`iamu/personas/<slug>.md`) and write 2–4 sentences of background narrative into the markdown body below the frontmatter, detailing their technical habits, patience level, and specific friction triggers.
145
+ If `iamu/context.yml` specifies an `access` mechanism, pass `--access "<role>"` matching an existing product account/role.
131
146
 
132
- If `iamu/context.yml` has an `access` mechanism, set the persona's `access` field in frontmatter to match an existing product account/role.
133
-
134
- Run `iamu validate --all`.
147
+ Once all confirmed personas are created, run validation once:
148
+ ```bash
149
+ iamu validate --all
150
+ ```
135
151
 
136
152
  5. Confirm: "Context saved and personas seeded in iamu/personas/. Run `iamu-new` to draft your first scenario." (or "Context saved. Run `iamu-new` to draft your first scenario." if personas were skipped).
137
153
 
@@ -157,11 +173,15 @@ Three outcomes:
157
173
 
158
174
  **Linking:**
159
175
 
160
- 1. Run `iamu auth login` (add `--url <api-url>` only if the user names a self-hosted cloud). It opens the sign-in page in the user's browser and waits up to two minutes — tell the user to approve it there. Allow the command at least 150 seconds before your shell tool times out. If your shell cannot wait that long, or runs where no browser can open (remote or container session), ask the user to run `iamu auth login` in their own terminal and tell you when it is done.
161
- 2. **Never pick the cloud project for the user.** In a non-interactive shell with existing cloud projects, login stops after sign-in and lists them as `iamu auth login --project <id>` lines plus `--project new`. Show that list, ask which project this repository belongs to, then re-run with their choice — the stored sign-in is reused, no second browser trip. Linking pushes every local persona, scenario and finding into the chosen project; a wrong guess leaks them into someone else's.
162
- 3. On success the output ends with `Dashboard: <url>` and, when an agent host was detected, `iamu-sync MCP server registered`. Relay both in two lines: the dashboard link, and that restarting the agent session loads the team tools (work requests, teammate-change alerts).
176
+ 1. Tell the user: "Opening browser for Iamu Cloud login..." then run `iamu auth login`. Allow the command at least 150 seconds for the user to complete sign-in in their browser. If your shell cannot wait that long, or runs where no browser can open (remote or container session), ask the user to run `iamu auth login` in their own terminal and tell you when it is done.
177
+ 2. **Never pick the cloud project for the user.** In a non-interactive shell with existing cloud projects, login stops after sign-in and lists them as `iamu auth login --project <id>` lines plus `--project new`. Show that list, ask which project this repository belongs to, then re-run with their choice — the stored sign-in is reused, no second browser trip.
178
+ 3. On success the output ends with `Dashboard: <url>` and, when an agent host was detected, `iamu-sync MCP server registered`. Relay both: the dashboard link, and that restarting the agent session loads the team tools (work requests, teammate-change alerts).
163
179
 
164
- If login fails (cloud unreachable, sign-in timed out), report the error in one line and continue — setup is complete without the cloud.
180
+ If login times out or fails (cloud unreachable, sign-in timed out, or network error):
181
+ - Explain clearly what happened: "Cloud linking could not be completed (<echo specific reason from command output>)."
182
+ - Reassure the user: "Your local project setup is 100% complete and fully functional. Personas, scenarios, outlines, and walkthroughs run locally without cloud."
183
+ - Provide the next step for linking: "You can link to Iamu Cloud anytime later by running `iamu auth login` in your terminal."
184
+ - Point to the next creative action: "Next: run `iamu-new` to draft your first scenario."
165
185
 
166
186
  All three outcomes leave a usable local setup. Cloud is strictly additive.
167
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamu-dev/iamu",
3
- "version": "0.2.0-beta.2",
3
+ "version": "0.2.0-beta.4",
4
4
  "type": "module",
5
5
  "description": "Test your product as realistic personas — scenario-driven development CLI",
6
6
  "license": "UNLICENSED",
@@ -58,8 +58,8 @@
58
58
  "typescript": "^5.8.0",
59
59
  "vitest": "^4.1.11",
60
60
  "@iamu-dev/local-store": "0.1.0",
61
- "@iamu/tsconfig": "0.1.0",
62
- "@iamu-dev/protocol": "0.1.0"
61
+ "@iamu-dev/protocol": "0.1.0",
62
+ "@iamu/tsconfig": "0.1.0"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "tsup && tsc -b tsconfig.build.json --emitDeclarationOnly && node scripts/copy-assets.mjs",