@formigio/fazemos-cli 0.10.66 → 0.10.74

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.
Files changed (48) hide show
  1. package/dist/commands/preflight.d.ts +41 -0
  2. package/dist/commands/preflight.js +706 -0
  3. package/dist/commands/preflight.js.map +1 -0
  4. package/dist/commands/provision.d.ts +29 -0
  5. package/dist/commands/provision.js +382 -0
  6. package/dist/commands/provision.js.map +1 -0
  7. package/dist/index.js +173 -14
  8. package/dist/index.js.map +1 -1
  9. package/dist/preflight/repoRead.d.ts +65 -0
  10. package/dist/preflight/repoRead.js +194 -0
  11. package/dist/preflight/repoRead.js.map +1 -0
  12. package/dist/preflight/roster.d.ts +65 -0
  13. package/dist/preflight/roster.js +153 -0
  14. package/dist/preflight/roster.js.map +1 -0
  15. package/dist/preflight/row1_member.d.ts +8 -0
  16. package/dist/preflight/row1_member.js +64 -0
  17. package/dist/preflight/row1_member.js.map +1 -0
  18. package/dist/preflight/row2_roleRegistration.d.ts +18 -0
  19. package/dist/preflight/row2_roleRegistration.js +156 -0
  20. package/dist/preflight/row2_roleRegistration.js.map +1 -0
  21. package/dist/preflight/row3_persona.d.ts +24 -0
  22. package/dist/preflight/row3_persona.js +92 -0
  23. package/dist/preflight/row3_persona.js.map +1 -0
  24. package/dist/preflight/row3_playbook.d.ts +30 -0
  25. package/dist/preflight/row3_playbook.js +142 -0
  26. package/dist/preflight/row3_playbook.js.map +1 -0
  27. package/dist/preflight/row3_rolesJson.d.ts +12 -0
  28. package/dist/preflight/row3_rolesJson.js +38 -0
  29. package/dist/preflight/row3_rolesJson.js.map +1 -0
  30. package/dist/preflight/row3_workspace.d.ts +24 -0
  31. package/dist/preflight/row3_workspace.js +253 -0
  32. package/dist/preflight/row3_workspace.js.map +1 -0
  33. package/dist/preflight/row4_ssm.d.ts +57 -0
  34. package/dist/preflight/row4_ssm.js +235 -0
  35. package/dist/preflight/row4_ssm.js.map +1 -0
  36. package/dist/preflight/row5_workerLambdaWakeConfig.d.ts +20 -0
  37. package/dist/preflight/row5_workerLambdaWakeConfig.js +113 -0
  38. package/dist/preflight/row5_workerLambdaWakeConfig.js.map +1 -0
  39. package/dist/preflight/row6_ingest.d.ts +20 -0
  40. package/dist/preflight/row6_ingest.js +178 -0
  41. package/dist/preflight/row6_ingest.js.map +1 -0
  42. package/dist/preflight/schema.d.ts +175 -0
  43. package/dist/preflight/schema.js +62 -0
  44. package/dist/preflight/schema.js.map +1 -0
  45. package/dist/preflight/workerLambdas.d.ts +22 -0
  46. package/dist/preflight/workerLambdas.js +25 -0
  47. package/dist/preflight/workerLambdas.js.map +1 -0
  48. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -30,6 +30,9 @@ import { registerProfilesCommands } from './commands/profiles.js';
30
30
  import { registerImageCommands } from './commands/image.js';
31
31
  import { registerIngestCommands } from './commands/ingest.js';
32
32
  import { registerAssetCommands } from './commands/asset/index.js';
33
+ // F53 — Agent Provisioning Tooling
34
+ import { runPreflight } from './commands/preflight.js';
35
+ import { runProvision } from './commands/provision.js';
33
36
  import { parseExecutionsJson, resolveWaitOptions, waitForPipelines, buildAwsCommand, validateExecutionEntry, } from './wait-for-pipeline.js';
