@axiom-lattice/core 4.2.2 → 4.2.3

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.mjs CHANGED
@@ -10070,8 +10070,8 @@ var metricsPlugin = {
10070
10070
  type: "metrics",
10071
10071
  category: "data",
10072
10072
  capabilityBundleEligible: true,
10073
- name: "Metrics",
10074
- description: "Provides metrics querying capabilities",
10073
+ name: "Metrics (DEPRECATED)",
10074
+ description: "DEPRECATED \u2014 use the 'semantic-metrics' plugin instead. Legacy metrics querying over the old server contract; kept for backward compatibility with existing agents. New agents should enable 'semantic-metrics' (connection-backed, /api/v1, table-grant scoping, semantic meta publishing).",
10075
10075
  tools: [
10076
10076
  { name: "list_datasources", description: "List all datasources from all configured servers" },
10077
10077
  { name: "query_metrics_list", description: "Query available metrics from datasources" },
@@ -22990,6 +22990,14 @@ Do not update or change a belief without new evidence. Every update cites the
22990
22990
  observation, states how it supports or contradicts the Claim, and records the
22991
22991
  resulting Decision Impact or explains why the plan remains unchanged.
22992
22992
 
22993
+ An approved scope or criteria change is one reconciliation, not two updates:
22994
+ revise \`## Objective\` / \`## Acceptance Criteria\` and, in the same
22995
+ reconciliation, re-base every affected Belief Key \u2014 its new Basis must cite the
22996
+ user approval \u2014 cancel or replace subtasks that depended on the superseded
22997
+ scope, and revise eval coverage to the revised contract. A downgraded
22998
+ probability after a scope change is an honest reset, not a regression; continue
22999
+ only from the re-based Belief State.
23000
+
22993
23001
  The current runtime requires numeric \`beliefImpact.after\` values and the
22994
23002
  canonical compatibility table below. Treat \`after\` as the evidence support
22995
23003
  percentage for the Claim. It is not an Eval score, Agent quality metric, or Task
@@ -23051,6 +23059,15 @@ that can change the parent goal, acceptance judgment, or next action. It is not
23051
23059
  tool call. Reading a skill, running one command, calling SQL, or editing a file is
23052
23060
  normally an internal \`write_todos\` step.
23053
23061
 
23062
+ Persist the plan before executing it. Announcing work in conversation (for
23063
+ example, "I will create three sub-agents") is not a plan: before that work
23064
+ starts, the parent Belief State must already exist and every planned child must
23065
+ be persisted with its contract (\`pending\` until its phase starts,
23066
+ \`in_progress\` when it starts). The persisted decomposition is what the user
23067
+ aligns on \u2014 in normal approval flows, present the decomposition (children,
23068
+ Targets, and belief dimensions) and confirm it before executing it; a deviation
23069
+ from the approved design is a material boundary requiring renewed confirmation.
23070
+
23054
23071
  Before creating a subtask, identify: (1) the uncertain parent Belief Key, (2) why
23055
23072
  it affects a decision, (3) the observable evidence this subtask will produce, and
23056
23073
  (4) the Prediction contract with positive and negative result branches and their
@@ -24680,6 +24697,9 @@ For a new Orchestra parent \u2014 build the delegation tree before the parent:
24680
24697
  each sub-agent is a bounded specialist with a clear interface (input/output/responsibility).
24681
24698
  A sub-agent qualifies as a sub-agent when it has independent tools, its own skill, or
24682
24699
  needs separate eval. Do not create a sub-agent for a simple inline step.
24700
+ Persist the approved delegation tree as planned child tasks with contracts and
24701
+ \`Targets\` before creating any sub-agent ([[task-tracking]]); in normal approval
24702
+ flows the decomposition is presented for user confirmation first.
24683
24703
 
24684
24704
  **2. Build each sub-agent's skill first.** Per sub-agent:
24685
24705
  - If domain knowledge exists \u2192 load [[document-learning-learn-capability]]
@@ -32353,7 +32373,7 @@ function snapshotDate(value) {
32353
32373
 
32354
32374
  // src/services/TaskLifecycleService.ts
32355
32375
  import { createHash as createHash6 } from "crypto";
32356
- import { parseTaskBeliefState as parseTaskBeliefState2, snapshotExactArray as snapshotExactArray3, snapshotExactRecord as snapshotExactRecord8, taskBeliefStatesEqual } from "@axiom-lattice/protocols";
32376
+ import { parseTaskBeliefState as parseTaskBeliefState2, replaceTaskBeliefState, snapshotExactArray as snapshotExactArray3, snapshotExactRecord as snapshotExactRecord8, taskBeliefStatesEqual } from "@axiom-lattice/protocols";
32357
32377
 
32358
32378
  // src/middlewares/taskBelief.ts
32359
32379
  import { createHash as createHash5 } from "crypto";
@@ -32450,6 +32470,71 @@ function buildParentBeliefActivity(input) {
32450
32470
  function failure2(code, error, hint) {
32451
32471
  return { success: false, code, error, ...hint === void 0 ? {} : { hint } };
32452
32472
  }
32473
+ async function seedBeliefOwnerTable(taskStore, owner, impacts) {
32474
+ if (impacts.length === 0) return { description: owner.description ?? "" };
32475
+ const parsed = parseTaskBeliefState2(owner.description ?? "");
32476
+ if (!parsed.success && parsed.code !== "MISSING_BELIEF_STATE") {
32477
+ return failure2("INVALID_BELIEF_TABLE", parsed.message);
32478
+ }
32479
+ const entries = parsed.success ? [...parsed.state.entries] : [];
32480
+ const known = new Set(entries.map((entry) => entry.key));
32481
+ const missing = impacts.filter((impact) => !known.has(impact.key));
32482
+ if (missing.length === 0) return { description: owner.description ?? "" };
32483
+ for (const impact of missing) {
32484
+ entries.push({ key: impact.key, probability: impact.after, target: impact.after, basis: impact.basis });
32485
+ }
32486
+ const base = owner.description ?? "";
32487
+ const description = replaceTaskBeliefState(base, { entries });
32488
+ const updated = await taskStore.update(owner.tenantId, owner.id, { description });
32489
+ if (!updated) return failure2("TASK_STORE_WRITE_FAILED", "Failed to seed the belief owner's Belief State table.");
32490
+ return { description: updated.description ?? description };
32491
+ }
32492
+ function beliefValidationFailure(validation) {
32493
+ switch (validation.code) {
32494
+ case "MISSING_BELIEF_TABLE":
32495
+ return failure2(
32496
+ validation.code,
32497
+ "The belief owner's description has no '## Belief State' table.",
32498
+ "Initialize a '## Belief State' section in the belief owner task's description via manage_task update, using the canonical four-column table | Belief Key | Probability | Target | Basis |, then retry completion with beliefImpact keys from that table."
32499
+ );
32500
+ case "INVALID_BELIEF_TABLE":
32501
+ return failure2(
32502
+ validation.code,
32503
+ `The belief owner's Belief State table is invalid: ${validation.message}`,
32504
+ "Fix the Belief State table via manage_task update on the belief owner task, then retry completion."
32505
+ );
32506
+ case "INVALID_BELIEF_KEY":
32507
+ return failure2(
32508
+ validation.code,
32509
+ `Belief key '${validation.key}' is not in the belief owner's Belief State table.`,
32510
+ "Add the key to the belief owner's Belief State table via manage_task update, or report an existing key."
32511
+ );
32512
+ case "INVALID_BELIEF_VALUE":
32513
+ return failure2(
32514
+ validation.code,
32515
+ `Belief key '${validation.key}' has an invalid after value.`,
32516
+ "after must be an integer between 0 and 100."
32517
+ );
32518
+ case "INVALID_BELIEF_BASIS":
32519
+ return failure2(
32520
+ validation.code,
32521
+ `Belief key '${validation.key}' has an invalid basis.`,
32522
+ "basis must be a single nonblank line of at most 1000 characters."
32523
+ );
32524
+ case "INVALID_DUPLICATE_BELIEF_KEY":
32525
+ return failure2(
32526
+ validation.code,
32527
+ `Duplicate belief key '${validation.key}'.`,
32528
+ "Report each belief key at most once."
32529
+ );
32530
+ case "MISSING_BELIEF_IMPACT":
32531
+ return failure2(
32532
+ validation.code,
32533
+ "Agent task completion requires beliefImpact.",
32534
+ "Provide beliefImpact: [{ key: '<belief-key>', after: <0-100>, basis: '<evidence>' }]"
32535
+ );
32536
+ }
32537
+ }
32453
32538
  function isProjectLifecycleTask(task) {
32454
32539
  const source = task.context?.source;
32455
32540
  return typeof task.workspaceId === "string" && task.workspaceId.length > 0 && typeof task.projectId === "string" && task.projectId.length > 0 && task.workspaceId !== "default" && task.projectId !== "default" && (source === "project_room" || source === "project_task");
@@ -32469,15 +32554,10 @@ function unsupportedTaskStatus() {
32469
32554
  );
32470
32555
  }
