@vecteur/cli 0.4.4 → 0.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vecteur/cli",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "vecteur": "bin/vecteur.js"
package/src/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
 
3
3
  import {
4
- ARTIFACT_MEDIA_TYPES, EVENT_KINDS, OWNER_CONTRACT_IDENTITY, validateAdmitted,
4
+ ARTIFACT_MEDIA_TYPES, EVENT_KINDS, OWNER_CONTRACT_IDENTITY, RETIRED_EVENT_KINDS, validateAdmitted,
5
5
  validateCustomerCostProjection, validateDeviceAuthorization, validateLimitDenial,
6
6
  validatePatCreated, validateProject, validateRunAck, validateAccount, validateQuotaDenial,
7
7
  RECOVERY_ACTIONS,
@@ -171,7 +171,8 @@ function exactObject(value, fields, code) {
171
171
  export function validateEvent(value, runId, expectedSeq) {
172
172
  exactObject(value, ["run_id", "seq", "kind", "payload"], "event_invalid");
173
173
  if (value.run_id !== runId || !Number.isInteger(value.seq) || value.seq !== expectedSeq ||
174
- !EVENT_KINDS.includes(value.kind) || !value.payload || typeof value.payload !== "object" ||
174
+ !(EVENT_KINDS.includes(value.kind) || RETIRED_EVENT_KINDS.includes(value.kind)) ||
175
+ !value.payload || typeof value.payload !== "object" ||
175
176
  Array.isArray(value.payload)) {
176
177
  throw new CliError("event_sequence_invalid", `Expected event sequence ${expectedSeq}`);
177
178
  }
package/src/contract.js CHANGED
@@ -1,10 +1,11 @@
1
1
  // GENERATED by scripts/gen-contract.mjs from owner TypeScript projections.
2
- export const OWNER_CONTRACT_IDENTITY = "api-sha256:5fe54838e61336acc12ae1ff2409970a21fac99c7457383ca9c7a6d8c6e882cc;run-wire-sha256:33813b7048376590b87c76d2bb5273199045b2a594b141ab63350aac92f9ede0";
2
+ export const OWNER_CONTRACT_IDENTITY = "api-sha256:0c052b44526d01d46a674d63ecd1bf8c0abf790e9b1bb9ba674c3e1f7acb9219;run-wire-sha256:30cae1b53b6142917e0f633d1f8edcbbe4d8eded0397cef91200dfddffd701d4";
3
3
  export const RECOVERY_ACTIONS = Object.freeze({"delete_project":{"label":"Delete a project","href":"/projects"},"upgrade_plan":{"label":"Upgrade your plan","href":"/dashboard/billing"},"wait_for_reset":{"label":"Wait until the UTC reset","href":null}});
4
- export const EVENT_KINDS = Object.freeze(["source","step_started","step_finished","synthesis","artifact","cta","state_advanced","terminal","heartbeat","assistant_delta","step_label","context_frame","knowledge_binding","engineering_projection","provider_attempt","clarification"]);
4
+ export const EVENT_KINDS = Object.freeze(["source","step_started","step_finished","tool_call","tool_result","synthesis","artifact","terminal","heartbeat","assistant_delta","knowledge_binding","engineering_projection","provider_attempt","clarification"]);
5
+ export const RETIRED_EVENT_KINDS = Object.freeze(["context_frame","cta","step_label"]);
5
6
  export const TERMINAL_FIELDS = Object.freeze(["answer","defect","deliverable_asked","evidence_dag","instruction_source","intent","missing_input_need","missing_inputs","provider_retry_offer","recovery","refusal_unfounded","state","steps","unmet_wanted"]);
6
- export const ARTIFACT_MEDIA_TYPES = Object.freeze({"code":"text/plain","csv":"text/csv","docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","drive":"application/vnd.google-drive","html":"text/html","md":"text/markdown","pdf":"application/pdf","xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
7
- export const TERMINAL_RECOVERY_DECLARATIONS = Object.freeze({"artifact_publication_missing":[["start_run",["project_id"]]],"artifact_store_unavailable":[["start_run",["project_id"]]],"budget_exhausted":[["start_run",["project_id"]]],"cancelled":[["start_run",["project_id"]]],"cause_unrecorded":[["start_run",["project_id"]]],"clarification_custody_invalid":[["start_run",["project_id"]]],"clarification_custody_lost":[["start_run",["project_id"]]],"clarification_resume_invalid":[["start_run",["project_id"]]],"clarification_unpersisted":[["start_run",["project_id"]]],"context_unselected":[["start_run",["project_id"]]],"credential_class_disclosure":[["start_run",["project_id"]]],"deliverable_missing":[["start_run",["project_id"]]],"design_state_missing":[["start_run",["project_id"]]],"evidence_admission_invalid":[["start_run",["project_id"]]],"evidence_artifact_invalid":[["start_run",["project_id"]]],"evidence_artifact_unbound":[["start_run",["project_id"]]],"evidence_binding_unresolved":[["start_run",["project_id"]]],"evidence_context_invalid":[["start_run",["project_id"]]],"evidence_extract_unreached":[["start_run",["project_id"]]],"evidence_missing":[["start_run",["project_id"]]],"evidence_owner_receipt_mismatch":[["start_run",["project_id"]]],"evidence_owner_receipt_missing":[["start_run",["project_id"]]],"evidence_payload_invalid":[["start_run",["project_id"]]],"evidence_reached_invalid":[["start_run",["project_id"]]],"evidence_replay_invalid":[["start_run",["project_id"]]],"evidence_run_mismatch":[["start_run",["project_id"]]],"evidence_seal_collision":[["start_run",["project_id"]]],"evidence_selected_unreached":[["start_run",["project_id"]]],"execution_route_invalid":[["start_run",["project_id"]]],"executor_root_invalid":[["start_run",["project_id"]]],"extraction_offer_invalid":[["start_run",["project_id"]]],"extraction_offer_tampered":[["start_run",["project_id"]]],"fact_support_unread":[["start_run",["project_id"]]],"harness_arm_invalid":[["start_run",["project_id"]]],"harness_event_unmapped":[["start_run",["project_id"]]],"harness_exited":[["start_run",["project_id"]]],"harness_mapping_failed":[["start_run",["project_id"]]],"harness_session_invalid":[["start_run",["project_id"]]],"harness_session_missing":[["start_run",["project_id"]]],"harness_timeout":[["start_run",["project_id"]]],"infeasible_physics":[["start_run",["project_id"]]],"lease_interval_invalid":[["start_run",["project_id"]]],"ledger_malformed":[["start_run",["project_id"]]],"max_tokens":[["start_run",["project_id"]]],"no_facts":[["start_run",["project_id"]]],"not_a_decision_i_can_make":[["start_run",["project_id"]]],"out_of_physics":[["start_run",["project_id"]]],"profile_eligibility_changed":[["start_run",["project_id"]]],"prompt_provenance_unavailable":[["start_run",["project_id"]]],"provider_budget_exhausted":[["start_run",["project_id"]]],"provider_budget_missing":[["start_run",["project_id"]]],"provider_budget_unavailable":[["start_run",["project_id"]]],"provider_relay_absent":[["start_run",["project_id"]]],"provider_route_control_invalid":[["start_run",["project_id"]]],"provider_route_exhausted":[["start_run",["project_id"]],["retry_run",["source_run_id","offer_id","generation"]]],"provider_route_failure_unobserved":[["start_run",["project_id"]]],"provider_route_reconciliation_invalid":[["start_run",["project_id"]]],"provider_route_restart_terminal":[["start_run",["project_id"]]],"provider_training_opted_in":[["start_run",["project_id"]]],"publish_seal_missing":[["start_run",["project_id"]]],"refusal_unfounded":[["start_run",["project_id"]]],"replay_capture_digest_mismatch":[["start_run",["project_id"]]],"replay_capture_invalid":[["start_run",["project_id"]]],"replay_config_incomplete":[["start_run",["project_id"]]],"replay_failed":[["start_run",["project_id"]]],"replay_no_requests":[["start_run",["project_id"]]],"replay_patch_invalid":[["start_run",["project_id"]]],"replay_plugin_absent":[["start_run",["project_id"]]],"replay_provider_socket":[["start_run",["project_id"]]],"replay_receipt_invalid":[["start_run",["project_id"]]],"replay_receipt_owner_chown":[["start_run",["project_id"]]],"replay_receipt_owner_incomplete":[["start_run",["project_id"]]],"replay_receipt_owner_invalid":[["start_run",["project_id"]]],"replay_request_observation_count":[["start_run",["project_id"]]],"replay_request_observation_invalid":[["start_run",["project_id"]]],"replay_request_observation_missing":[["start_run",["project_id"]]],"replay_request_owner_chown":[["start_run",["project_id"]]],"replay_socket_observation_invalid":[["start_run",["project_id"]]],"replay_socket_observation_missing":[["start_run",["project_id"]]],"replay_socket_owner_chown":[["start_run",["project_id"]]],"run_database_capability_refused":[["start_run",["project_id"]]],"runtime_unavailable":[["start_run",["project_id"]]],"sealed_contract_violated":[["start_run",["project_id"]]],"sealed_file_missing":[["start_run",["project_id"]]],"seat_patch_absent":[["start_run",["project_id"]]],"seat_patch_drift":[["start_run",["project_id"]]],"selection_admission_invalid":[["start_run",["project_id"]]],"selection_context_invalid":[["start_run",["project_id"]]],"selection_receipt_conflict":[["start_run",["project_id"]]],"selection_receipt_invalid":[["start_run",["project_id"]]],"selection_receipt_missing":[["start_run",["project_id"]]],"selection_required":[["start_run",["project_id"]]],"state_corrupt":[["start_run",["project_id"]]],"state_file_invalid":[["start_run",["project_id"]]],"state_invalid":[["start_run",["project_id"]]],"state_payload_overflow":[["start_run",["project_id"]]],"state_unencodable":[["start_run",["project_id"]]],"state_version_unknown":[["start_run",["project_id"]]],"unreceipted_numbers":[["start_run",["project_id"]]],"usage_egress_mismatch":[["start_run",["project_id"]]],"wanted_not_computed":[["start_run",["project_id"]]],"web_without_miss":[["start_run",["project_id"]]]});
7
+ export const ARTIFACT_MEDIA_TYPES = Object.freeze({"binary":"application/octet-stream","code":"text/plain","csv":"text/csv","docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","drive":"application/vnd.google-drive","html":"text/html","jpeg":"image/jpeg","json":"application/json","md":"text/markdown","pdf":"application/pdf","png":"image/png","svg":"image/svg+xml","xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
8
+ export const TERMINAL_RECOVERY_DECLARATIONS = Object.freeze({"artifact_publication_missing":[["start_run",["project_id"]]],"artifact_store_unavailable":[["start_run",["project_id"]]],"budget_exhausted":[["start_run",["project_id"]]],"cancelled":[["start_run",["project_id"]]],"cause_unrecorded":[["start_run",["project_id"]]],"clarification_custody_invalid":[["start_run",["project_id"]]],"clarification_custody_lost":[["start_run",["project_id"]]],"clarification_resume_invalid":[["start_run",["project_id"]]],"clarification_unpersisted":[["start_run",["project_id"]]],"context_unselected":[["start_run",["project_id"]]],"credential_class_disclosure":[["start_run",["project_id"]]],"deliverable_missing":[["start_run",["project_id"]]],"design_state_missing":[["start_run",["project_id"]]],"evidence_admission_invalid":[["start_run",["project_id"]]],"evidence_artifact_invalid":[["start_run",["project_id"]]],"evidence_artifact_unbound":[["start_run",["project_id"]]],"evidence_binding_unresolved":[["start_run",["project_id"]]],"evidence_context_invalid":[["start_run",["project_id"]]],"evidence_extract_unreached":[["start_run",["project_id"]]],"evidence_missing":[["start_run",["project_id"]]],"evidence_owner_receipt_mismatch":[["start_run",["project_id"]]],"evidence_owner_receipt_missing":[["start_run",["project_id"]]],"evidence_payload_invalid":[["start_run",["project_id"]]],"evidence_reached_invalid":[["start_run",["project_id"]]],"evidence_replay_invalid":[["start_run",["project_id"]]],"evidence_run_mismatch":[["start_run",["project_id"]]],"evidence_seal_collision":[["start_run",["project_id"]]],"evidence_selected_unreached":[["start_run",["project_id"]]],"execution_route_invalid":[["start_run",["project_id"]]],"executor_root_invalid":[["start_run",["project_id"]]],"extraction_offer_invalid":[["start_run",["project_id"]]],"extraction_offer_tampered":[["start_run",["project_id"]]],"fact_support_unread":[["start_run",["project_id"]]],"harness_arm_invalid":[["start_run",["project_id"]]],"harness_event_unmapped":[["start_run",["project_id"]]],"harness_exited":[["start_run",["project_id"]]],"harness_mapping_failed":[["start_run",["project_id"]]],"harness_session_invalid":[["start_run",["project_id"]]],"harness_session_missing":[["start_run",["project_id"]]],"harness_timeout":[["start_run",["project_id"]]],"infeasible_physics":[["start_run",["project_id"]]],"lab_denied":[["start_run",["project_id"]]],"lab_failed":[["start_run",["project_id"]]],"lab_not_reproduced":[["start_run",["project_id"]]],"lease_interval_invalid":[["start_run",["project_id"]]],"ledger_malformed":[["start_run",["project_id"]]],"max_tokens":[["start_run",["project_id"]]],"no_facts":[["start_run",["project_id"]]],"not_a_decision_i_can_make":[["start_run",["project_id"]]],"out_of_physics":[["start_run",["project_id"]]],"profile_eligibility_changed":[["start_run",["project_id"]]],"prompt_provenance_unavailable":[["start_run",["project_id"]]],"provider_budget_exhausted":[["start_run",["project_id"]]],"provider_budget_missing":[["start_run",["project_id"]]],"provider_budget_unavailable":[["start_run",["project_id"]]],"provider_relay_absent":[["start_run",["project_id"]]],"provider_route_control_invalid":[["start_run",["project_id"]]],"provider_route_exhausted":[["start_run",["project_id"]],["retry_run",["source_run_id","offer_id","generation"]]],"provider_route_failure_unobserved":[["start_run",["project_id"]]],"provider_route_reconciliation_invalid":[["start_run",["project_id"]]],"provider_route_restart_terminal":[["start_run",["project_id"]]],"provider_training_opted_in":[["start_run",["project_id"]]],"publish_seal_missing":[["start_run",["project_id"]]],"refusal_unfounded":[["start_run",["project_id"]]],"replay_capture_digest_mismatch":[["start_run",["project_id"]]],"replay_capture_invalid":[["start_run",["project_id"]]],"replay_config_incomplete":[["start_run",["project_id"]]],"replay_failed":[["start_run",["project_id"]]],"replay_no_requests":[["start_run",["project_id"]]],"replay_patch_invalid":[["start_run",["project_id"]]],"replay_plugin_absent":[["start_run",["project_id"]]],"replay_provider_socket":[["start_run",["project_id"]]],"replay_receipt_invalid":[["start_run",["project_id"]]],"replay_receipt_owner_chown":[["start_run",["project_id"]]],"replay_receipt_owner_incomplete":[["start_run",["project_id"]]],"replay_receipt_owner_invalid":[["start_run",["project_id"]]],"replay_request_observation_count":[["start_run",["project_id"]]],"replay_request_observation_invalid":[["start_run",["project_id"]]],"replay_request_observation_missing":[["start_run",["project_id"]]],"replay_request_owner_chown":[["start_run",["project_id"]]],"replay_socket_observation_invalid":[["start_run",["project_id"]]],"replay_socket_observation_missing":[["start_run",["project_id"]]],"replay_socket_owner_chown":[["start_run",["project_id"]]],"row_budget":[["start_run",["project_id"]]],"run_database_capability_refused":[["start_run",["project_id"]]],"runtime_unavailable":[["start_run",["project_id"]]],"sealed_contract_violated":[["start_run",["project_id"]]],"sealed_file_missing":[["start_run",["project_id"]]],"seat_patch_absent":[["start_run",["project_id"]]],"seat_patch_drift":[["start_run",["project_id"]]],"selection_admission_invalid":[["start_run",["project_id"]]],"selection_context_invalid":[["start_run",["project_id"]]],"selection_receipt_conflict":[["start_run",["project_id"]]],"selection_receipt_invalid":[["start_run",["project_id"]]],"selection_receipt_missing":[["start_run",["project_id"]]],"selection_required":[["start_run",["project_id"]]],"state_corrupt":[["start_run",["project_id"]]],"state_file_invalid":[["start_run",["project_id"]]],"state_invalid":[["start_run",["project_id"]]],"state_payload_overflow":[["start_run",["project_id"]]],"state_unencodable":[["start_run",["project_id"]]],"state_version_unknown":[["start_run",["project_id"]]],"unreceipted_numbers":[["start_run",["project_id"]]],"usage_egress_mismatch":[["start_run",["project_id"]]],"wall_budget":[["start_run",["project_id"]]],"wanted_not_computed":[["start_run",["project_id"]]]});
8
9
  export const ORIGIN_KINDS = Object.freeze(["user","hypothesis","derived","knowledge","file","catalog","default"]);
9
10
  export const ORIGIN_WORD = Object.freeze({"user":"your brief","hypothesis":"assumed","derived":"derived","knowledge":"Vecteur knowledge","file":"your file","catalog":"catalogue","default":"default","unattributed":"unstated"});
10
11
  const shape=(v,r,o=[])=>!!v&&typeof v==="object"&&!Array.isArray(v)&&r.every(k=>Object.hasOwn(v,k))&&Object.keys(v).every(k=>r.includes(k)||o.includes(k));
@@ -26,7 +27,7 @@ const ownerCostScope=v=>shape(v,["type","id"],[])&&((v.type==="organization"||v.
26
27
  const ownerCostBindingScope=v=>shape(v,["kind","scope"],[])&&((v.kind==="platform_tier"||v.kind==="restriction"||v.kind==="unlimited"))&&(ownerCostScope(v.scope));
27
28
  const ownerCustomerCostDisplay=v=>shape(v,["currency","used","scope_used","limit","remaining"],[])&&((v.currency==="EUR"||v.currency==="USD"))&&((typeof v.used==="string"||v.used===null))&&((typeof v.scope_used==="string"||v.scope_used===null))&&((typeof v.limit==="string"||v.limit===null))&&((typeof v.remaining==="string"||v.remaining===null));
28
29
  const ownerLimitDenial=v=>shape(v,["schema","scope","binding_scope","period_start","period_end","unit","used","scope_used","limit","remaining","reset_at","coverage","display","dimension","recovery"],[])&&(v.schema==="vecteur.customer-cost-projection.v1")&&(ownerCostScope(v.scope))&&(ownerCostBindingScope(v.binding_scope))&&(Number.isFinite(v.period_start))&&(Number.isFinite(v.period_end))&&(v.unit==="customer_gross_microusd")&&((Number.isFinite(v.used)||v.used===null))&&((Number.isFinite(v.scope_used)||v.scope_used===null))&&((Number.isFinite(v.limit)||v.limit===null))&&((Number.isFinite(v.remaining)||v.remaining===null))&&(Number.isFinite(v.reset_at))&&((v.coverage==="complete"||v.coverage==="incomplete"))&&(ownerCustomerCostDisplay(v.display))&&(v.dimension==="customer_cost")&&(Array.isArray(v.recovery)&&v.recovery.every(x=>(x==="wait_for_reset"||x==="upgrade_plan")));
29
- const ownerArtifact=v=>shape(v,["id","kind","cas_ref","filename"],["produced_by_step","from_input_rows","build_receipt_id","output_index"])&&(typeof v.id==="string")&&((v.kind==="docx"||v.kind==="xlsx"||v.kind==="pdf"||v.kind==="md"||v.kind==="csv"||v.kind==="html"||v.kind==="code"||v.kind==="drive"))&&(ownerCasRef(v.cas_ref))&&(typeof v.filename==="string")&&(v.produced_by_step===undefined||(typeof v.produced_by_step==="string"||v.produced_by_step===null))&&(v.from_input_rows===undefined||(Array.isArray(v.from_input_rows)&&v.from_input_rows.every(x=>typeof x==="string")||v.from_input_rows===null))&&(v.build_receipt_id===undefined||(typeof v.build_receipt_id==="string"||v.build_receipt_id===null))&&(v.output_index===undefined||(Number.isFinite(v.output_index)||v.output_index===null));
30
+ const ownerArtifact=v=>shape(v,["id","kind","cas_ref","filename"],["produced_by_step","from_input_rows","build_receipt_id","output_index","path","revision","origin_call_id","preview","supersedes_cas_ref","execution_id"])&&(typeof v.id==="string")&&((v.kind==="docx"||v.kind==="xlsx"||v.kind==="pdf"||v.kind==="md"||v.kind==="csv"||v.kind==="html"||v.kind==="code"||v.kind==="drive"||v.kind==="png"||v.kind==="jpeg"||v.kind==="svg"||v.kind==="json"||v.kind==="binary"))&&(ownerCasRef(v.cas_ref))&&(typeof v.filename==="string")&&(v.produced_by_step===undefined||(typeof v.produced_by_step==="string"||v.produced_by_step===null))&&(v.from_input_rows===undefined||(Array.isArray(v.from_input_rows)&&v.from_input_rows.every(x=>typeof x==="string")||v.from_input_rows===null))&&(v.build_receipt_id===undefined||(typeof v.build_receipt_id==="string"||v.build_receipt_id===null))&&(v.output_index===undefined||(Number.isFinite(v.output_index)||v.output_index===null))&&(v.path===undefined||(typeof v.path==="string"||v.path===null))&&(v.revision===undefined||(Number.isFinite(v.revision)||v.revision===null))&&(v.origin_call_id===undefined||(typeof v.origin_call_id==="string"||v.origin_call_id===null))&&(v.preview===undefined||(v.preview==="text"||v.preview==="code"||v.preview==="csv"||v.preview==="table"||v.preview==="series"||v.preview==="image"||v.preview==="html"||v.preview==="docx"||v.preview==="xlsx"||v.preview==="pdf"||v.preview==="binary"||v.preview===null))&&(v.supersedes_cas_ref===undefined||(ownerCasRef(v.supersedes_cas_ref)||v.supersedes_cas_ref===null))&&(v.execution_id===undefined||(typeof v.execution_id==="string"||v.execution_id===null));
30
31
  const ownerCasRef=v=>typeof v==="string";
31
32
  const ownerSynthesis=v=>shape(v,["answer","core","terminal"],[])&&(typeof v.answer==="string")&&(v.core!==null&&typeof v.core==="object"&&!Array.isArray(v.core)&&Object.values(v.core).every(x=>true))&&((v.terminal==="ok"||v.terminal==="partial"||v.terminal==="blocked"||v.terminal==="refused"||v.terminal==="infeasible_physics"||v.terminal==="capability_gap"));
32
33
  export const validateAccount=v=>ownerAccount(v)&&[v.id,v.email,v.display_name,v.org_id].every(text)&&v.workspaces.every(w=>[w.id,w.org_id,w.name].every(text))&&integer(v.entitlements.active_projects.current)&&v.entitlements.active_projects.current>=0&&(v.entitlements.active_projects.maximum===null||(integer(v.entitlements.active_projects.maximum)&&v.entitlements.active_projects.maximum>=0));
@@ -45,281 +46,3 @@ const usage=(v)=>exact(v,["coverage","provider_id","model_id","observed_at","bil
45
46
  export const validateAdmitted=(v)=>shape(v,["run_id","state_hash","result_hash","requested_route_id","profile","terminal","usage","events"],["duration_seconds"])&&[v.run_id,v.state_hash,v.result_hash,v.requested_route_id,v.profile].every(text)&&["ok","partial","blocked","refused","infeasible_physics","capability_gap"].includes(v.terminal)&&usage(v.usage)&&Array.isArray(v.events)&&(v.duration_seconds===undefined||v.duration_seconds===null||(integer(v.duration_seconds)&&v.duration_seconds>=0));
46
47
  export const validatePatCreated=(v)=>exact(v,["id","name","token","prefix","project_id","scopes","created_at","expires_at"])&&[v.id,v.name,v.token,v.prefix].every(text)&&(v.project_id===null||text(v.project_id))&&Array.isArray(v.scopes)&&v.scopes.every(s=>["project:read","project:execute"].includes(s))&&integer(v.created_at)&&integer(v.expires_at);
47
48
  export const validateDeviceAuthorization=(v)=>exact(v,["device_code","user_code","verification_uri","verification_uri_complete","expires_at","interval"])&&[v.device_code,v.user_code,v.verification_uri,v.verification_uri_complete].every(text)&&integer(v.expires_at)&&integer(v.interval)&&v.interval>=0;
48
- // --- frontend/src/run/tasks.ts, transpiled: the task projection the canvas and this door share ---
49
- export function stepVerb(step) {
50
- return (step.method?.verb ?? '').replace(/^mcp__[a-z0-9]+__/i, '');
51
- }
52
- const PROGRAM_ROW = /^call_(\d+)_steps$/;
53
- export function programNodes(step) {
54
- if (stepVerb(step) !== 'run_program')
55
- return null;
56
- const nodes = [];
57
- for (const row of step.inputs ?? []) {
58
- if (!PROGRAM_ROW.test(row.name) || !Array.isArray(row.value))
59
- continue;
60
- for (const entry of row.value) {
61
- if (!entry || typeof entry !== 'object' || Array.isArray(entry))
62
- return null;
63
- const { bind, verb } = entry;
64
- if (typeof bind !== 'string' || typeof verb !== 'string' || !verb)
65
- return null;
66
- nodes.push({ bind, verb });
67
- }
68
- }
69
- return nodes.length ? nodes : null;
70
- }
71
- export const MISSING_INPUT_CODE = 'missing_input';
72
- const RESULT_ROW = /^call_(\d+)_result$/;
73
- function isInputNeed(value) {
74
- if (typeof value !== 'string')
75
- return false;
76
- try {
77
- const decoded = JSON.parse(value);
78
- return Boolean(decoded) && typeof decoded === 'object' && !Array.isArray(decoded)
79
- && 'missing_inputs' in decoded;
80
- }
81
- catch {
82
- return false;
83
- }
84
- }
85
- export function stepNeedsInput(step) {
86
- if (stepVerb(step) !== 'run_program')
87
- return false;
88
- const results = (step.outputs ?? []).filter((row) => (Boolean(row) && typeof row === 'object' && RESULT_ROW.test(String(row.name ?? ''))));
89
- return results.length > 0 && results.every((row) => isInputNeed(row.value));
90
- }
91
- export function attemptState(step) {
92
- const produced = (step.outputs ?? []).length > 0 && !stepNeedsInput(step);
93
- if (!produced && ((step.refusals ?? []).length > 0 || stepNeedsInput(step)))
94
- return 'refused';
95
- return produced ? 'computed' : 'open';
96
- }
97
- function attemptOf(step) {
98
- const state = attemptState(step);
99
- const code = stepNeedsInput(step) ? MISSING_INPUT_CODE : (step.refusals?.[0]?.code ?? null);
100
- return { step, state, code: state === 'refused' ? code : null };
101
- }
102
- export function taskGroups(steps) {
103
- const tasks = [];
104
- let open = null;
105
- for (const step of steps) {
106
- const verb = stepVerb(step);
107
- if (verb === 'thinking')
108
- continue;
109
- const nodes = programNodes(step);
110
- const verbs = nodes ? [...new Set(nodes.map((node) => node.verb))] : [];
111
- if (nodes && open && verbs.some((verb) => open.verbs.includes(verb))) {
112
- const attempt = attemptOf(step);
113
- open.attempts.push(attempt);
114
- if (attempt.state === 'refused')
115
- open.refused.push(attempt);
116
- for (const verb of verbs)
117
- if (!open.verbs.includes(verb))
118
- open.verbs.push(verb);
119
- open.state = attempt.state;
120
- if (attempt.state === 'computed')
121
- open = null;
122
- continue;
123
- }
124
- const attempt = attemptOf(step);
125
- const task = {
126
- id: step.id, program: nodes !== null, verbs,
127
- attempts: [attempt], refused: attempt.state === 'refused' ? [attempt] : [],
128
- state: attempt.state,
129
- };
130
- tasks.push(task);
131
- if (nodes)
132
- open = attempt.state === 'computed' ? null : task;
133
- else if (verb !== 'phys_search')
134
- open = null;
135
- }
136
- return tasks;
137
- }
138
- const INTENT_ROW = /^call_(\d+)_intent$/;
139
- const MISSION_ROW = /^call_(\d+)_(intent|hoisted_requirements|unmet_wanted)$/;
140
- const UNMET_ROW = /^call_(\d+)_unmet_wanted$/;
141
- const HOISTED_ROW = /^call_(\d+)_hoisted_requirements$/;
142
- export function isIntentRow(name) {
143
- return MISSION_ROW.test(name);
144
- }
145
- const words = (value) => (Array.isArray(value) ? value.filter((item) => typeof item === 'string' && item.trim() !== '').map((item) => item.trim()) : []);
146
- function asThresholds(value) {
147
- if (!Array.isArray(value))
148
- return [];
149
- const out = [];
150
- for (const row of value) {
151
- if (!row || typeof row !== 'object' || Array.isArray(row))
152
- continue;
153
- const { quantity, comparator, limit, unit, quote } = row;
154
- if (typeof quantity !== 'string' || typeof comparator !== 'string' || typeof limit !== 'number' || typeof quote !== 'string')
155
- continue;
156
- out.push({ quantity, comparator, limit, unit: typeof unit === 'string' ? unit : '', quote });
157
- }
158
- return out;
159
- }
160
- export function stepIntent(step) {
161
- let found = null;
162
- for (const row of step.inputs ?? []) {
163
- if (!INTENT_ROW.test(row.name))
164
- continue;
165
- const value = row.value;
166
- if (typeof value === 'string') {
167
- found = { title: value.trim(), rationale: '', wanted: [], thresholds: [] };
168
- continue;
169
- }
170
- if (!value || typeof value !== 'object' || Array.isArray(value))
171
- continue;
172
- const { title, rationale, wanted, thresholds } = value;
173
- found = {
174
- title: typeof title === 'string' ? title.trim() : '',
175
- rationale: typeof rationale === 'string' ? rationale.trim() : '',
176
- wanted: words(wanted),
177
- thresholds: asThresholds(thresholds),
178
- };
179
- }
180
- return found;
181
- }
182
- export function hoistedRequirements(step) {
183
- const out = [];
184
- for (const row of step.inputs ?? []) {
185
- if (!HOISTED_ROW.test(row.name) || !Array.isArray(row.value))
186
- continue;
187
- for (const entry of row.value) {
188
- if (!entry || typeof entry !== 'object' || Array.isArray(entry))
189
- continue;
190
- const { quantity, comparator, limit, unit } = entry;
191
- if (typeof quantity !== 'string' || typeof comparator !== 'string' || typeof limit !== 'number')
192
- continue;
193
- out.push({ quantity: quantity.replace(/^\$/, ''), comparator, limit, unit: typeof unit === 'string' ? unit : '' });
194
- }
195
- }
196
- return out;
197
- }
198
- export function hoistedQuotes(step) {
199
- const quotes = new Map();
200
- const thresholds = stepIntent(step)?.thresholds ?? [];
201
- for (const row of hoistedRequirements(step)) {
202
- const matches = thresholds.filter((threshold) => (threshold.comparator === row.comparator && threshold.limit === row.limit && threshold.unit === row.unit));
203
- if (matches.length === 1)
204
- quotes.set(row.quantity, matches[0].quote);
205
- }
206
- return quotes;
207
- }
208
- export function unmetWanted(step) {
209
- let found = [];
210
- for (const row of step.outputs ?? []) {
211
- if (!row || typeof row !== 'object')
212
- continue;
213
- const { name, value } = row;
214
- if (typeof name === 'string' && UNMET_ROW.test(name))
215
- found = words(value);
216
- }
217
- return found;
218
- }
219
- const sameWords = (left, right) => {
220
- const norm = (value) => value.replace(/[.!?]+$/u, '').replace(/\s+/g, ' ').trim().toLowerCase();
221
- const a = norm(left);
222
- return Boolean(a) && a === norm(right);
223
- };
224
- export function intentTitle(step) {
225
- const recorded = (step.title ?? '').trim();
226
- const intent = stepIntent(step);
227
- return recorded && intent && sameWords(recorded, intent.title) ? recorded : '';
228
- }
229
- export const ENGINEERING_VERBS = {
230
- analyze_acquisition_contact_latency: 'Acquisition-to-contact latency',
231
- analyze_eclipse_profile: 'Eclipse profile',
232
- close_link: 'Link closure',
233
- resolve_payload: 'Image resolution',
234
- resolve_utc_interval: 'Time window',
235
- sample_projection: 'Sampled projection',
236
- select_propulsion: 'Propulsion selection',
237
- size_access: 'Coverage and revisit',
238
- size_annual_power: 'Annual power',
239
- size_burn_sequence: 'Burn sequence',
240
- size_delta_v_budget: 'Delta-v budget',
241
- size_drag_makeup: 'Drag make-up',
242
- size_ground_contacts: 'Ground contacts',
243
- size_hohmann_transfer: 'Hohmann transfer',
244
- size_hybrid_transfer: 'Hybrid transfer',
245
- size_in_view: 'Satellites in view',
246
- size_orbit: 'Orbit geometry',
247
- size_phase_duration: 'Phasing duration',
248
- size_platform: 'Platform sizing',
249
- size_pnt_geometry: 'Navigation geometry',
250
- size_power: 'Power system',
251
- size_propellant: 'Propellant',
252
- size_raan_change: 'Plane change',
253
- size_repeat_orbit: 'Repeat orbit',
254
- size_station_keeping: 'Station keeping',
255
- size_topology: 'Topology search',
256
- size_transfer: 'Orbit transfer',
257
- };
258
- export function engineeringVerbLabel(verb) {
259
- return ENGINEERING_VERBS[verb] ?? verb.replace(/^size_/, '').replaceAll('_', ' ')
260
- .replace(/^./, (letter) => letter.toUpperCase());
261
- }
262
- export function taskTitle(task) {
263
- for (let index = task.attempts.length - 1; index >= 0; index -= 1) {
264
- const title = intentTitle(task.attempts[index].step);
265
- if (title)
266
- return title;
267
- }
268
- return task.verbs.map(engineeringVerbLabel).join(' · ');
269
- }
270
- export function taskRationale(task) {
271
- for (let index = task.attempts.length - 1; index >= 0; index -= 1) {
272
- const rationale = stepIntent(task.attempts[index].step)?.rationale ?? '';
273
- if (rationale)
274
- return rationale;
275
- }
276
- return '';
277
- }
278
- export const REFUSAL_REASONS = {
279
- authoring_defect: 'the program needed a repair',
280
- owner_refusal: 'an input was outside what the physics owner accepts',
281
- support_mismatch: 'a number needed its source',
282
- unit_error: 'a unit did not match',
283
- capability_gap: 'no physics owner covers this',
284
- not_converged: 'the physics did not converge',
285
- budget: 'the budget for this step was spent',
286
- state_fork: 'the design had moved on since the program was written',
287
- missing_knowledge_dependency: 'a method note or fact it needed was missing',
288
- release_withdrawn: 'the data release was withdrawn',
289
- data_access_denied: 'this data is outside your plan',
290
- surface_absent: 'it named a tool that does not exist',
291
- UNKNOWN_TOOL: 'it named a tool that does not exist',
292
- ABORTED_BEFORE_DISPATCH: 'it was stopped before it ran',
293
- INVALID_TOOL_OUTPUT: 'its result could not be read',
294
- facts_unavailable: 'the catalogue was unavailable',
295
- spacedata_release_absent: 'the catalogue was unavailable',
296
- spacedata_release_unreadable: 'the catalogue was unavailable',
297
- invalid_arguments: 'the request was malformed',
298
- internal_error: 'the catalogue failed',
299
- [MISSING_INPUT_CODE]: 'it needed an input you had not given',
300
- };
301
- export const REFUSAL_FALLBACK = 'it was not accepted';
302
- export function refusalReason(refusal) {
303
- const sentence = REFUSAL_REASONS[refusal?.code ?? ''] ?? REFUSAL_FALLBACK;
304
- const subject = (refusal?.subject ?? '').trim();
305
- return subject ? `${sentence} — ${subject.split('/').pop() ?? subject}` : sentence;
306
- }
307
- export function taskStateWord(task) {
308
- if (task.state === 'open')
309
- return 'no result';
310
- return task.state === 'refused' ? 'not computed' : task.state;
311
- }
312
- export function taskUnmet(task) {
313
- if (task.state !== 'computed')
314
- return [];
315
- return unmetWanted(task.attempts[task.attempts.length - 1].step);
316
- }
317
- export function taskMeta(task) {
318
- const count = task.attempts.length;
319
- const unmet = taskUnmet(task).length;
320
- return [
321
- taskStateWord(task),
322
- count > 1 ? `${count} attempts` : '',
323
- unmet ? `${unmet} still to compute` : '',
324
- ].filter(Boolean).join(' · ');
325
- }
package/src/format.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ORIGIN_KINDS, ORIGIN_WORD, TERMINAL_FIELDS, TERMINAL_RECOVERY_DECLARATIONS,
3
- isIntentRow, taskGroups, taskMeta, taskTitle, validateArtifact, validateSynthesis,
3
+ validateArtifact, validateSynthesis,
4
4
  } from "./contract.js";
5
5
  import { CliError } from "./errors.js";
6
6
 
@@ -64,8 +64,7 @@ export function originWord(origin) {
64
64
  /** `name = value unit (origin word, ref)` — one line per input, in wire order. */
65
65
  export function inputLines(inputs) {
66
66
  if (!Array.isArray(inputs)) return [];
67
- // `call_N_intent` is the step's title and rationale (v1.9.36), not one of its inputs.
68
- return inputs.filter((row) => !isIntentRow(String(row?.name ?? ""))).map((row) => {
67
+ return inputs.map((row) => {
69
68
  const unit = typeof row?.unit === "string" && row.unit ? ` ${row.unit}` : "";
70
69
  const word = originWord(row?.origin);
71
70
  // The REF is what makes the word actionable — "your file" is a category, "your file
@@ -78,24 +77,29 @@ export function inputLines(inputs) {
78
77
  }
79
78
 
80
79
  /**
81
- * TASK OVER STEPS, SPOKEN BY THIS DOOR TOO.
80
+ * ONE ROW PER INTENT, SPOKEN BY THIS DOOR TOO (RunWire v2, CONTRACTS.md S1).
82
81
  *
83
- * The owner's hybrid run of 2026-09-11 was eleven model turns for one objective, nine of them
84
- * refused `run_program` calls. `taskGroups` in `contract.js` the same bytes the canvas
85
- * renders, generated from `frontend/src/run/tasks.ts` folds them into the tasks the reader
86
- * asked for: one line per task, its verbs as the title, what it is and how many attempts it
87
- * took. Binding receipts (`binding-*`) are the workspace register's rows, not work.
82
+ * The rows are the `step_finished` facts keyed by `step_id`: the finding as the title, the
83
+ * outcome word, the attempt count and the `RESULT:` line the program printed. Tool calls stay
84
+ * folded; this door prints the plan, not the process.
88
85
  */
86
+ /** The budget that closed a partial row (`step_finished.cause`), in the reader's words — the same
87
+ * words the workbench's row meta uses (`StepRow.vue`). */
88
+ const CAUSE_WORD = Object.freeze({
89
+ row_budget: "stopped at its budget", wall_budget: "stopped at the turn's time limit",
90
+ });
91
+
89
92
  export function taskLines(events) {
90
- const steps = events.flatMap((event) => {
93
+ return events.flatMap((event) => {
91
94
  if (event?.kind !== "step_finished") return [];
92
- const step = event.payload?.step ?? event.payload;
93
- return step && typeof step === "object" && typeof step.id === "string"
94
- && !step.id.startsWith("binding-") ? [step] : [];
95
- });
96
- return taskGroups(steps).filter((task) => task.program).map((task) => {
97
- const refused = task.refused.length ? ` (${task.refused.length} refused)` : "";
98
- return ` ${plainLine(`${taskTitle(task)} ${taskMeta(task)}${refused}`)}`;
95
+ const row = event.payload;
96
+ if (!row || typeof row !== "object" || typeof row.step_id !== "string") return [];
97
+ const attempts = Number.isInteger(row.attempts) && row.attempts > 0
98
+ ? ` · ${row.attempts} ${row.attempts === 1 ? "attempt" : "attempts"}` : "";
99
+ const result = typeof row.result_line === "string" && row.result_line.trim()
100
+ ? `\n ${plainLine(row.result_line)}` : "";
101
+ const outcome = CAUSE_WORD[row.cause] ?? row.status;
102
+ return [` ${plainLine(`${row.title} — ${outcome}${attempts}`)}${result}`];
99
103
  });
100
104
  }
101
105
 
@@ -192,7 +196,7 @@ export function humanRun(value, { projectId, cost } = {}) {
192
196
  const tasks = taskLines(value.events);
193
197
  const lines = [];
194
198
  if (terminal.answer !== undefined) lines.push(terminal.answer, "");
195
- if (tasks.length) lines.push("Tasks:", ...tasks, "");
199
+ if (tasks.length) lines.push("Steps:", ...tasks, "");
196
200
  if (origins.length) lines.push("Inputs and origins:", ...origins, "");
197
201
  if (artifacts.length) {
198
202
  lines.push("Artifacts:");
@@ -241,10 +245,6 @@ export function progress(event) {
241
245
  const title = plainLine(event.payload?.title ?? "");
242
246
  return title.trim() ? `Starting: ${title}\n` : "Starting\n";
243
247
  }
244
- if (event?.kind === "step_label") {
245
- const label = plainLine(event.payload?.label ?? "");
246
- return label.trim() ? `Working: ${label}\n` : "";
247
- }
248
248
  if (event?.kind === "artifact") {
249
249
  return `File ready: ${plainLine(event.payload.filename)}\n`;
250
250
  }
package/src/mcp.js CHANGED
@@ -3,7 +3,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
3
3
  import * as z from "zod/v4";
4
4
 
5
5
  import { CliError, VecteurClient, redact } from "./client.js";
6
- import { EVENT_KINDS } from "./contract.js";
6
+ import { EVENT_KINDS, RETIRED_EVENT_KINDS } from "./contract.js";
7
7
  import { canonicalJson } from "./format.js";
8
8
 
9
9
  const projectInput = z.object({ project_id: z.string().min(1) }).strict();
@@ -12,7 +12,7 @@ const submitInput = z.object({
12
12
  ask: z.string().min(1),
13
13
  }).strict();
14
14
  const runInput = z.object({ run_id: z.string().min(1) }).strict();
15
- const eventKind = z.enum(EVENT_KINDS);
15
+ const eventKind = z.enum([...EVENT_KINDS, ...RETIRED_EVENT_KINDS]);
16
16
  const eventOutput = z.object({
17
17
  run_id: z.string().min(1), seq: z.number().int().safe().nonnegative(),
18
18
  kind: eventKind,