@rosthq/cli 0.7.22 → 0.7.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"command-manifest.d.ts","sourceRoot":"","sources":["../../src/generated/command-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAwN3D,CAAC"}
1
+ {"version":3,"file":"command-manifest.d.ts","sourceRoot":"","sources":["../../src/generated/command-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EA2N3D,CAAC"}
package/dist/index.js CHANGED
@@ -37979,6 +37979,147 @@ var CATALOG_ENTRIES = [
37979
37979
  scope_tiers: ["read"],
37980
37980
  credential_required: false,
37981
37981
  default_access_policy: "always_allow"
37982
+ },
37983
+ // DER-1293 (tool-id canonicalization): the stock agent templates
37984
+ // (`packages/agents/src/templates.ts`) grant these dotted business-tool ids, so a
37985
+ // signed AP-Clerk / SDR / Support / QA / Signal manifest derived from a template
37986
+ // already carries them. They were missing from the catalog, which (1) made a Skill
37987
+ // that requires one resolve `unknown_tool` at `skill.check_dependencies`, and (2)
37988
+ // left the runtime guard's scope-tier lookup (`resolveToolScopeTier`) unresolved →
37989
+ // fail-closed `critical` for an autonomous read/draft grant. Adding them here — the
37990
+ // single source of truth for scope tier and access policy — reconciles all three
37991
+ // surfaces (catalog ↔ templates ↔ skills). Conservative-by-default (invariant #10):
37992
+ // read/draft tiers only, drafts never send, and the ids never mint new authority —
37993
+ // authorization stays with the signed manifest + guard (invariant #6).
37994
+ {
37995
+ id: "accounting.bills.read",
37996
+ title: "Read payable bills",
37997
+ provider: "accounting",
37998
+ description: "Call this to read payable bills, vendor records, and matching evidence when preparing accounts-payable work. Read-only: no payment release, coding change, or vendor send.",
37999
+ default_scope_tier: "read",
38000
+ scope_tiers: ["read"],
38001
+ credential_required: true,
38002
+ default_access_policy: "always_allow"
38003
+ },
38004
+ {
38005
+ id: "accounting.invoices.read",
38006
+ title: "Read receivable invoices",
38007
+ provider: "accounting",
38008
+ description: "Call this to read receivable invoice aging and payment status for collections and reconciliation. Read-only: it never changes terms, applies credits, or sends.",
38009
+ default_scope_tier: "read",
38010
+ scope_tiers: ["read"],
38011
+ credential_required: true,
38012
+ default_access_policy: "always_allow"
38013
+ },
38014
+ {
38015
+ id: "inbox.ap.read",
38016
+ title: "Read AP inbox",
38017
+ provider: "email",
38018
+ description: "Call this to read messages in the assigned accounts-payable inbox for triage and invoice matching. Read-only and scoped to the AP inbox.",
38019
+ default_scope_tier: "read",
38020
+ scope_tiers: ["read"],
38021
+ credential_required: true,
38022
+ default_access_policy: "always_allow"
38023
+ },
38024
+ {
38025
+ id: "inbox.ap.draft",
38026
+ title: "Draft AP reply",
38027
+ provider: "email",
38028
+ description: "Call this to draft an accounts-payable reply for a human to review. Draft-only: it never sends.",
38029
+ default_scope_tier: "draft",
38030
+ scope_tiers: ["draft"],
38031
+ credential_required: true,
38032
+ default_access_policy: "always_allow"
38033
+ },
38034
+ {
38035
+ id: "email.collections.draft",
38036
+ title: "Draft collections reminder",
38037
+ provider: "email",
38038
+ description: "Call this to draft a collections reminder for human approval. Draft-only: it never sends, changes terms, or applies credits.",
38039
+ default_scope_tier: "draft",
38040
+ scope_tiers: ["draft"],
38041
+ credential_required: true,
38042
+ default_access_policy: "always_allow"
38043
+ },
38044
+ {
38045
+ id: "helpdesk.ticket.read",
38046
+ title: "Read support tickets",
38047
+ provider: "helpdesk",
38048
+ description: "Call this to read assigned support tickets and their history for triage. Read-only and scoped to the assigned queues.",
38049
+ default_scope_tier: "read",
38050
+ scope_tiers: ["read"],
38051
+ credential_required: true,
38052
+ default_access_policy: "always_allow"
38053
+ },
38054
+ {
38055
+ id: "helpdesk.ticket.classify",
38056
+ title: "Classify support ticket",
38057
+ provider: "helpdesk",
38058
+ description: "Call this to tag and route a support ticket to the correct queue. Classification and routing only \u2014 it never replies, changes account state, or closes a ticket.",
38059
+ default_scope_tier: "draft",
38060
+ scope_tiers: ["draft"],
38061
+ credential_required: true,
38062
+ default_access_policy: "always_allow"
38063
+ },
38064
+ {
38065
+ id: "helpdesk.reply.draft",
38066
+ title: "Draft support reply",
38067
+ provider: "helpdesk",
38068
+ description: "Call this to draft a first support response from approved knowledge-base content. Draft-only: it never sends or promises a fix.",
38069
+ default_scope_tier: "draft",
38070
+ scope_tiers: ["draft"],
38071
+ credential_required: true,
38072
+ default_access_policy: "always_allow"
38073
+ },
38074
+ {
38075
+ id: "crm.contacts.read",
38076
+ title: "Read CRM contacts",
38077
+ provider: "crm",
38078
+ description: "Call this to read assigned inbound leads and account records for enrichment and briefing. Read-only: it never changes lifecycle stage or sends outreach.",
38079
+ default_scope_tier: "read",
38080
+ scope_tiers: ["read"],
38081
+ credential_required: true,
38082
+ default_access_policy: "always_allow"
38083
+ },
38084
+ {
38085
+ id: "content.calendar.draft_update",
38086
+ title: "Draft content calendar",
38087
+ provider: "content",
38088
+ description: "Call this to draft content-calendar entries for review. Drafts only \u2014 it never publishes, schedules, or sends.",
38089
+ default_scope_tier: "draft",
38090
+ scope_tiers: ["draft"],
38091
+ credential_required: true,
38092
+ default_access_policy: "always_allow"
38093
+ },
38094
+ {
38095
+ id: "release.artifacts.read",
38096
+ title: "Read release artifacts",
38097
+ provider: "release",
38098
+ description: "Call this to read assigned release artifacts, checklists, and test results for review. Read-only: it never approves a release or changes production state.",
38099
+ default_scope_tier: "read",
38100
+ scope_tiers: ["read"],
38101
+ credential_required: true,
38102
+ default_access_policy: "always_allow"
38103
+ },
38104
+ {
38105
+ id: "issues.draft",
38106
+ title: "Draft tracker issue",
38107
+ provider: "issues",
38108
+ description: "Call this to draft a release-risk or tracker issue for human review. Draft-only: it never closes, assigns, or changes issue state autonomously.",
38109
+ default_scope_tier: "draft",
38110
+ scope_tiers: ["draft"],
38111
+ credential_required: true,
38112
+ default_access_policy: "always_allow"
38113
+ },
38114
+ {
38115
+ id: "signal.report",
38116
+ title: "Draft Signal reading",
38117
+ provider: "rost",
38118
+ description: "Call this to propose a draft Signal reading for one of the seat's agent-sourced measurables, with a cited source. Draft-only: a human confirms the reading; it never fabricates a value or changes a measurable definition.",
38119
+ default_scope_tier: "draft",
38120
+ scope_tiers: ["draft"],
38121
+ credential_required: false,
38122
+ default_access_policy: "always_allow"
37982
38123
  }
37983
38124
  ];