34
37
  import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync, statSync } from 'fs';
35
38
  import { fileURLToPath } from 'url';
@@ -7452,6 +7455,24 @@ agentsCmd
7452
7455
  console.log(chalk.gray(` Audit: ${a.auditLogId}`));
7453
7456
  }
7454
7457
  }
7458
+ // F53 — next-step hint (additive; pre-existing success lines above stay byte-identical)
7459
+ // Suppressed under --json (AC4 rule: rul_f53_hint_text_additive_only).
7460
+ if (!opts.json) {
7461
+ const orgId = getActiveOrgId();
7462
+ const orgSlug = orgId ? (findOrgById(orgId)?.slug ?? null) : null;
7463
+ const roleSlug = opts.roles?.[0] ?? opts.name;
7464
+ const projectSlug = credentialProjectId
7465
+ ? (orgId ? (findProjectById(orgId, credentialProjectId)?.slug ?? null) : null)
7466
+ : null;
7467
+ console.log('');
7468
+ console.log(chalk.gray(' Not autonomous yet — layers 2–6 remain.'));
7469
+ if (orgSlug && projectSlug && roleSlug) {
7470
+ console.log(chalk.gray(` Next: fazemos agents preflight ${orgSlug}/${projectSlug}/${roleSlug}`));
7471
+ }
7472
+ else {
7473
+ console.log(chalk.gray(` Next: fazemos agents preflight <org>/<project>/${roleSlug}`));
7474
+ }
7475
+ }
7455
7476
  }
7456
7477
  catch (err) {
7457
7478
  if (opts.json) {
@@ -7476,6 +7497,59 @@ agentsCmd
7476
7497
  process.exit(1);
7477
7498
  }
7478
7499
  });
7500
+ // ── F53 — `agents preflight` ────────────────────────────────────────────────
7501
+ // 6-row PASS/FAIL/SKIP/XWS_DEFERRED verifier for agent provisioning state.
7502
+ // Exit codes: 0=all clear, 1=FAIL, 2=tooling-error, 3=XWS_DEFERRED (INCOMPLETE).
7503
+ // Target forms: <org>/<project>/<role>, <org>/<project>, <org>/<role>.
7504
+ // Spec: projects/fazemos/specs/tech/platform/F53-agent-provision-tooling-tech-spec.md
7505
+ agentsCmd
7506
+ .command('preflight')
7507
+ .description('Verify agent provisioning state: 6-row PASS/FAIL/SKIP verifier with fix commands.\n' +
7508
+ 'Target: <org>/<project>/<role> | <org>/<project> (all roles) | <org>/<role> (all projects)\n' +
7509
+ 'Exit codes: 0=all clear, 1=FAIL, 2=tooling-error, 3=XWS_DEFERRED (cross-workspace unverified)')
7510
+ .argument('<target>', 'org/project/role, org/project (fan-out roles), or org/role (fan-out projects)')
7511
+ .option('--json', 'Emit stable JSON instead of human-readable output (schema_version 1.0)')
7512
+ .option('--workspace <path>', 'Path to workspace root containing .fazemos/roles.json (defaults to nearest ancestor)')
7513
+ .option('--region <region>', 'AWS region for SSM/Lambda checks (reads AWS_REGION env var by default)')
7514
+ .action(async (target, opts) => {
7515
+ try {
7516
+ const exitCode = await runPreflight(target, opts);
7517
+ process.exit(exitCode);
7518
+ }
7519
+ catch (err) {
7520
+ if (opts.json) {
7521
+ process.stdout.write(JSON.stringify({ schema_version: '1.0', target, exit_code: 2, error: err?.message ?? String(err) }) + '\n');
7522
+ }
7523
+ else {
7524
+ console.error(chalk.red(`⚠ TOOLING-ERROR: ${err?.message ?? String(err)}`));
7525
+ }
7526
+ process.exit(2);
7527
+ }
7528
+ });
7529
+ // ── F53 — `agents provision` ────────────────────────────────────────────────
7530
+ // Idempotent composite of provisioning layers 1–3, then runs preflight.
7531
+ // Non-interactive one-shot; --dry-run is the safety valve (no --yes flag, Ollie A1).
7532
+ // Spec: projects/fazemos/specs/tech/platform/F53-agent-provision-tooling-tech-spec.md
7533
+ agentsCmd
7534
+ .command('provision')
7535
+ .description('Idempotent provisioning of layers 1–3 for an agent role, then runs preflight.\n' +
7536
+ 'Layer 1: agents register. Layer 2: roles.json + roles sync. Layer 3: verify-and-instruct (no scaffold).\n' +
7537
+ 'Non-interactive. Use --dry-run to preview without writing.')
7538
+ .argument('<target>', 'org/project/role to provision')
7539
+ .requiredOption('--name <agent>', 'Agent display name')
7540
+ .requiredOption('--model <model>', 'Model (e.g., sonnet, opus, haiku)')
7541
+ .option('--dry-run', 'Preview what would be done without making changes')
7542
+ .option('--json', 'Suppress human output; preflight result is emitted as JSON')
7543
+ .option('--region <region>', 'AWS region for SSM/Lambda checks in the final preflight run')
7544
+ .action(async (target, opts) => {
7545
+ try {
7546
+ await runProvision(target, opts);
7547
+ }
7548
+ catch (err) {
7549
+ console.error(chalk.red(`provision error: ${err?.message ?? String(err)}`));
7550
+ process.exit(1);
7551
+ }
7552
+ });
7479
7553
  // ── F17 — Project-scoped agents ─────────────────────────────────
