@rosthq/cli 0.7.21 → 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.
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,
@@ -42703,8 +43002,7 @@ var softwareGithubAutomationPolicyInputSchema = external_exports.object({
42703
43002
  message: "production deploy must remain human-gated"
42704
43003
  })
42705
43004
  }).strict();
42706
- var softwareGithubRepositoryBindingInputSchema = external_exports.object({
42707
- software_project_id: uuid10,
43005
+ var softwareGithubConnectedRepositoryInputSchema = external_exports.object({
42708
43006
  repository_id: external_exports.number().int().positive(),
42709
43007
  repository_name: external_exports.string().trim().min(1).max(255),
42710
43008
  repository_full_name: external_exports.string().trim().min(1).max(500),
@@ -42712,18 +43010,65 @@ var softwareGithubRepositoryBindingInputSchema = external_exports.object({
42712
43010
  default_branch: external_exports.string().trim().min(1).max(255).default("main"),
42713
43011
  permissions: external_exports.record(external_exports.string().min(1), external_exports.enum(["read", "write"])).default({})
42714
43012
  }).strict();
42715
- var softwareGithubInstallationBindInputSchema = external_exports.object({
43013
+ var softwareGithubInstallationConnectInputSchema = external_exports.object({
42716
43014
  app_slug: external_exports.string().trim().min(1).max(120).default("rost-forge"),
42717
43015
  installation_id: external_exports.number().int().positive(),
42718
43016
  account_login: external_exports.string().trim().min(1).max(255),
42719
43017
  account_id: external_exports.number().int().positive(),
42720
43018
  account_type: external_exports.string().trim().min(1).max(80),
42721
- repositories: external_exports.array(softwareGithubRepositoryBindingInputSchema).min(1).max(100)
43019
+ repositories: external_exports.array(softwareGithubConnectedRepositoryInputSchema).min(1).max(200)
43020
+ }).strict();
43021
+ var softwareGithubInstallationConnectOutputSchema = external_exports.object({
43022
+ github_installation_id: uuid10,
43023
+ repositories_connected: external_exports.number().int().nonnegative()
43024
+ });
43025
+ var softwareGithubRepositoryBindMappingSchema = external_exports.object({
43026
+ repository_id: external_exports.number().int().positive(),
43027
+ software_project_id: uuid10
43028
+ }).strict();
43029
+ var softwareGithubInstallationBindInputSchema = external_exports.object({
43030
+ app_slug: external_exports.string().trim().min(1).max(120).default("rost-forge"),
43031
+ installation_id: external_exports.number().int().positive(),
43032
+ bindings: external_exports.array(softwareGithubRepositoryBindMappingSchema).min(1).max(100)
42722
43033
  }).strict();
42723
43034
  var softwareGithubInstallationBindOutputSchema = external_exports.object({
42724
43035
  github_installation_id: uuid10,
42725
43036
  repositories_bound: external_exports.number().int().nonnegative()
42726
43037
  });
43038
+ var softwareGithubRepositoryUnbindInputSchema = external_exports.object({
43039
+ app_slug: external_exports.string().trim().min(1).max(120).default("rost-forge"),
43040
+ installation_id: external_exports.number().int().positive(),
43041
+ repository_id: external_exports.number().int().positive(),
43042
+ disconnect: external_exports.boolean().default(false)
43043
+ }).strict();
43044
+ var softwareGithubRepositoryUnbindOutputSchema = external_exports.object({
43045
+ repository_id: external_exports.number().int().positive(),
43046
+ status: external_exports.enum(["connected", "revoked"])
43047
+ });
43048
+ var softwareGithubInstallationListInputSchema = external_exports.object({ app_slug: external_exports.string().trim().min(1).max(120).default("rost-forge") }).strict();
43049
+ var softwareGithubInstallationRepositoryViewSchema = external_exports.object({
43050
+ repository_id: external_exports.number().int().positive(),
43051
+ repository_name: external_exports.string(),
43052
+ repository_full_name: external_exports.string(),
43053
+ private: external_exports.boolean(),
43054
+ default_branch: external_exports.string(),
43055
+ status: external_exports.enum(["connected", "active"]),
43056
+ software_project_id: uuid10.nullable(),
43057
+ software_project_name: external_exports.string().nullable(),
43058
+ software_project_slug: external_exports.string().nullable()
43059
+ });
43060
+ var softwareGithubInstallationViewSchema = external_exports.object({
43061
+ id: uuid10,
43062
+ installation_id: external_exports.number().int().positive(),
43063
+ account_login: external_exports.string(),
43064
+ account_id: external_exports.number().int().positive(),
43065
+ account_type: external_exports.string(),
43066
+ status: external_exports.enum(["active", "suspended", "revoked"]),
43067
+ repositories: external_exports.array(softwareGithubInstallationRepositoryViewSchema)
43068
+ });
43069
+ var softwareGithubInstallationListOutputSchema = external_exports.object({
43070
+ installations: external_exports.array(softwareGithubInstallationViewSchema)
43071
+ });
42727
43072
  var softwareGithubAutomationPolicyUpsertOutputSchema = external_exports.object({
42728
43073
  policy_id: uuid10,
42729
43074
  software_project_id: uuid10,
@@ -43711,7 +44056,7 @@ Treat AICOS as a coordinator over the operating system. It can become more usefu
43711
44056
  order: 20,
43712
44057
  title: "Responsibility Graph playbook",
43713
44058
  summary: "How to build a functions-first graph with seats, owners, Stewards, vacancies, and clean authority.",
43714
- version: "2026-06-30.1",
44059
+ version: "2026-07-04.2",
43715
44060
  public: true,
43716
44061
  audiences: ["human", "cli", "mcp", "in_app_agent"],
43717
44062
  stages: ["graph_design", "staffing"],
@@ -43773,6 +44118,17 @@ The graph also carries a mission-control panel. It pulls the same operational st
43773
44118
 
43774
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.
43775
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
+
43776
44132
  ## First-pass structure
43777
44133
 
43778
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.
@@ -44149,7 +44505,7 @@ The dry run is a real sandbox rehearsal, not a stamp. It executes a mock-provide
44149
44505
  order: 80,
44150
44506
  title: "Sync rhythm playbook",
44151
44507
  summary: "How Signal, Friction, Cascade, and Sync Briefs turn weekly meetings into decision time.",
44152
- version: "2026-06-30.1",
44508
+ version: "2026-07-04.1",
44153
44509
  public: true,
44154
44510
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44155
44511
  stages: ["operating_rhythm"],
@@ -44195,7 +44551,7 @@ The Sync Brief should answer:
44195
44551
  - Which agent escalations are aging?
44196
44552
  - Which goals lack current evidence?
44197
44553
 
44198
- 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.
44199
44555
 
44200
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.
44201
44557
 
@@ -44224,7 +44580,7 @@ Decisions should be recorded as human decisions. Handoffs should attach to seats
44224
44580
  order: 45,
44225
44581
  title: "How agents work",
44226
44582
  summary: "How {{brand}} agents operate inside seats, use Charters, report work, and escalate beyond authority.",
44227
- version: "2026-07-02.1",
44583
+ version: "2026-07-04.1",
44228
44584
  public: true,
44229
44585
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44230
44586
  stages: ["staffing", "operating_rhythm"],
@@ -44307,7 +44663,7 @@ The model is only ever offered the tools the seat's manifest grants \u2014 a den
44307
44663
 
44308
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.
44309
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.
44310
- 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.
44311
44667
  4. Every call \u2014 allowed, denied, escalated, or invalid \u2014 writes a tool-call audit row you can review.
44312
44668
 
44313
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.
@@ -44426,7 +44782,7 @@ There is exactly one way to give a connected tool its credential, and it is the
44426
44782
  order: 47,
44427
44783
  title: "Available tools guide",
44428
44784
  summary: "How to think about tool categories available to seats and what each category should be used for.",
44429
- version: "2026-06-30.1",
44785
+ version: "2026-07-04.1",
44430
44786
  public: true,
44431
44787
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44432
44788
  stages: ["staffing"],
@@ -44464,6 +44820,8 @@ Start from the seat's responsibility, not the tool list. If a tool does not dire
44464
44820
 
44465
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.
44466
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
+
44467
44825
  ## How agents should request tools
44468
44826
 
44469
44827
  Agents should explain the job, the required tool category, the minimum permission needed, and the escalation boundary. Humans approve or decline the request.
@@ -44479,7 +44837,7 @@ External connectors are being rolled out provider by provider, conservatively (r
44479
44837
  order: 48,
44480
44838
  title: "CLI and MCP installation guide",
44481
44839
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
44482
- version: "2026-07-04.11",
44840
+ version: "2026-07-04.15",
44483
44841
  public: true,
44484
44842
  audiences: ["human", "cli", "mcp", "in_app_agent"],
44485
44843
  stages: ["company_setup", "staffing"],
@@ -45203,6 +45561,9 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
45203
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>"}\`. |
45204
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"}\`. |
45205
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. |
45206
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 \`{}\`. |
45207
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"}\`. |
45208
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. |
@@ -45213,8 +45574,9 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
45213
45574
  | \`rost_list_forge_secret_requests\` | \`software_factory.secret_request.list\` | List missing-secret requests and their approval Task ids/statuses. It returns request metadata only \u2014 no secret values and no vault refs. | Tenant | Call with \`{}\` or \`{"status":"pending"}\`. |
45214
45575
  | \`rost_grant_a_forge_secret\` | \`software_factory.secret.grant\` | A human grants a seat scoped access to a project secret by vault ref (Postgres stores only the pointer, never secret material). Owner-only and human-gated. | Tenant-admin | Call with \`{"software_project_id":"<project-id>","environment":"production","seat_id":"<seat-id>","action":"vercel.env.sync","key_name":"OPENAI_API_KEY","vault_ref":"infisical://prod/OPENAI_API_KEY"}\`. |
45215
45576
  | \`rost_revoke_a_forge_secret_grant\` | \`software_factory.secret.revoke\` | Revoke a Forge secret grant (teardown \u2014 cut a compromised seat's access immediately). Owner-only and human-gated. | Tenant-admin | Call with \`{"grant_id":"<grant-id>"}\`; non-interactive callers receive a confirmation handoff. |
45216
- | \`rost_set_a_forge_github_automation_policy\` | \`software_factory.github.policy.upsert\` | Set the server-side GitHub automation policy: allowed actions, automation-mode ceiling, and operations requiring humans. Owner-only and human-gated. | Tenant-admin | Call with \`{"software_project_id":"<project-id>","automation_mode_ceiling":"pr_only","allowed_actions":["webhook_intake","installation_token"],"requires_human_for":["deploy_production"]}\`. |
45577
+ | \`rost_set_a_forge_github_automation_policy\` | \`software_factory.github.policy.upsert\` | Set the server-side GitHub automation policy: allowed actions, automation-mode ceiling, and operations requiring humans. The allowed-actions and human-gated-actions lists are stored server-side as structured JSON arrays. Owner-only and human-gated. | Tenant-admin | Call with \`{"software_project_id":"<project-id>","automation_mode_ceiling":"pr_only","allowed_actions":["webhook_intake","installation_token"],"requires_human_for":["deploy_production"]}\`. |
45217
45578
  | \`rost_create_a_forge_github_installation_token\` | \`software_factory.github.installation_token.create\` | Mint a short-lived GitHub App installation token for one bound repository after policy evaluation. The token is returned once and never stored. | Tenant | Call with \`{"software_project_id":"<project-id>","repository_id":789,"requested_actions":["read"],"requested_automation_mode":"plan_only"}\`. |
45579
+ | \`rost_list_forge_github_installations\` | \`software_factory.github.installation.list\` | List connected GitHub App installations and each repository's bind state (connected or active) with the Forge project it maps to. Read-only. | Tenant | Call with \`{}\`; a \`connected\` repository is verified but not yet bound to a project. |
45218
45580
  | \`rost_list_forge_runner_capacity\` | \`software_factory.capacity.list\` | List Forge runner capacity observations (advisory scheduling input only, never an authority input). Read-only; requires the Forge add-on. | Tenant | Call with \`{}\` or \`{"runner_id":"<runner-id>"}\`. |
45219
45581
 
45220
45582
  The web Forge control room at \`/forge\` uses the same command path for project selection, build request creation/list/detail reads, runner capacity, configuration status, and Developer Team install. The install button deliberately stages a pending confirmation before durable seats, Skills, authority grants, or live agent activation are applied; the install page states plainly that approving activates the 6 agents at a pull-request-only, observe-first posture and surfaces the company autonomy ceiling.
@@ -45225,7 +45587,7 @@ Forge repository access is through a tenant-bound GitHub App installation, not t
45225
45587
 
45226
45588
  Installation tokens are short lived and are not stored. The durable record is audit metadata: installation id, repository id, requested action, policy decision, reason, and related Forge request when one exists. GitHub issue titles, labels, and bodies are treated as untrusted source content; labels may request an automation mode, but only server-side Forge automation policy can allow \`pr_only\`, \`merge_after_checks\`, \`deploy_preview\`, or \`deploy_production\`. Production deploy remains human-gated.
45227
45589
 
45228
- Tenant GitHub App installation binding is intentionally not a CLI or MCP tool. Start at \`/forge/settings/github\`: the settings flow preserves the signed GitHub setup state, performs user-scoped GitHub App authorization, verifies admin repositories server-side, and then submits the governed bind command from the UI.
45590
+ Tenant GitHub App connect and bind are intentionally not CLI or MCP mutation tools; only the read \`software_factory.github.installation.list\` is exposed. Start at \`/forge/settings/github\`. Connect and bind are decoupled (DER-1281): user-scoped GitHub App authorization verifies the repositories you administer server-side and records them as **connected** (unbound, no project) via \`software_factory.github.installation.connect\` \u2014 this persists on any successful ownership proof, not only the one-shot post-install redirect, so a missed setup redirect is no longer fatal (a persistent "Verify ownership & add repositories" action re-runs it any time). Binding is a separate, always-available step: \`software_factory.github.installation.bind\` maps a connected repository to a Forge project (no GitHub re-authorization), and \`software_factory.github.repository.unbind\` returns a repository to connected/unbound (re-bindable) or disconnects it. Token minting and issue intake only ever see \`active\` (bound) repositories, so an unbound repository never enters automation.
45229
45591
 
45230
45592
  The Forge GitHub App itself is org-owned. App private key, webhook secret, and client secret values are platform-owned ROST operator credentials stored through the vault's reserved ROST system namespace, not through a customer tenant namespace or a tenant UUID deployment variable. Manifest conversion and manual secret storage also require the app-level \`GITHUB_APP_OPERATOR_EMAILS\` allowlist, which should contain only approved ROST platform operator emails. Deployment config carries only refs (\`GITHUB_APP_PRIVATE_KEY_REF\`, \`GITHUB_APP_WEBHOOK_SECRET_REF\`, \`GITHUB_APP_CLIENT_SECRET_REF\`); raw secret env vars are local/legacy compatibility only. The dogfood app is \`ROST Forge\` under \`agenticoperatingsystem\` with App ID \`4208495\` and Client ID \`Iv23liImH7qlBvXYQ0Wx\`. The base app omits \`administration\` and \`workflows\`; elevated repo creation or workflow mutation needs a separate human-approved power path.
45231
45593
 
@@ -45703,7 +46065,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
45703
46065
  order: 60,
45704
46066
  title: "Cascade guide",
45705
46067
  summary: "How to connect company goals to seat-level work without turning {{brand}} into a project-management tool.",
45706
- version: "2026-07-01.1",
46068
+ version: "2026-07-04.1",
45707
46069
  public: true,
45708
46070
  audiences: ["human", "cli", "mcp", "in_app_agent"],
45709
46071
  stages: ["operating_rhythm"],
@@ -45775,7 +46137,7 @@ On \`/cascade\`, the screen renders the full goal depth, not just one or two lev
45775
46137
 
45776
46138
  ## Goal progress and at-risk goals
45777
46139
 
45778
- 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.
45779
46141
 
45780
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.
45781
46143
 
@@ -45809,7 +46171,7 @@ Agents can suggest commitments and report progress. They should not create a new
45809
46171
  order: 61,
45810
46172
  title: "Signal guide",
45811
46173
  summary: "How to define and read measurables so the company runs on evidence instead of status theater.",
45812
- version: "2026-07-04.1",
46174
+ version: "2026-07-04.2",
45813
46175
  public: true,
45814
46176
  audiences: ["human", "cli", "mcp", "in_app_agent"],
45815
46177
  stages: ["operating_rhythm"],
@@ -45870,11 +46232,11 @@ Avoid vanity numbers, manual-only status fields, and metrics nobody can act on.
45870
46232
 
45871
46233
  ## Run Signal without an agent
45872
46234
 
45873
- 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.
45874
46236
 
45875
46237
  ## Import a scorecard from CSV
45876
46238
 
45877
- 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.
45878
46240
 
45879
46241
  ## Adopt a measurable template
45880
46242
 
@@ -45897,7 +46259,7 @@ Discovery always returns a \`recipe_presets\` array; it is empty when {{brand}}
45897
46259
 
45898
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.
45899
46261
 
45900
- 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.
45901
46263
 
45902
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.
45903
46265
 
@@ -45997,7 +46359,7 @@ Resolving Friction should produce one of four outcomes: a decision, a task, a Ch
45997
46359
  order: 70,
45998
46360
  title: "Steward queue guide",
45999
46361
  summary: "How Stewards review escalations, approve agent boundaries, and keep agents accountable.",
46000
- version: "2026-06-27.2",
46362
+ version: "2026-07-04.1",
46001
46363
  public: true,
46002
46364
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46003
46365
  stages: ["staffing", "operating_rhythm"],
@@ -46036,6 +46398,8 @@ In the app, the evidence is shown as a legible card, not raw data: a proposed to
46036
46398
 
46037
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.
46038
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
+
46039
46403
  ## How escalations reach you
46040
46404
 
46041
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.
@@ -46409,7 +46773,7 @@ Every notification should include the seat, cause, evidence, and requested decis
46409
46773
  order: 75,
46410
46774
  title: "Local runner guide",
46411
46775
  summary: "How local agent sessions and runner surfaces should operate through {{brand}} without bypassing Charters or audit.",
46412
- version: "2026-07-04.1",
46776
+ version: "2026-07-04.3",
46413
46777
  public: true,
46414
46778
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46415
46779
  stages: ["staffing", "operating_rhythm"],
@@ -46463,6 +46827,10 @@ AICOS runner chat uses the same runner process but not the scheduled work-order
46463
46827
 
46464
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.
46465
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
+
46466
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.
46467
46835
 
46468
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.
@@ -48400,11 +48768,17 @@ var COMMAND_MANIFEST = [
48400
48768
  { "id": "software_factory.developer_team.install", "namespace": "software_factory", "action": "developer_team.install", "title": "Install Forge Developer Team", "description": "Install AND activate the governed Forge Developer Team: 7 seats (1 human lead + 6 agents), first-party skills, authority presets, and a conservative token budget. Approving this ACTIVATES the 6 agents as live occupancies at a pr_only, observe-first posture: they open pull requests but never merge or deploy without a human. Entitlement-gated and human-confirmed.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "steward_seat_id", "flag": "steward-seat-id", "type": "string", "required": true }, { "name": "software_project_id", "flag": "software-project-id", "type": "string", "required": false }, { "name": "assign_skills", "flag": "assign-skills", "type": "boolean", "required": false }, { "name": "acknowledge_autonomy_ceiling", "flag": "acknowledge-autonomy-ceiling", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Install the governed Forge Developer Team template with seats, draft Charters, skills, project authority grants, and audit records. Tenant-admin and human-gated; creates no live agent occupancy." },
48401
48769
  { "id": "software_factory.gate.decide", "namespace": "software_factory", "action": "gate.decide", "title": "Decide a Forge gate", "description": "A human approves or rejects a Forge gate. The resolver is recorded (never an agent \u2014 invariant #7); sensitive gates (security sign-off, merge/deploy, authority change, production deploy) also write a linked human decision. Requires confirmation.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "gate_id", "flag": "gate-id", "type": "string", "required": true }, { "name": "decision", "flag": "decision", "type": "enum", "required": true, "enumValues": ["approve", "reject"] }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "A human approves or rejects a Forge gate; an agent caller routes to /approvals and can never self-approve. Sensitive gates record a human decision." },
48402
48770
  { "id": "software_factory.github.installation_token.create", "namespace": "software_factory", "action": "github.installation_token.create", "title": "Create a Forge GitHub installation token", "description": "Mint a short-lived GitHub App installation token for one bound repository after server-side policy evaluation. The token is returned once and never persisted.", "requiredScope": "tenant", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "software_project_id", "flag": "software-project-id", "type": "string", "required": true }, { "name": "repository_id", "flag": "repository-id", "type": "integer", "required": true }, { "name": "requested_actions", "flag": "requested-actions", "type": "array", "required": true, "itemType": "string" }, { "name": "requested_automation_mode", "flag": "requested-automation-mode", "type": "enum", "required": false, "enumValues": ["plan_only", "pr_only", "merge_after_checks", "deploy_preview", "deploy_production"] }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Mint a short-lived GitHub App installation token for one bound repository after policy evaluation; token material is returned once and never stored." },
48403
- { "id": "software_factory.github.installation.bind", "namespace": "software_factory", "action": "github.installation.bind", "title": "Bind a Forge GitHub installation", "description": "Bind a GitHub App installation and selected repositories to Forge projects from the authenticated Forge GitHub settings flow. Owner-only and human-gated; webhook payloads never supply tenant authority.", "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": "account_login", "flag": "account-login", "type": "string", "required": true }, { "name": "account_id", "flag": "account-id", "type": "integer", "required": true }, { "name": "account_type", "flag": "account-type", "type": "string", "required": true }], "hasComplexInput": true, "help": "Bind a GitHub App installation and selected repositories to Forge projects from the authenticated Forge GitHub settings flow. Owner-only and human-gated." },
48771
+ { "id": "software_factory.github.installation.bind", "namespace": "software_factory", "action": "github.installation.bind", "title": "Bind Forge GitHub repositories to projects", "description": "Bind already-connected GitHub repositories to Forge projects. Owner-only and human-gated; operates on repositories already verified and connected in this tenant, so no GitHub re-authorization is required. Available any time, add or re-map bindings.", "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 }], "hasComplexInput": true, "help": "Bind already-connected GitHub repositories to Forge projects from the Forge GitHub settings flow. Owner-only and human-gated; no GitHub re-authorization required." },
48772
+ { "id": "software_factory.github.installation.connect", "namespace": "software_factory", "action": "github.installation.connect", "title": "Connect a Forge GitHub installation", "description": "Record a proven GitHub App installation and its verified repositories as connected (unbound) so they can be bound to Forge projects later. Owner-only and human-gated; starts from the authenticated Forge GitHub settings flow. Idempotent \u2014 re-connecting reconciles metadata and never unbinds an already-bound repository.", "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": "account_login", "flag": "account-login", "type": "string", "required": true }, { "name": "account_id", "flag": "account-id", "type": "integer", "required": true }, { "name": "account_type", "flag": "account-type", "type": "string", "required": true }], "hasComplexInput": true, "help": "Record a verified GitHub App installation and its repositories as connected (unbound) so they can be bound to Forge projects later. Owner-only and human-gated." },
48773
+ { "id": "software_factory.github.installation.list", "namespace": "software_factory", "action": "github.installation.list", "title": "List Forge GitHub installations", "description": "List connected GitHub App installations and their repositories with bind state (connected or active) and the Forge project each bound repository maps to. Read-only; requires the Forge add-on.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "app_slug", "flag": "app-slug", "type": "string", "required": false }], "hasComplexInput": false, "help": "List connected GitHub App installations and each repository's bind state (connected or active) with the Forge project it maps to. Read-only." },
48404
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." },
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." },
48405
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." },
48406
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." },
48407
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." },
48408
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." },
48409
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." },
48410
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." },