37984
38125
  var catalogById = new Map(CATALOG_ENTRIES.map((entry) => [entry.id, entry]));
@@ -42206,6 +42347,34 @@ var softwareGithubActionSchema = external_exports.enum([
42206
42347
  ]);
42207
42348
  var softwareGithubPolicyDecisionSchema = external_exports.enum(["allowed", "denied", "requires_human"]);
42208
42349
  var softwarePhaseRunStatusSchema = external_exports.enum(["pending", "running", "passed", "failed", "blocked", "skipped"]);
42350
+ var softwarePlanVersionStatusSchema = external_exports.enum([
42351
+ "draft",
42352
+ "needs_clarification",
42353
+ "ready_for_plan_review",
42354
+ "approved",
42355
+ "rejected"
42356
+ ]);
42357
+ var softwareChangesetSplitCriterionSchema = external_exports.enum([
42358
+ "single",
42359
+ "risk_isolation",
42360
+ "reviewability_budget",
42361
+ "deploy_ordering",
42362
+ "independent_revert"
42363
+ ]);
42364
+ var softwareChangesetStatusSchema = external_exports.enum(["planned", "in_progress", "in_review", "merged", "declined"]);
42365
+ var softwareTaskStatusSchema = external_exports.enum(["planned", "in_progress", "blocked", "done"]);
42366
+ var softwareConformanceSeveritySchema = external_exports.enum(["blocker", "major", "minor"]);
42367
+ var softwareConformanceCategorySchema = external_exports.enum([
42368
+ "scope_gap",
42369
+ "plan_deviation",
42370
+ "missing_test",
42371
+ "security_constraint",
42372
+ "secret_handling",
42373
+ "authority_limit",
42374
+ "skipped_scope",
42375
+ "other"
42376
+ ]);
42377
+ var softwareConformanceStatusSchema = external_exports.enum(["open", "accepted", "resolved"]);
42209
42378
  var softwareGateTypeSchema = external_exports.enum([
42210
42379
  "plan_review",
42211
42380
  "security_signoff",
@@ -42308,6 +42477,54 @@ var softwareGateSummarySchema = external_exports.object({
42308
42477
  rationale: external_exports.string().nullable(),
42309
42478
  created_at: external_exports.string()
42310
42479
  });
42480
+ var softwareChangesetSummarySchema = external_exports.object({
42481
+ id: uuid10,
42482
+ build_request_id: uuid10,
42483
+ ordinal: external_exports.number().int(),
42484
+ title: external_exports.string(),
42485
+ split_criterion: softwareChangesetSplitCriterionSchema,
42486
+ status: softwareChangesetStatusSchema,
42487
+ branch_name: external_exports.string().nullable(),
42488
+ pr_number: external_exports.number().int().nullable(),
42489
+ pr_url: external_exports.string().nullable(),
42490
+ pr_draft: external_exports.boolean(),
42491
+ inferred_risk: softwareRiskLevelSchema.nullable(),
42492
+ merged_at: external_exports.string().nullable(),
42493
+ created_at: external_exports.string()
42494
+ });
42495
+ var softwareTaskSummarySchema = external_exports.object({
42496
+ id: uuid10,
42497
+ build_request_id: uuid10,
42498
+ changeset_id: uuid10,
42499
+ plan_version_id: uuid10,
42500
+ ordinal: external_exports.number().int(),
42501
+ task_key: external_exports.string(),
42502
+ title: external_exports.string(),
42503
+ status: softwareTaskStatusSchema,
42504
+ depends_on: external_exports.array(external_exports.string()),
42505
+ parallelizable: external_exports.boolean(),
42506
+ est_turns: external_exports.number().int().nullable(),
42507
+ actual_turns: external_exports.number().int().nullable(),
42508
+ actual_files: external_exports.number().int().nullable(),
42509
+ started_at: external_exports.string().nullable(),
42510
+ completed_at: external_exports.string().nullable(),
42511
+ created_at: external_exports.string()
42512
+ });
42513
+ var softwarePlanConformanceFindingSummarySchema = external_exports.object({
42514
+ id: uuid10,
42515
+ build_request_id: uuid10,
42516
+ changeset_id: uuid10.nullable(),
42517
+ phase_run_id: uuid10.nullable(),
42518
+ plan_version_id: uuid10.nullable(),
42519
+ severity: softwareConformanceSeveritySchema,
42520
+ category: softwareConformanceCategorySchema,
42521
+ summary: external_exports.string(),
42522
+ detail: external_exports.string().nullable(),
42523
+ status: softwareConformanceStatusSchema,
42524
+ accepted_by_decision_id: uuid10.nullable(),
42525
+ resolved_at: external_exports.string().nullable(),
42526
+ created_at: external_exports.string()
42527
+ });
42311
42528
  var softwareAuthorityProfileSummarySchema = external_exports.object({
42312
42529
  id: uuid10,
42313
42530
  software_project_id: uuid10.nullable(),
@@ -42415,6 +42632,39 @@ var softwareGateDecideOutputSchema = external_exports.object({
42415
42632
  resolved_by_user_id: uuid10,
42416
42633
  decision_id: uuid10.nullable()
42417
42634
  });
42635
+ var forgeClarificationAnswer = external_exports.object({
42636
+ question: external_exports.string().trim().min(1).max(2e3),
42637
+ answer: external_exports.string().trim().min(1).max(4e3)
42638
+ }).strict();
42639
+ var softwareRequestAnswerClarificationInputSchema = external_exports.object({
42640
+ build_request_id: uuid10,
42641
+ answers: external_exports.array(forgeClarificationAnswer).min(1).max(50),
42642
+ // The planner marks the plan ready once its questions are resolved; the human/COS can
42643
+ // signal that here. Default false keeps the plan in needs_clarification.
42644
+ mark_ready_for_plan_review: external_exports.boolean().default(false)
42645
+ }).strict();
42646
+ var softwareRequestAnswerClarificationOutputSchema = external_exports.object({
42647
+ build_request_id: uuid10,
42648
+ plan_version_id: uuid10,
42649
+ status: softwarePlanVersionStatusSchema,
42650
+ answered_count: external_exports.number().int()
42651
+ });
42652
+ var softwarePlanApproveInputSchema = external_exports.object({
42653
+ build_request_id: uuid10,
42654
+ rationale: external_exports.string().trim().min(1).max(4e3).optional()
42655
+ }).strict();
42656
+ var softwarePlanRejectInputSchema = external_exports.object({
42657
+ build_request_id: uuid10,
42658
+ // A rejection must say why (it routes the request back to discovery/scoping).
42659
+ rationale: external_exports.string().trim().min(1).max(4e3)
42660
+ }).strict();
42661
+ var softwarePlanDecisionOutputSchema = external_exports.object({
42662
+ build_request_id: uuid10,
42663
+ plan_version_id: uuid10,
42664
+ status: external_exports.enum(["approved", "rejected"]),
42665
+ decision_id: uuid10,
42666
+ current_phase: softwarePhaseSchema
42667
+ });
42418
42668
  var softwareAuthorityProfileListInputSchema = external_exports.object({
42419
42669
  software_project_id: uuid10.nullable().optional()
42420
42670
  }).strict();
@@ -42650,14 +42900,63 @@ var softwareDeveloperTeamInstallOutputSchema = external_exports.object({
42650
42900
  });
42651
42901
  var forgeArtifactText = external_exports.string().trim().min(1).max(4e3);
42652
42902
  var forgeArtifactList = external_exports.array(forgeArtifactText).max(50).default([]);
42903
+ var forgeTaskKey = external_exports.string().trim().min(1).max(200);
42904
+ var forgeTaskTitle = external_exports.string().trim().min(1).max(300);
42905
+ var forgeTaskPathList = external_exports.array(external_exports.string().trim().min(1).max(300)).max(20).default([]);
42906
+ var forgeTaskVerificationList = external_exports.array(external_exports.string().trim().min(1).max(500)).max(25).default([]);
42907
+ var forgeTaskDefinitionSchema = external_exports.object({
42908
+ task_key: forgeTaskKey,
42909
+ title: forgeTaskTitle,
42910
+ // task_keys this task depends on (dependency DAG); disjoint-file tasks may be parallel.
42911
+ depends_on: external_exports.array(forgeTaskKey).max(50).default([]),
42912
+ parallelizable: external_exports.boolean().default(false),
42913
+ // ≤ ~40% of the phase session budget (headroom for fix loops); split above the ceiling.
42914
+ est_turns: external_exports.number().int().positive().max(1e3).nullable().default(null),
42915
+ files_likely: forgeTaskPathList,
42916
+ // verification commands + expected proof, stated BEFORE implementation.
42917
+ verification: forgeTaskVerificationList
42918
+ }).strict();
42919
+ var forgeChangesetPlanSchema = external_exports.object({
42920
+ ordinal: external_exports.number().int().positive().max(100),
42921
+ title: forgeTaskTitle,
42922
+ split_criterion: softwareChangesetSplitCriterionSchema.default("single"),
42923
+ // task_keys grouped into this PR-boundary unit.
42924
+ task_keys: external_exports.array(forgeTaskKey).max(200).default([])
42925
+ }).strict();
42653
42926
  var forgePlanArtifact = external_exports.object({
42654
42927
  scope: forgeArtifactText,
42655
42928
  plan_steps: forgeArtifactList,
42656
42929
  files_or_systems: forgeArtifactList,
42657
42930
  verification: forgeArtifactList,
42658
42931
  risks: forgeArtifactList,
42659
- clarifying_questions: forgeArtifactList
42660
- }).strict();
42932
+ clarifying_questions: forgeArtifactList,
42933
+ // DER-1197 changeset B: structured human answers to the clarifying questions, written
42934
+ // by software_factory.request.answer_clarification. Default [] keeps older artifacts valid.
42935
+ clarification_answers: external_exports.array(forgeClarificationAnswer).max(50).default([]),
42936
+ // DER-1197 decomposition. Default [] keeps pre-decomposition artifacts valid.
42937
+ tasks: external_exports.array(forgeTaskDefinitionSchema).max(200).default([]),
42938
+ changesets: external_exports.array(forgeChangesetPlanSchema).max(100).default([])
42939
+ }).strict().superRefine((artifact, ctx) => {
42940
+ const taskKeys = /* @__PURE__ */ new Set();
42941
+ for (const [i, task] of artifact.tasks.entries()) {
42942
+ if (taskKeys.has(task.task_key)) {
42943
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["tasks", i, "task_key"], message: `Duplicate task_key "${task.task_key}"` });
42944
+ }
42945
+ taskKeys.add(task.task_key);
42946
+ }
42947
+ const ordinals = /* @__PURE__ */ new Set();
42948
+ for (const [i, cs] of artifact.changesets.entries()) {
42949
+ if (ordinals.has(cs.ordinal)) {
42950
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changesets", i, "ordinal"], message: `Duplicate changeset ordinal ${cs.ordinal}` });
42951
+ }
42952
+ ordinals.add(cs.ordinal);
42953
+ for (const [j, key] of cs.task_keys.entries()) {
42954
+ if (!taskKeys.has(key)) {
42955
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changesets", i, "task_keys", j], message: `Changeset references unknown task_key "${key}"` });
42956
+ }
42957
+ }
42958
+ }
42959
+ });
42661
42960
  var forgeImplementationArtifact = external_exports.object({
42662
42961
  changes: forgeArtifactList,
42663
42962
  verification: forgeArtifactList,
@@ -43757,7 +44056,7 @@ Treat AICOS as a coordinator over the operating system. It can become more usefu
43757
44056
  order: 20,
43758
44057
  title: "Responsibility Graph playbook",
43759
44058
  summary: "How to build a functions-first graph with seats, owners, Stewards, vacancies, and clean authority.",
43760
- version: "2026-06-30.1",
44059
+ version: "2026-07-04.2",
43761
44060
  public: true,
43762
44061
  audiences: ["human", "cli", "mcp", "in_app_agent"],
43763
44062
  stages: ["graph_design", "staffing"],
@@ -43819,6 +44118,17 @@ The graph also carries a mission-control panel. It pulls the same operational st
43819
44118
 
43820
44119
  Agent seat pages show the operator-facing output trail, not just low-level run telemetry. The completed work area combines explicit \`agent_deliverables\`, successful \`work.log\` evidence, and recent successful run summaries into one readable list. Each item shows what was delivered, when it happened, what kind of work it was, and safe evidence links labelled as internal, Linear, GitHub, or external. Secret-shaped values are redacted before display, and run or task context is shown only when it belongs to the same seat.
43821
44120
 
44121
+ ## Read a human seat's page
44122
+
44123
+ A human seat's page opens on one computed answer line \u2014 for example "On track \u2014 4 of 5 measurables on target \xB7 1 held draft awaiting review" \u2014 instead of a wall of always-shown sections. Below it:
44124
+
44125
+ - **Exceptions are fully visible**: off-target measurables, escalations addressed to this seat as Steward (a held draft awaiting the Steward's decision), and open Friction filed by or owned by this seat all render as rows up top, each with a one-click way to act (log a reading, review, or resolve).
44126
+ - **Healthy content collapses to a count**: on-target measurables and measurables with no reading yet fold into one expandable "N measurables on target" row so the calm majority does not compete with the exceptions for attention.
44127
+ - **Three lens tabs** \u2014 Overview, Activity, Access \u2014 are views of the same seat, not separate sub-pages: Overview holds the answer line, exceptions, Purpose and accountabilities, and the Cascade goal summary; Activity is the event feed and the seat's task queue; Access is occupancy, Charter status, decision authority, and the permission manifest.
44128
+ - **One Manage drawer** replaces the inline staffing panel: it opens to Occupancy (staffing controls, when this seat is eligible to be staffed, and Let go), Charter (a link to the Charter Builder), and Measurables (a link to log a reading in Signal). Opening the drawer calls the exact same commands as before \u2014 nothing moved out of it changed behavior.
44129
+
44130
+ Agent seat pages keep their own dedicated Overview/Charter/Access layout with an always-visible fact sheet; see "Review an agent seat's delivered work" above for the agent-specific completed-work view.
44131
+
43822
44132
  ## First-pass structure
43823
44133
 
43824
44134
  Start with the operating root, then major functions, then the few seats that own the most important recurring work. Do not over-model. A graph with eight clear seats is better than a graph with thirty vague boxes.
@@ -44195,7 +44505,7 @@ The dry run is a real sandbox rehearsal, not a stamp. It executes a mock-provide
44195
44505
  order: 80,
44196
44506
  title: "Sync rhythm playbook",
44197
44507
  summary: "How Signal, Friction, Cascade, and Sync Briefs turn weekly meetings into decision time.",
44198
- version: "2026-06-30.1",
44508
+ version: "2026-07-04.1",
44199
44509
  public: true,
44200
44510
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44201
44511
  stages: ["operating_rhythm"],
@@ -44241,7 +44551,7 @@ The Sync Brief should answer:
44241
44551
  - Which agent escalations are aging?
44242
44552
  - Which goals lack current evidence?
44243
44553
 
44244
- On screen the brief reads in plain terms: Signal exceptions, goal progress, task review, ranked Friction, and agent activity. Where a section has no source data, it lists gaps to confirm \u2014 the missing inputs a human should know about before the meeting \u2014 rather than a blank section.
44554
+ On screen the brief reads exceptions-first. One computed answer line states what changed in plain terms, then every exception \u2014 Signal breaches, slipped or at-risk Cascade goals, escalation-grade Friction, agent Charter exceedances, and stalled or overdue tasks \u2014 is fully visible in a single agenda; the agenda is the exceptions, not a tour of every seat. Friction, task review, and agent activity collapse to an expandable count when they hold nothing above their escalation threshold, so the page stays calm when nothing there needs attention. Signal and Cascade have no such collapsed count by design: the brief only ever records exceptions for those two sections, not a reviewed total, so the screen never blends a live count with this frozen, already-compiled snapshot. Where a section has no source data at all, it lists gaps to confirm \u2014 the missing inputs a human should know about before the meeting \u2014 rather than a blank section; a brief with open gaps but no exception rows says so plainly instead of reporting an all-clear. Compile now and Run current Sync live behind one Manage control so the read view stays uncluttered.
44245
44555
 
44246
44556
  Before the first brief exists, the Sync pages are readiness views. They show the next scheduled compile and the source areas that will feed it: Signal, Cascade, Tasks, Friction, and Agents. Use those links to add missing source data, or use Compile now to run the same idempotent persisted compile operation immediately when the company uses company-wide Sync Briefs. If the company is configured for per-cluster briefs, compile the target cluster from CLI or MCP with a cluster id until the UI offers a cluster selector. Once a brief exists, the page shows whether it covers the current period, when it was compiled, and which sections were omitted or compiled with gaps.
44247
44557
 
@@ -44270,7 +44580,7 @@ Decisions should be recorded as human decisions. Handoffs should attach to seats
44270
44580
  order: 45,
44271
44581
  title: "How agents work",
44272
44582
  summary: "How {{brand}} agents operate inside seats, use Charters, report work, and escalate beyond authority.",
44273
- version: "2026-07-02.1",
44583
+ version: "2026-07-04.1",
44274
44584
  public: true,
44275
44585
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44276
44586
  stages: ["staffing", "operating_rhythm"],
@@ -44353,7 +44663,7 @@ The model is only ever offered the tools the seat's manifest grants \u2014 a den
44353
44663
 
44354
44664
  1. The manifest guard runs first and decides: allowed, denied, or must-escalate. A denied or must-escalate call never runs the action; an escalation is raised for a human.
44355
44665
  2. For an allowed call, the proposed input is validated against the tool's schema. Malformed input fails closed \u2014 the action does not run, and the model is told to correct it.
44356
- 3. The action runs bound to the seat's vaulted credential. The secret stays inside the call and never reaches the result, the audit row, the logs, or the model.
44666
+ 3. The action runs bound to the seat's vaulted credential. The secret stays inside the call and never reaches the result, the audit row, the logs, or the model. Brokered secret access applies the same rule on every attempt, including a denied or missing grant: it records a redacted, constraint-safe access-log entry and never opens the vault when the grant does not match.
44357
44667
  4. Every call \u2014 allowed, denied, escalated, or invalid \u2014 writes a tool-call audit row you can review.
44358
44668
 
44359
44669
  When operational evidence appears in the app, it is formatted for review instead of shown as primary raw JSON. Tool arguments, escalation evidence, status evidence, Sync inputs, and task context are summarized as labeled fields; secret-looking values stay redacted. Raw identifiers remain available only as supporting detail when they help an operator trace the record.
@@ -44472,7 +44782,7 @@ There is exactly one way to give a connected tool its credential, and it is the
44472
44782
  order: 47,
44473
44783
  title: "Available tools guide",
44474
44784
  summary: "How to think about tool categories available to seats and what each category should be used for.",
44475
- version: "2026-06-30.1",
44785
+ version: "2026-07-04.1",
44476
44786
  public: true,
44477
44787
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44478
44788
  stages: ["staffing"],
@@ -44510,6 +44820,8 @@ Start from the seat's responsibility, not the tool list. If a tool does not dire
44510
44820
 
44511
44821
  Skills are reusable procedures a seat can learn from; they are not tools and they never grant authority. A skill package may declare required or optional tool dependencies so setup can identify blockers before assignment. Those dependencies are checked against the discoverable \`tool.catalog\` ids and scope tiers, then compared to the seat's Charter permission manifest. Missing required tools block approval; optional tools produce setup warnings. A published skill version is immutable, so later corrections create a new version instead of rewriting what a run may have used.
44512
44822
 
44823
+ The catalog covers both the platform verbs (status, escalation, Signal readings) and the business tools the stock-agent templates grant \u2014 accounts-payable and receivable reads, AP-inbox and collections drafts, helpdesk triage, CRM reads, and content-calendar, release-artifact, and issue drafts. Each is listed at a conservative scope tier (read for the reads, draft for the drafts, where a draft never sends), and the business tools are credential-gated. Because a skill's required tool id is matched against these ids, a skill that requires one of them resolves against the catalog rather than reporting an unknown tool. Catalog membership is configuration only: it still confers no authority, and a listed id runs only once a live handler exists behind the seat's signed permission manifest, the server guard, and any required credential \u2014 the manifest and guard remain the control plane.
44824
+
44513
44825
  ## How agents should request tools
44514
44826
 
44515
44827
  Agents should explain the job, the required tool category, the minimum permission needed, and the escalation boundary. Humans approve or decline the request.
@@ -44525,7 +44837,7 @@ External connectors are being rolled out provider by provider, conservatively (r
44525
44837
  order: 48,
44526
44838
  title: "CLI and MCP installation guide",
44527
44839
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
44528
- version: "2026-07-04.14",
44840
+ version: "2026-07-04.15",
44529
44841
  public: true,
44530
44842
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44531
44843
  stages: ["company_setup", "staffing"],
@@ -45249,6 +45561,9 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
45249
45561
  | \`rost_show_a_forge_build_request\` | \`software_factory.request.show\` | The Forge request detail: the request, current phase, phase-run history, and gates. Read-only; requires the Forge add-on. | Tenant | Call with \`{"build_request_id":"<request-id>"}\`. |
45250
45562
  | \`rost_advance_a_forge_build_request_phase\` | \`software_factory.phase.advance\` | Advance a build request to its next phase; the server enforces the closed phase state machine and rejects an illegal transition. | Tenant | Call with \`{"build_request_id":"<request-id>","to_phase":"discovery_scoping"}\`. |
45251
45563
  | \`rost_decide_a_forge_gate\` | \`software_factory.gate.decide\` | A human approves or rejects a Forge gate; an agent caller routes to \`/approvals\` and can never self-approve. Sensitive gates record a linked human decision. | Tenant | Call with \`{"gate_id":"<gate-id>","decision":"approve"}\`; non-interactive callers receive a confirmation handoff. |
45564
+ | \`rost_answer_forge_plan_clarifications\` | \`software_factory.request.answer_clarification\` | Write structured human answers to a draft plan's clarifying questions and optionally mark it ready for plan review; answers append to the versioned planning artifact and never widen authority or automation mode. | Tenant | Call with \`{"build_request_id":"<request-id>","answers":[{"question":"Which database?","answer":"Postgres"}],"mark_ready_for_plan_review":true}\`. |
45565
+ | \`rost_approve_a_forge_plan\` | \`software_factory.plan.approve\` | A human approves the current plan at the plan_review gate; records a human decision and advances the request to implementation. Owner-only and human-gated. | Tenant-admin | Call with \`{"build_request_id":"<request-id>"}\`; non-interactive callers receive a confirmation handoff. |
45566
+ | \`rost_reject_a_forge_plan\` | \`software_factory.plan.reject\` | A human rejects the current plan (with a required rationale) and routes the request back to discovery/scoping for re-planning. Owner-only and human-gated. | Tenant-admin | Call with \`{"build_request_id":"<request-id>","rationale":"Scope too broad"}\`; non-interactive callers receive a confirmation handoff. |
45252
45567
  | \`rost_list_forge_authority_profiles\` | \`software_factory.authority_profile.list\` | List the tenant's Forge authority profiles (seat capability presets, read-only by default). Read-only; requires the Forge add-on. | Tenant | Call with \`{}\`. |
45253
45568
  | \`rost_create_a_forge_authority_profile\` | \`software_factory.authority_profile.create\` | Define a Forge authority profile (a named seat capability preset). Owner-only; defaults to the read_only preset. | Tenant-admin | Call with \`{"name":"Builder","preset":"contributor"}\`. |
45254
45569
  | \`rost_grant_forge_seat_authority\` | \`software_factory.authority.grant\` | Grant a seat a Forge authority profile on a project (seat \u2192 project \u2192 profile). Owner-only and human-gated; emits a durable authority-change event. | Tenant-admin | Call with \`{"software_project_id":"<project-id>","seat_id":"<seat-id>","authority_profile_id":"<profile-id>"}\`; non-interactive callers receive a confirmation handoff. |
@@ -45750,7 +46065,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
45750
46065
  order: 60,
45751
46066
  title: "Cascade guide",
45752
46067
  summary: "How to connect company goals to seat-level work without turning {{brand}} into a project-management tool.",
45753
- version: "2026-07-01.1",
46068
+ version: "2026-07-04.1",
45754
46069
  public: true,
45755
46070
  audiences: ["human", "cli", "mcp", "in_app_agent"],
45756
46071
  stages: ["operating_rhythm"],
@@ -45822,7 +46137,7 @@ On \`/cascade\`, the screen renders the full goal depth, not just one or two lev
45822
46137
 
45823
46138
  ## Goal progress and at-risk goals
45824
46139
 
45825
- A goal can carry a quantified progress (0-100) distinct from its on/off/done status. Report it with \`goal.set_progress\`; when an agent reports progress it lands as a proposal a human approves before the goal moves. A seat goal that has milestones takes its progress from milestone completion instead \u2014 the percentage is the share of its non-dropped milestones marked done, recomputed automatically as milestones complete, drop, or re-open. \`goal.list_at_risk\` projects which goals are off pace by comparing progress against the elapsed fraction of the cycle window (deterministic date math, no forecast model). Off-pace goals surface on \`/cascade\`, on the owner home, in the weekly Sync Brief, and as a weekly owner alert. Status-only goals (no progress recorded) are excluded from the projection and render as pending measurement, not as proven on track.
46140
+ A goal can carry a quantified progress (0-100) distinct from its on/off/done status. Report it with \`goal.set_progress\`; when an agent reports progress it lands as a proposal a human approves before the goal moves. A seat goal that has milestones takes its progress from milestone completion instead \u2014 the percentage is the share of its non-dropped milestones marked done, recomputed automatically as milestones complete, drop, or re-open. \`goal.list_at_risk\` projects which goals are off pace by comparing progress against the elapsed fraction of the cycle window (deterministic date math, no forecast model). Off-pace goals surface on \`/cascade\`, in the owner-only band on \`/home\`, in the weekly Sync Brief, and as a weekly owner alert. Status-only goals (no progress recorded) are excluded from the projection and render as pending measurement, not as proven on track.
45826
46141
 
45827
46142
  On human and function seat pages, goal visibility includes both direct goals and descendant seat goals from the Responsibility Graph subtree, so a manager can review team progress without double-owning the agent's work.
45828
46143
 
@@ -45856,7 +46171,7 @@ Agents can suggest commitments and report progress. They should not create a new
45856
46171
  order: 61,
45857
46172
  title: "Signal guide",
45858
46173
  summary: "How to define and read measurables so the company runs on evidence instead of status theater.",
45859
- version: "2026-07-04.1",
46174
+ version: "2026-07-04.2",
45860
46175
  public: true,
45861
46176
  audiences: ["human", "cli", "mcp", "in_app_agent"],
45862
46177
  stages: ["operating_rhythm"],
@@ -45917,11 +46232,11 @@ Avoid vanity numbers, manual-only status fields, and metrics nobody can act on.
45917
46232
 
45918
46233
  ## Run Signal without an agent
45919
46234
 
45920
- A human can run the whole loop from the Signal page. Each measurable has a "Log this period's number" control that records a human reading (the same \`signal.correct_reading\` path), and an "Add a measurable" form creates one against a seat (the \`measurable.create\` path). You do not need an agent to keep Signal current.
46235
+ A human can run the whole loop from the Signal page. The page opens answer-first \u2014 one computed line ("2 of 14 measurables need attention," or "All 14 measurables on target" when nothing needs you) with only the exception rows fully visible; healthy measurables collapse to a single "N on target" count you can expand. Every create/edit action lives behind the one "+ Add" button, which opens a drawer with four segments: **Log reading** records a human reading (the same \`signal.correct_reading\` path, or a row's own "Log reading" button seeds the drawer to that measurable), **New measurable** creates one against a seat (the \`measurable.create\` path, plus adopting from the template catalog), **Sources**, and **CSV import**. You do not need an agent to keep Signal current.
45921
46236
 
45922
46237
  ## Import a scorecard from CSV
45923
46238
 
45924
- To move off a spreadsheet or another operating tool, upload a scorecard export from the Signal page "Import from CSV" panel (the \`signal.import\` command, also available on CLI/MCP). Each row becomes a measurable owned by the seat whose name matches the row's owner, with its target, unit, direction, cadence, and trailing readings. Import is idempotent \u2014 re-importing upserts by period \u2014 and a row whose cadence conflicts with an existing measurable is reported and skipped, not overwritten.
46239
+ To move off a spreadsheet or another operating tool, open the Signal page's "+ Add" drawer and choose the "CSV import" segment (the \`signal.import\` command, also available on CLI/MCP). Each row becomes a measurable owned by the seat whose name matches the row's owner, with its target, unit, direction, cadence, and trailing readings. Import is idempotent \u2014 re-importing upserts by period \u2014 and a row whose cadence conflicts with an existing measurable is reported and skipped, not overwritten.
45925
46240
 
45926
46241
  ## Adopt a measurable template
45927
46242
 
@@ -45944,7 +46259,7 @@ Discovery always returns a \`recipe_presets\` array; it is empty when {{brand}}
45944
46259
 
45945
46260
  Recipes are validated data, never code: a read-only GET, a closed set of non-secret headers, and a restricted scalar path to the value. Every fetch passes one SSRF guard (HTTPS only, a steward-confirmed host allowlist set at bind, and a runtime check that the host does not resolve to a private address). The preset output never contains \`nango://\` handles, vault refs, tokens, or static credential headers. Deterministic pulls write \`integration\`-sourced readings on the measurable's cadence.
45946
46261
 
45947
- In the web app, the same workflow lives on \`/signal\` in the "Connect a self-filling source" panel. It shows each measurable's setup state \u2014 manual, agent draft, source draft, or auto-filled \u2014 plus the latest safe pull outcome when one exists. Choose a connected source, discover its non-secret metadata, preview a GET URL and value path, bind the working preview as a draft, then confirm the draft before scheduled pulls can write readings. The UI never displays credential material, vault refs, raw response bodies, or recipe secrets; if no connected source exists, connect one from Settings first.
46262
+ In the web app, the same workflow lives on \`/signal\` in the "+ Add" drawer's "Sources" segment. It shows each measurable's setup state \u2014 manual, agent draft, source draft, or auto-filled \u2014 plus the latest safe pull outcome when one exists. Choose a connected source, discover its non-secret metadata, preview a GET URL and value path, bind the working preview as a draft, then confirm the draft before scheduled pulls can write readings. The UI never displays credential material, vault refs, raw response bodies, or recipe secrets; if no connected source exists, connect one from Settings first.
45948
46263
 
45949
46264
  A source binding can inform a measurable without automatically changing a Cascade goal. The proven Leiluna Baserow binding uses \`informs\`. Use \`drives_status\` only after a second business anchor confirms that this exact measurable should compute a childless goal's status; otherwise the Signal should stay visible as evidence and exception context, not an automatic goal-status driver.
45950
46265
 
@@ -46044,7 +46359,7 @@ Resolving Friction should produce one of four outcomes: a decision, a task, a Ch
46044
46359
  order: 70,
46045
46360
  title: "Steward queue guide",
46046
46361
  summary: "How Stewards review escalations, approve agent boundaries, and keep agents accountable.",
46047
- version: "2026-06-27.2",
46362
+ version: "2026-07-04.1",
46048
46363
  public: true,
46049
46364
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46050
46365
  stages: ["staffing", "operating_rhythm"],
@@ -46083,6 +46398,8 @@ In the app, the evidence is shown as a legible card, not raw data: a proposed to
46083
46398
 
46084
46399
  When nothing is waiting, the Steward page still proves the governance loop. It shows which agent or hybrid seats the human stewards, how many escalations were raised or decided recently, and whether any are open. That empty state is an operating summary, not a dead end.
46085
46400
 
46401
+ The Steward page itself only lists charter-clause escalations (Queue, Escalations). Agent-raised confirmations that need a sign-off \u2014 Charter approvals, tool/permission grants, and other gated commands \u2014 live in the consolidated \`/approvals\` queue, one click away from a header link on the Steward page. See the confirmations guide for how that queue works.
46402
+
46086
46403
  ## How escalations reach you
46087
46404
 
46088
46405
  An escalation reaches you the same way no matter how the agent raised it \u2014 in a chat or CLI session, or on its own scheduled cloud run. When the agent stops at a boundary it opens the queue item and sends a notification to the accountable human along the steward chain, preferring a connected Slack channel and falling back to email. If no human occupies the agent's seat, the chain walks up to the next Steward. Delivery is idempotent: a retried run never notifies you twice for the same escalation, and the notification carries only summarized, redacted evidence \u2014 never secret material.
@@ -46456,7 +46773,7 @@ Every notification should include the seat, cause, evidence, and requested decis
46456
46773
  order: 75,
46457
46774
  title: "Local runner guide",
46458
46775
  summary: "How local agent sessions and runner surfaces should operate through {{brand}} without bypassing Charters or audit.",
46459
- version: "2026-07-04.1",
46776
+ version: "2026-07-04.3",
46460
46777
  public: true,
46461
46778
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46462
46779
  stages: ["staffing", "operating_rhythm"],
@@ -46510,6 +46827,10 @@ AICOS runner chat uses the same runner process but not the scheduled work-order
46510
46827
 
46511
46828
  When the Forge add-on is enabled, Forge phase work uses the same runner work-order lane. A Forge phase with an owning runner-agent Seat is linked to a normal \`work_orders\` row; the runner claims it, starts it, reports the result, and the server advances the linked phase. There is no separate local lease store.
46512
46829
 
46830
+ A build request decomposes into changesets and tasks tracked as queryable execution state. A changeset is the pull-request boundary and the revert unit (default one per request; additional changesets only on a named split criterion such as risk isolation or a reviewability-size budget). A task is one coding session inside a changeset, carrying its own verification and a per-task checkpoint that is the safe resume and pause boundary. Plan-conformance findings loop a changeset back to implementation; a finding can only be accepted, rather than resolved, through a recorded human decision.
46831
+
46832
+ The plan-review step is human-driven through tri-surface commands. A person answers a draft plan's clarifying questions and can mark it ready for review; approving the plan records a human decision and moves the request into implementation, while rejecting it records the decision and routes the request back to discovery and scoping for re-planning. Approving or rejecting a plan is owner-only and human-gated \u2014 an agent can never decide a plan on its own.
46833
+
46513
46834
  Runner heartbeats can include advisory capacity telemetry: OS, runner version, CPU and memory, active session count, detected local runtimes, and a model-account alias plus usage-limit state. Missing, empty, or whitespace model-account aliases are treated as the same \`default\` account so the scheduler can enforce a conservative one-session default-account cap. The scheduler also caps active runner work per tenant, project, runner, and model account.
46514
46835
 
46515
46836
  Forge context packets are deliberately bounded. The runner receives ids, phase state, authority-profile metadata, config metadata, and secret-grant metadata. It does not receive request free text, source refs, repo source dumps, raw secrets, vault refs, or a model-visible runner bearer secret. A short-lived seat-scoped MCP token is written only to the local MCP config file for the claimed turn.
@@ -48453,8 +48774,11 @@ var COMMAND_MANIFEST = [
48453
48774
  { "id": "software_factory.github.policy.upsert", "namespace": "software_factory", "action": "github.policy.upsert", "title": "Set a Forge GitHub automation policy", "description": "Set the server-side policy for GitHub actions and automation-mode ceilings. Owner-only and human-gated; production deploy remains human-gated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "software_project_id", "flag": "software-project-id", "type": "string", "required": true }, { "name": "authority_profile_id", "flag": "authority-profile-id", "type": "string", "required": false }, { "name": "automation_mode_ceiling", "flag": "automation-mode-ceiling", "type": "enum", "required": false, "enumValues": ["plan_only", "pr_only", "merge_after_checks", "deploy_preview", "deploy_production"] }, { "name": "allowed_actions", "flag": "allowed-actions", "type": "array", "required": true, "itemType": "string" }, { "name": "requires_human_for", "flag": "requires-human-for", "type": "array", "required": true, "itemType": "string" }], "hasComplexInput": false, "help": "Set Forge's server-side GitHub automation policy for actions, mode ceilings, and human-gated operations." },
48454
48775
  { "id": "software_factory.github.repository.unbind", "namespace": "software_factory", "action": "github.repository.unbind", "title": "Unbind a Forge GitHub repository", "description": "Remove a GitHub repository's Forge project binding. By default the repository stays connected (unbound) and can be re-bound later; pass disconnect to remove it entirely. Owner-only and human-gated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": false, "fields": [{ "name": "app_slug", "flag": "app-slug", "type": "string", "required": false }, { "name": "installation_id", "flag": "installation-id", "type": "integer", "required": true }, { "name": "repository_id", "flag": "repository-id", "type": "integer", "required": true }, { "name": "disconnect", "flag": "disconnect", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Remove a GitHub repository's Forge project binding; the repository stays connected for re-binding unless disconnect is set. Owner-only and human-gated." },
48455
48776
  { "id": "software_factory.phase.advance", "namespace": "software_factory", "action": "phase.advance", "title": "Advance a Forge build request phase", "description": "Advance a build request to the next phase, enforcing the closed phase state machine server-side (an illegal transition is rejected). Writes a phase-run row and updates the current phase. Entitlement-gated.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "build_request_id", "flag": "build-request-id", "type": "string", "required": true }, { "name": "to_phase", "flag": "to-phase", "type": "enum", "required": true, "enumValues": ["intake", "discovery_scoping", "plan_review", "implementation", "plan_conformance_review", "security_review", "qa_verification", "release_preview", "merge_or_deploy_gate", "closeout"] }, { "name": "owning_seat_id", "flag": "owning-seat-id", "type": "string", "required": false }, { "name": "note", "flag": "note", "type": "string", "required": false }], "hasComplexInput": false, "help": "Advance a build request to its next phase; the server enforces the closed phase state machine and rejects an illegal transition." },
48777
+ { "id": "software_factory.plan.approve", "namespace": "software_factory", "action": "plan.approve", "title": "Approve a Forge plan", "description": "A human approves the current plan at the plan_review gate; records a human decision and advances the request to implementation. Owner-only and human-gated (invariant #7).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "build_request_id", "flag": "build-request-id", "type": "string", "required": true }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "A human approves the current plan at the plan_review gate; records a human decision and advances the request to implementation. Owner-only and human-gated." },
48778
+ { "id": "software_factory.plan.reject", "namespace": "software_factory", "action": "plan.reject", "title": "Reject a Forge plan", "description": "A human rejects the current plan at the plan_review gate; records a human decision (with a required rationale) and routes the request back to discovery/scoping for re-planning. Owner-only and human-gated (invariant #7).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "build_request_id", "flag": "build-request-id", "type": "string", "required": true }, { "name": "rationale", "flag": "rationale", "type": "string", "required": true }], "hasComplexInput": false, "help": "A human rejects the current plan (with a required rationale) and routes the request back to discovery/scoping for re-planning. Owner-only and human-gated." },
48456
48779
  { "id": "software_factory.project.create", "namespace": "software_factory", "action": "project.create", "title": "Create a Forge project", "description": "Create an active Forge software project before binding repositories or opening build requests. Tenant-admin, human-gated, and entitlement-gated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "name", "flag": "name", "type": "string", "required": true }, { "name": "slug", "flag": "slug", "type": "string", "required": false }, { "name": "base_branch", "flag": "base-branch", "type": "string", "required": false }, { "name": "repo_ref", "flag": "repo-ref", "type": "string", "required": false }], "hasComplexInput": false, "help": "Create an active Forge software project before binding repositories or opening build requests. Tenant-admin and human-gated; requires the Forge add-on." },
48457
48780
  { "id": "software_factory.project.list", "namespace": "software_factory", "action": "project.list", "title": "List Forge projects", "description": "List active Forge software projects so a tenant can choose a project for build requests, GitHub repository bindings, and config. Read-only and entitlement-gated.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List active Forge software projects so a tenant can choose a project for build requests, GitHub repository bindings, and config. Read-only; requires the Forge add-on." },
48781
+ { "id": "software_factory.request.answer_clarification", "namespace": "software_factory", "action": "request.answer_clarification", "title": "Answer Forge plan clarifications", "description": "Write structured human answers to a draft plan's clarifying questions and optionally mark it ready for plan review. Answers append to the versioned planning artifact; this never widens authority or automation mode.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "build_request_id", "flag": "build-request-id", "type": "string", "required": true }, { "name": "mark_ready_for_plan_review", "flag": "mark-ready-for-plan-review", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Write structured human answers to a draft plan's clarifying questions and optionally mark it ready for plan review. Never widens authority or automation mode." },
48458
48782
  { "id": "software_factory.request.create", "namespace": "software_factory", "action": "request.create", "title": "Create a Forge build request", "description": "Open a governed Forge build request against a connected software project. Records the request plus its initial intake phase run. Entitlement-gated (Forge add-on); the title is untrusted display text, never an instruction.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "software_project_id", "flag": "software-project-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "source_channel", "flag": "source-channel", "type": "enum", "required": false, "enumValues": ["ui", "cli", "github_issue", "linear", "api"] }, { "name": "source_ref", "flag": "source-ref", "type": "string", "required": false }], "hasComplexInput": true, "help": "Open a governed Forge build request against a connected software project; the title is untrusted display text. Requires the Forge add-on." },
48459
48783
  { "id": "software_factory.request.list", "namespace": "software_factory", "action": "request.list", "title": "List Forge build requests", "description": "The Forge control-room board: the tenant's build requests with status, current phase, and risk/automation mode. Read-only, entitlement-gated.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "List Forge build requests (the control-room board) with status, current phase, and risk. Read-only; requires the Forge add-on." },
48460
48784
  { "id": "software_factory.request.show", "namespace": "software_factory", "action": "request.show", "title": "Show a Forge build request", "description": "The Forge request detail: the build request, its current phase, phase-run history, and gates. Read-only, entitlement-gated, tenant-scoped.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "build_request_id", "flag": "build-request-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Show a Forge build request's detail: current phase, phase-run history, and gates. Read-only; requires the Forge add-on." },