7480
7554
  // `agents list` / `agents show` become Project-scoped by default. The
7481
7555
  // pre-F17 Org-level list is still reachable via `--org-only`. Execution
@@ -7514,6 +7588,10 @@ function exitNoActiveProjectForAgentsList() {
7514
7588
  function formatAgentSource(source) {
7515
7589
  if (source === 'project_override')
7516
7590
  return 'project-override';
7591
+ if (source === 'org_file')
7592
+ return 'org-file';
7593
+ if (source === 'project_file')
7594
+ return 'project-file';
7517
7595
  return source;
7518
7596
  }
7519
7597
  /**
@@ -7781,11 +7859,26 @@ agentsCmd
7781
7859
  const { orgId, projectId } = await requireProjectForAgents(opts.project);
7782
7860
  const data = await api('GET', `/api/organizations/${orgId}/projects/${projectId}/agents/${encodeURIComponent(name)}`, undefined, { noProjectHeader: true });
7783
7861
  const a = data.agent;
7862
+ const resolution = data.resolution;
7784
7863
  const proj = findProjectById(orgId, projectId);
7785
7864
  const projSlug = proj?.slug ?? projectId;
7786
- const sourceLabel = formatAgentSource(a.source);
7865
+ // Use resolution.agent_source (F18-aware) when available; fall back to
7866
+ // a.source (F17-only) for older API versions (degrade per §6).
7867
+ const effectiveSource = resolution?.agent_source ?? a.source;
7868
+ const sourceLabel = formatAgentSource(effectiveSource);
7787
7869
  console.log(chalk.cyan(`Agent: ${a.name} (${a.display_name})`));
7788
7870
  console.log(`Project: ${projSlug} · Source: ${sourceLabel}`);
7871
+ // Role doc line — show immediately after source when a role doc is active.
7872
+ // Uses agent.role_doc_path populated by the API's F18 layer. When the API
7873
+ // is newer (resolution block present), also shows the resolved prompt length
7874
+ // so an empty role-doc stub is visible without a CloudWatch query (R10).
7875
+ if (a.role_doc_path) {
7876
+ const level = a.role_doc_level ? ` (level: ${a.role_doc_level})` : '';
7877
+ console.log(chalk.gray(` Role doc: ${a.role_doc_path}${level}`));
7878
+ if (resolution?.resolved_system_prompt_length !== undefined) {
7879
+ console.log(chalk.gray(` Resolved prompt: ${resolution.resolved_system_prompt_length.toLocaleString()} chars`));
7880
+ }
7881
+ }
7789
7882
  console.log('');
7790
7883
  // EFFECTIVE CONFIG
7791
7884
  console.log(chalk.cyan('EFFECTIVE CONFIG'));
@@ -7837,12 +7930,6 @@ agentsCmd
7837
7930
  const label = a.source === 'project_override' ? 'Override created' : 'Project-only created';
7838
7931
  console.log(chalk.gray(`${label}: ${new Date(a.override_updated_at).toISOString().slice(0, 10)}`));
7839
7932
  }
7840
- // F18 forward-compat: role doc line only when populated.
7841
- if (a.role_doc_path) {
7842
- const level = a.role_doc_level ? ` (${a.role_doc_level})` : '';
7843
- console.log('');
7844
- console.log(chalk.gray(`Role doc: ${a.role_doc_path}${level}`));
7845
- }
7846
7933
  }
7847
7934
  catch (err) {
7848
7935
  if (err instanceof ApiError && err.code === 'AGENT_NOT_FOUND') {
@@ -8545,9 +8632,11 @@ agentsCmd
8545
8632
  .description('Upload an agent definition file to Fazemos')
8546
8633
  .argument('<name>', 'Agent name')
8547
8634
  .argument('<file>', 'Path to agent definition .md file')
8548
- .action(async (name, file) => {
8635
+ .option('--project <slug>', 'Project context for role-doc check (uses active project if not set)')
8636
+ .option('--force', 'Proceed even when a role doc overrides the DB systemPrompt at runtime', false)
8637
+ .action(async (name, file, opts) => {
8549
8638
  try {
8550
- // Resolve agent name to member ID
8639
+ // Resolve agent name to member ID (org-level members list)
8551
8640
  const orgId = getActiveOrgId();
8552
8641
  if (!orgId) {
8553
8642
  console.error(chalk.red('No active org'));
@@ -8560,11 +8649,68 @@ agentsCmd
8560
8649
  console.error(chalk.red(`Agent "${name}" not found`));
8561
8650
  process.exit(1);
8562
8651
  }
8563
- // Read file and strip YAML frontmatter
8564
- const raw = readFileSync(resolve(file), 'utf-8');
8565
- const body = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
8566
- await api('PATCH', `/api/members/${agent.id}/agent-config`, { systemPrompt: body });
8567
- console.log(chalk.green(`Uploaded definition for ${agent.display_name} (${body.length} chars)`));
8652
+ // BUG-PERSONA-RESOLUTION-PATHS-DISAGREE fix (R9, AC-9):
8653
+ // Before PATCHing the DB, check whether a role doc overrides the
8654
+ // systemPrompt at runtime. If so, the upload is silently inert — warn
8655
+ // and refuse unless --force is passed.
8656
+ //
8657
+ // Predicate is derived from the API's resolution.has_role_doc field
8658
+ // (predicate-based, NOT a name-list allowlist — rul_respaths_predicate_not_allowlist).
8659
+ // Requires a project context to call the F17 detail endpoint that carries
8660
+ // the resolution block. When no project context is available, skip the
8661
+ // check and proceed (defensive degrade per §6 — same behavior as today).
8662
+ //
8663
+ // proceedWithUpload is set to false BEFORE process.exit(1) so that test
8664
+ // environments where process.exit is mocked still gate the PATCH correctly.
8665
+ let proceedWithUpload = true;
8666
+ if (!opts.force) {
8667
+ // Resolve project context: --project flag → active project → none.
8668
+ let projectId = null;
8669
+ if (opts.project) {
8670
+ const proj = findProjectBySlug(orgId, opts.project);
8671
+ projectId = proj?.id ?? null;
8672
+ if (!projectId) {
8673
+ proceedWithUpload = false;
8674
+ console.error(chalk.red(`Project "${opts.project}" not found`));
8675
+ process.exit(1);
8676
+ }
8677
+ }
8678
+ else {
8679
+ projectId = getActiveProjectId();
8680
+ }
8681
+ if (proceedWithUpload && projectId) {
8682
+ // Fetch the F17 detail endpoint (now F18-aware) to get the resolution block.
8683
+ // Use agent.name (lowercase slug) as the URL param.
8684
+ const agentName = agent.name ?? norm(name).replace(/\s+/g, '-');
8685
+ try {
8686
+ const detailData = await api('GET', `/api/organizations/${orgId}/projects/${projectId}/agents/${encodeURIComponent(agentName)}`, undefined, { noProjectHeader: true });
8687
+ // Defensive degrade: if resolution block is absent (older API), treat as
8688
+ // has_role_doc=false and proceed — behavior identical to today (§6 / EC-7).
8689
+ if (detailData.resolution?.has_role_doc === true) {
8690
+ const roleDocPath = detailData.resolution.role_doc_path ?? '(unknown path)';
8691
+ proceedWithUpload = false; // Gate PATCH before calling exit (for test environments).
8692
+ console.error(chalk.yellow(`⚠ a role doc at ${roleDocPath} overrides the DB systemPrompt at runtime —`));
8693
+ console.error(chalk.yellow(` this upload will not take effect. Edit the file instead, or re-run with --force`));
8694
+ console.error(chalk.yellow(` if you deliberately want to write the DB value.`));
8695
+ process.exit(1);
8696
+ }
8697
+ }
8698
+ catch (detailErr) {
8699
+ // Detail-fetch failure should not block the upload — fall through.
8700
+ // The PATCH may still be inert if a role doc exists, but we cannot
8701
+ // determine that without the API's resolution block.
8702
+ console.error(chalk.gray(`(role-doc check skipped: ${detailErr.message})`));
8703
+ }
8704
+ }
8705
+ // No project context → skip check, proceed as before.
8706
+ }
8707
+ if (proceedWithUpload) {
8708
+ // Read file and strip YAML frontmatter
8709
+ const raw = readFileSync(resolve(file), 'utf-8');
8710
+ const body = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
8711
+ await api('PATCH', `/api/members/${agent.id}/agent-config`, { systemPrompt: body });
8712
+ console.log(chalk.green(`Uploaded definition for ${agent.display_name} (${body.length} chars)`));
8713
+ }
8568
8714
  }
8569
8715
  catch (err) {
8570
8716
  console.error(chalk.red(err.message));
@@ -10337,6 +10483,19 @@ Run after editing roles.json to sync inbox access to the API.`)
10337
10483
  console.log(` ${chalk.cyan(slug)}`);
10338
10484
  }
10339
10485
  }
10486
+ // F53 — next-step hint (additive; the success line above stays byte-identical)
10487
+ // Suppressed under --dry-run (opts.dryRun returns early above; this only runs on real sync).
10488
+ // The org/project come from the local registry that was just synced.
10489
+ const hintOrgSlug = localRegistry.org;
10490
+ const hintProjectSlug = localRegistry.project ?? null;
10491
+ console.log('');
10492
+ console.log(chalk.gray(` Not autonomous yet — layers 3–6 remain for each role.`));
10493
+ if (hintOrgSlug && hintProjectSlug) {
10494
+ console.log(chalk.gray(` Next: fazemos agents preflight ${hintOrgSlug}/${hintProjectSlug}`));
10495
+ }
10496
+ else if (hintOrgSlug) {
10497
+ console.log(chalk.gray(` Next: fazemos agents preflight ${hintOrgSlug}/<project>`));
10498
+ }
10340
10499
  }
10341
10500
  catch (err) {
10342
10501
  console.error(chalk.red(err instanceof Error ? err.message : String(err)));