32471
32556
  function requireProjectTaskThread(task, inputThreadId, allowPendingClaim = false) {
32472
- if (!isProjectLifecycleTask(task)) return void 0;
32473
- const stored = task.context?.thread_id;
32474
- if (typeof stored === "string" && stored.length > 0) {
32475
- return stored === inputThreadId ? void 0 : failure2("TASK_THREAD_CONFLICT", "Project task mutation belongs to another Thread.");
32476
- }
32477
- if (allowPendingClaim && task.status === "pending" && typeof inputThreadId === "string" && inputThreadId.length > 0) {
32478
- return void 0;
32479
- }
32480
- return failure2("PROJECT_TASK_THREAD_REQUIRED", "Project task execution requires its authoritative Task Thread.");
32557
+ void task;
32558
+ void inputThreadId;
32559
+ void allowPendingClaim;
32560
+ return void 0;
32481
32561
  }
32482
32562
  function detailOf(item) {
32483
32563
  const detail = item.detail;
@@ -33706,7 +33786,11 @@ var TaskLifecycleService = class {
33706
33786
  if (existing.ownerType !== "agent") return failure2("AGENT_TASK_REQUIRED", "Lifecycle completion only supports agent tasks.");
33707
33787
  const threadFailure = requireProjectTaskThread(existing, input.threadId);
33708
33788
  if (threadFailure) return threadFailure;
33709
- if (existing.status !== "in_progress") return failure2("TASK_STATUS_CONFLICT", "Task is not in progress.");
33789
+ if (existing.status !== "in_progress") return failure2(
33790
+ "TASK_STATUS_CONFLICT",
33791
+ "Task is not in progress.",
33792
+ "Start the task first (status='in_progress'), then complete it with result and beliefImpact."
33793
+ );
33710
33794
  if (!review && existing.requireReview === true) {
33711
33795
  return failure2("REVIEW_REQUIRED", "Task requires completion evidence review through submitReview.");
33712
33796
  }
@@ -33714,12 +33798,18 @@ var TaskLifecycleService = class {
33714
33798
  if (!result) return failure2("MISSING_RESULT", "Agent completion requires a nonblank result.");
33715
33799
  const parentResult = await this.loadParent(existing);
33716
33800
  if (parentResult && "success" in parentResult) return parentResult;
33801
+ const beliefOwnerTask = parentResult?.ownerType === "agent" ? parentResult : existing;
33802
+ if (input.beliefImpact?.length) {
33803
+ const seeded = await seedBeliefOwnerTable(this.deps.taskStore, beliefOwnerTask, input.beliefImpact);
33804
+ if ("code" in seeded) return seeded;
33805
+ beliefOwnerTask.description = seeded.description;
33806
+ }
33717
33807
  const validation = validateBeliefImpactForTask({
33718
33808
  parent: parentResult ? { ownerType: parentResult.ownerType } : null,
33719
33809
  impacts: input.beliefImpact,
33720
33810
  ownerDescription: parentResult?.ownerType === "agent" ? parentResult.description : existing.description
33721
33811
  });
33722
- if (!validation.ok) return failure2(validation.code, "Belief impact failed validation.");
33812
+ if (!validation.ok) return beliefValidationFailure(validation);
33723
33813
  const beliefOwner = this.beliefOwnerSnapshot(existing, parentResult);
33724
33814
  const baseEventKey = eventKeyFor(input.taskId, result, input.beliefImpact, beliefOwner);
33725
33815
  let eventKey = baseEventKey;
@@ -36935,7 +37025,7 @@ var semanticMetricsPlugin = {
36935
37025
  category: "data",
36936
37026
  capabilityBundleEligible: true,
36937
37027
  name: "Semantic Metrics",
36938
- description: "Semantic metrics datasource exploration, meta publishing, and runtime querying",
37028
+ description: "Semantic metrics datasource exploration, meta publishing, and runtime querying. PERMISSION MODEL \u2014 query-only agents (metric definitions + data): enable this middleware with allowedTools ['metrics_runtime_tool']. Metric designers (Builder): keep all three tools (metrics_datasource_tool, metrics_meta_tool, metrics_runtime_tool) for exploration, publishing, and verification, or use the built-in 'semantic-metrics-builder' agent.",
36939
37029
  version: "1.0.0",
36940
37030
  tools: [
36941
37031
  { name: "metrics_datasource_tool", description: "Explore datasource structure within the tenant's granted scope" },
@@ -36944,6 +37034,8 @@ var semanticMetricsPlugin = {
36944
37034
  ],
36945
37035
  configSchema: {
36946
37036
  type: "object",
37037
+ title: "Semantic Metrics Configuration",
37038
+ description: "First select connections (connections or connectAll). Then scope tools by role via allowedTools: QUERY-ONLY agents (metric definitions + data) set allowedTools to ['metrics_runtime_tool'] \u2014 read_semantic_catalog and query_metrics cover both; metric DESIGNERS keep all three tools (datasource exploration, meta publishing, runtime verification).",
36947
37039
  properties: {
36948
37040
  connections: {
36949
37041
  type: "array",
@@ -39531,6 +39623,15 @@ function createTaskMiddleware(options = {}) {
39531
39623
  });
39532
39624
  }
39533
39625
  const title = input.title;
39626
+ let createScopeWorkspaceId = workspaceId;
39627
+ let createScopeProjectId = projectId;
39628
+ if (!trustedProject && !delegatedTaskId && input.parentId && (!createScopeWorkspaceId || !createScopeProjectId)) {
39629
+ const parentTask = await store.getById(tenantId2, input.parentId);
39630
+ if (parentTask) {
39631
+ createScopeWorkspaceId = createScopeWorkspaceId ?? parentTask.workspaceId;
39632
+ createScopeProjectId = createScopeProjectId ?? parentTask.projectId;
39633
+ }
39634
+ }
39534
39635
  const effectiveOwnerType = delegatedTaskId ? "agent" : trustedProject ? "agent" : input.ownerType || "user";
39535
39636
  const effectiveOwnerId = delegatedTaskId ? rc.assistant_id : ownerId;
39536
39637
  if (delegatedTaskId && !effectiveOwnerId) {
@@ -39605,7 +39706,7 @@ function createTaskMiddleware(options = {}) {
39605
39706
  store,
39606
39707
  tenantId2,
39607
39708
  delegatedTaskId,
39608
- { workspaceId, projectId },
39709
+ { workspaceId: createScopeWorkspaceId, projectId: createScopeProjectId },
39609
39710
  input.parentId,
39610
39711
  input.dependencies
39611
39712
  );
@@ -39614,7 +39715,7 @@ function createTaskMiddleware(options = {}) {
39614
39715
  const referenceError = await validateReferencedTasks(
39615
39716
  store,
39616
39717
  tenantId2,
39617
- { workspaceId, projectId },
39718
+ { workspaceId: createScopeWorkspaceId, projectId: createScopeProjectId },
39618
39719
  input.parentId,
39619
39720
  input.dependencies
39620
39721
  );
@@ -39631,7 +39732,7 @@ function createTaskMiddleware(options = {}) {
39631
39732
  const dependencyError = await validateEffectiveDependencies(
39632
39733
  store,
39633
39734
  tenantId2,
39634
- { workspaceId, projectId },
39735
+ { workspaceId: createScopeWorkspaceId, projectId: createScopeProjectId },
39635
39736
  input.dependencies
39636
39737
  );
39637
39738
  if (dependencyError) return dependencyError;
@@ -39679,8 +39780,8 @@ function createTaskMiddleware(options = {}) {
39679
39780
  dependencies: input.dependencies,
39680
39781
  result: input.result,
39681
39782
  failureReason: input.failureReason,
39682
- workspaceId,
39683
- projectId,
39783
+ workspaceId: createScopeWorkspaceId,
39784
+ projectId: createScopeProjectId,
39684
39785
  files: input.files
39685
39786
  });
39686
39787
  };
@@ -39874,7 +39975,7 @@ function createTaskMiddleware(options = {}) {
39874
39975
  if (delegatedTaskId && input.id !== delegatedTaskId) {
39875
39976
  return delegatedTaskScopeError(delegatedTaskId);
39876
39977
  }
39877
- const existing = await store.getById(tenantId2, input.id);
39978
+ let existing = await store.getById(tenantId2, input.id);
39878
39979
  if (!existing) {
39879
39980
  return JSON.stringify({
39880
39981
  success: false,
@@ -39916,15 +40017,6 @@ function createTaskMiddleware(options = {}) {
39916
40017
  }
39917
40018
  const isAgentTask = existing.ownerType === "agent";
39918
40019
  const candidateReviewInterruption = input.status === "interrupted" && input.context?.interruption && typeof input.context.interruption === "object" && input.context.interruption.type === "review_required" && !!input.result?.trim() && !!input.beliefImpact?.length;
39919
- const trustedLifecycleInterruption = !!trustedProject && input.status === "interrupted" && input.context?.interruption && typeof input.context.interruption === "object";
39920
- if (isAgentTask && input.context !== void 0 && !candidateReviewInterruption && !trustedLifecycleInterruption) {
39921
- return JSON.stringify({
39922
- success: false,
39923
- code: "TASK_LIFECYCLE_CONTEXT_PROTECTED",
39924
- error: "Agent task context is owned by the task lifecycle service.",
39925
- hint: "Use lifecycle status inputs without context; the service preserves thread and interruption audit data."
39926
- });
39927
- }
39928
40020
  const changesOwnerType = input.ownerType !== void 0 && input.ownerType !== existing.ownerType;
39929
40021
  const changesAgentIdentity = isAgentTask && (input.ownerId !== void 0 && input.ownerId !== existing.ownerId || input.parentId !== void 0 && input.parentId !== existing.parentId);
39930
40022
  if (changesOwnerType || changesAgentIdentity) {
@@ -39954,14 +40046,6 @@ function createTaskMiddleware(options = {}) {
39954
40046
  hint: "Persist ownership or parent changes separately before changing lifecycle or task content."
39955
40047
  });
39956
40048
  }
39957
- if (isAgentTask && input.description !== void 0 && input.status !== void 0) {
39958
- return JSON.stringify({
39959
- success: false,
39960
- code: "AGENT_TASK_LIFECYCLE_REQUIRED",
39961
- error: "Agent description and status updates must be separate operations.",
39962
- hint: "Reconcile the description first, then issue the lifecycle status update."
39963
- });
39964
- }
39965
40049
  const actor = trustedActor(trustedProject, rc) ?? (existing.ownerType === "agent" ? `agent:${existing.ownerId}` : `user:${existing.ownerId ?? ownerId}`);
39966
40050
  const threadId = trustedProject?.projectTask?.threadId ?? (trustedProject?.projectRoom ? void 0 : input.sourceId ?? rc.thread_id);
39967
40051
  const lifecycle = isAgentTask ? createTaskLifecycleService({
@@ -39972,29 +40056,36 @@ function createTaskMiddleware(options = {}) {
39972
40056
  if (result.success && result.mutated) markMutation();
39973
40057
  return lifecycleResponse(input.id, result, extra);
39974
40058
  };
40059
+ const hasCarriedContentFields = () => ["title", "description", "priority", "dueDate", "metadata", "files"].some((key4) => input[key4] !== void 0);
39975
40060
  if (lifecycle && input.status === "failed") {
39976
40061
  await validateExecutionResult();
39977
40062
  const callerError = await revalidateCaller();
39978
40063
  if (callerError) return callerError;
39979
- return lifecycleMutationResponse(await lifecycle.failTask({
40064
+ const failed = await lifecycle.failTask({
39980
40065
  tenantId: tenantId2,
39981
40066
  taskId: input.id,
39982
40067
  failureReason: input.failureReason ?? existing.failureReason ?? "",
39983
40068
  actor,
39984
40069
  threadId
39985
- }));
40070
+ });
40071
+ if (!failed.success) return lifecycleMutationResponse(failed);
40072
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(failed);
40073
+ existing = { ...existing, status: input.status };
39986
40074
  }
39987
40075
  if (lifecycle && input.status === "cancelled") {
39988
40076
  await validateExecutionResult();
39989
40077
  const callerError = await revalidateCaller();
39990
40078
  if (callerError) return callerError;
39991
- return lifecycleMutationResponse(await lifecycle.cancelTask({
40079
+ const cancelled = await lifecycle.cancelTask({
39992
40080
  tenantId: tenantId2,
39993
40081
  taskId: input.id,
39994
40082
  actor,
39995
40083
  threadId,
39996
40084
  summary: input.summary
39997
- }));
40085
+ });
40086
+ if (!cancelled.success) return lifecycleMutationResponse(cancelled);
40087
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(cancelled);
40088
+ existing = { ...existing, status: input.status };
39998
40089
  }
39999
40090
  if (lifecycle && input.status === "interrupted" && !(input.context?.interruption && typeof input.context.interruption === "object" && input.context.interruption.type === "review_required")) {
40000
40091
  const interruption = input.context?.interruption;
@@ -40010,7 +40101,7 @@ function createTaskMiddleware(options = {}) {
40010
40101
  await validateExecutionResult();
40011
40102
  const callerError = await revalidateCaller();
40012
40103
  if (callerError) return callerError;
40013
- return lifecycleMutationResponse(await lifecycle.interruptTask({
40104
+ const interrupted = await lifecycle.interruptTask({
40014
40105
  tenantId: tenantId2,
40015
40106
  taskId: input.id,
40016
40107
  type,
@@ -40018,40 +40109,52 @@ function createTaskMiddleware(options = {}) {
40018
40109
  actor,
40019
40110
  threadId,
40020
40111
  dependencyTaskIds: input.dependencyTaskIds
40021
- }));
40112
+ });
40113
+ if (!interrupted.success) return lifecycleMutationResponse(interrupted);
40114
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(interrupted);
40115
+ existing = { ...existing, status: input.status };
40022
40116
  }
40023
40117
  if (lifecycle && input.status === "in_progress" && existing.status === "interrupted") {
40024
40118
  await validateExecutionResult();
40025
40119
  const callerError = await revalidateCaller();
40026
40120
  if (callerError) return callerError;
40027
- return lifecycleMutationResponse(await lifecycle.resumeInterruption({
40121
+ const resumed = await lifecycle.resumeInterruption({
40028
40122
  tenantId: tenantId2,
40029
40123
  taskId: input.id,
40030
40124
  actor,
40031
40125
  threadId
40032
- }));
40126
+ });
40127
+ if (!resumed.success) return lifecycleMutationResponse(resumed);
40128
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(resumed);
40129
+ existing = { ...existing, status: input.status };
40033
40130
  }
40034
40131
  if (lifecycle && input.status === "in_progress" && existing.status === "pending") {
40035
40132
  await validateExecutionResult();
40036
40133
  const callerError = await revalidateCaller();
40037
40134
  if (callerError) return callerError;
40038
- return lifecycleMutationResponse(await lifecycle.startTask({
40135
+ const started = await lifecycle.startTask({
40039
40136
  tenantId: tenantId2,
40040
40137
  taskId: input.id,
40041
40138
  actor,
40042
40139
  threadId
40043
- }));
40140
+ });
40141
+ if (!started.success) return lifecycleMutationResponse(started);
40142
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(started);
40143
+ existing = { ...existing, status: input.status };
40044
40144
  }
40045
40145
  if (lifecycle && input.status === "in_progress" && existing.status === "failed") {
40046
40146
  await validateExecutionResult();
40047
40147
  const callerError = await revalidateCaller();
40048
40148
  if (callerError) return callerError;
40049
- return lifecycleMutationResponse(await lifecycle.retryTask({
40149
+ const retried = await lifecycle.retryTask({
40050
40150
  tenantId: tenantId2,
40051
40151
  taskId: input.id,
40052
40152
  actor,
40053
40153
  threadId
40054
- }));
40154
+ });
40155
+ if (!retried.success) return lifecycleMutationResponse(retried);
40156
+ if (trustedProject || !hasCarriedContentFields()) return lifecycleMutationResponse(retried);
40157
+ existing = { ...existing, status: input.status };
40055
40158
  }
40056
40159
  if (isAgentTask && input.requireReview === true && options.reviewMode !== "hitl") {
40057
40160
  return reviewModeDisabledResponse();
@@ -40172,7 +40275,8 @@ function createTaskMiddleware(options = {}) {
40172
40275
  return JSON.stringify({
40173
40276
  success: false,
40174
40277
  code: "AGENT_TASK_LIFECYCLE_REQUIRED",
40175
- error: `Agent task lifecycle cannot transition from '${existing.status}' to '${input.status}'.`
40278
+ error: `Agent task lifecycle cannot transition from '${existing.status}' to '${input.status}'.`,
40279
+ hint: "Valid transitions: pending\u2192in_progress, in_progress\u2192completed (requires result + beliefImpact), in_progress\u2192failed (requires failureReason), in_progress\u2192cancelled, in_progress\u2192interrupted. Check the current status with manage_task get first."
40176
40280
  });
40177
40281
  }
40178
40282
  const persistedStatus = input.status;
@@ -40395,8 +40499,8 @@ function createTaskMiddleware(options = {}) {
40395
40499
  if (!existing) {
40396
40500
  return JSON.stringify({
40397
40501
  success: false,
40398
- error: `Task '${input.id}' not found or could not be deleted`,
40399
- hint: "Use list to verify the task exists"
40502
+ error: `Task '${input.id}' not found`,
40503
+ hint: "Use list to see available tasks and their IDs"
40400
40504
  });
40401
40505
  }
40402
40506
  if (!taskMatchesRuntimeScope3(existing, workspaceId, projectId)) {
@@ -41478,6 +41582,10 @@ never plain text. One question per tool call.
41478
41582
  safety boundary): the target identity exists and is fixed. Preserve the IDs. Confirm only
41479
41583
  material-boundary decisions. After architecture approval, apply reversible in-contract updates
41480
41584
  without routine renewed confirmation; every material boundary requires HITL or human confirmation.
41585
+ The bound tracking Task is your main task and belief root: reconcile its description before
41586
+ creating children \u2014 write the confirmed Objective, Acceptance Criteria, and Belief State once the
41587
+ Goal Model is confirmed, and keep reconciling the same task as evidence arrives. Never create a
41588
+ parallel main task under it; children are only independently verifiable outcomes.
41481
41589
  If the exact bound target is missing or cannot be loaded \u2192 hard stop: update the tracking task with status
41482
41590
  "interrupted" and a recovery condition. NEVER create a replacement.
41483
41591