@abot-ai/runtime 1.1.0 → 1.2.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/README.md +6 -3
- package/dist/src/capabilities/tool-types.d.ts +1 -1
- package/dist/src/model-gateway/providers/ollama/generation-options.d.ts +1 -3
- package/dist/src/model-gateway/providers/ollama/generation-options.js +1 -5
- package/dist/src/model-gateway/providers/ollama/payload.js +0 -8
- package/dist/src/model-gateway/server/request-body.js +1 -0
- package/dist/src/plugin-sdk/index.d.ts +2 -0
- package/dist/src/plugin-sdk/index.js +2 -0
- package/dist/src/plugin-sdk/tool-availability-brief.d.ts +9 -0
- package/dist/src/plugin-sdk/tool-availability-brief.js +48 -0
- package/dist/src/plugin-sdk/tool-availability-overview.d.ts +9 -0
- package/dist/src/plugin-sdk/tool-availability-overview.js +62 -0
- package/dist/src/runtime/adapters/registered-tool-payload-plan.d.ts +0 -9
- package/dist/src/runtime/adapters/registered-tool-payload-plan.js +0 -67
- package/dist/src/runtime/adapters/registered-tool-payload-related-artifacts.d.ts +13 -0
- package/dist/src/runtime/adapters/registered-tool-payload-related-artifacts.js +84 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/catalog.js +4 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/execution.js +3 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-lifecycle.d.ts +1 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-lifecycle.js +11 -1
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-stages.d.ts +1 -0
- package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-stages.js +9 -1
- package/dist/src/runtime/capabilities/request-bound-tool-registry.js +1 -24
- package/dist/src/runtime/capabilities/tool-availability.d.ts +6 -0
- package/dist/src/runtime/capabilities/tool-availability.js +28 -0
- package/dist/src/runtime/context/capability-brief.d.ts +25 -0
- package/dist/src/runtime/context/capability-brief.js +106 -0
- package/dist/src/runtime/context/request-tool-results-message-binding.d.ts +6 -0
- package/dist/src/runtime/context/request-tool-results-message-binding.js +30 -0
- package/dist/src/runtime/context/request-tool-results-scope.d.ts +3 -0
- package/dist/src/runtime/context/request-tool-results-scope.js +8 -0
- package/dist/src/runtime/context/request-tool-results.d.ts +8 -4
- package/dist/src/runtime/context/request-tool-results.js +49 -38
- package/dist/src/runtime/orchestration/role-calls/candidate-validation.js +8 -1
- package/dist/src/runtime/orchestration/role-calls/child-return.d.ts +4 -0
- package/dist/src/runtime/orchestration/role-calls/child-return.js +25 -5
- package/dist/src/runtime/orchestration/role-calls/command-decoder.js +8 -3
- package/dist/src/runtime/orchestration/role-calls/command-dispatch/child-transitions.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/command-dispatch/child-transitions.js +17 -2
- package/dist/src/runtime/orchestration/role-calls/command-dispatch.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/command-dispatch.js +2 -2
- package/dist/src/runtime/orchestration/role-calls/contracts.d.ts +5 -2
- package/dist/src/runtime/orchestration/role-calls/contracts.js +4 -4
- package/dist/src/runtime/orchestration/role-calls/dependency-results.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/dependency-results.js +1 -0
- package/dist/src/runtime/orchestration/role-calls/index.d.ts +5 -1
- package/dist/src/runtime/orchestration/role-calls/index.js +5 -1
- package/dist/src/runtime/orchestration/role-calls/ledger.d.ts +3 -1
- package/dist/src/runtime/orchestration/role-calls/ledger.js +9 -2
- package/dist/src/runtime/orchestration/role-calls/reducer.d.ts +1 -1
- package/dist/src/runtime/orchestration/role-calls/reducer.js +2 -2
- package/dist/src/runtime/orchestration/role-calls/result-receipt.d.ts +49 -0
- package/dist/src/runtime/orchestration/role-calls/result-receipt.js +188 -0
- package/dist/src/runtime/orchestration/role-calls/return-result-receipt.d.ts +19 -0
- package/dist/src/runtime/orchestration/role-calls/return-result-receipt.js +52 -0
- package/dist/src/runtime/orchestration/role-calls/transactions.js +1 -0
- package/dist/src/runtime/orchestration/role-calls/work-result-lineage.d.ts +34 -0
- package/dist/src/runtime/orchestration/role-calls/work-result-lineage.js +185 -0
- package/dist/src/runtime/orchestration/role-calls/work-result-receipt.d.ts +36 -0
- package/dist/src/runtime/orchestration/role-calls/work-result-receipt.js +187 -0
- package/dist/src/runtime/orchestration/role-executors/activation/result-normalization.js +6 -3
- package/dist/src/runtime/orchestration/role-executors/child-invocation/transaction.js +1 -0
- package/dist/src/runtime/orchestration/role-executors/contracts.d.ts +2 -1
- package/dist/src/runtime/orchestration/worker-capabilities/assignment-provenance.d.ts +36 -0
- package/dist/src/runtime/orchestration/worker-capabilities/assignment-provenance.js +171 -0
- package/dist/src/runtime/orchestration/worker-capabilities/contracts.d.ts +32 -1
- package/dist/src/runtime/orchestration/worker-capabilities/execution/invocation-preparation.d.ts +2 -1
- package/dist/src/runtime/orchestration/worker-capabilities/execution/invocation-preparation.js +3 -0
- package/dist/src/runtime/orchestration/worker-capabilities/execution.js +42 -19
- package/dist/src/runtime/orchestration/worker-capabilities/index.d.ts +2 -0
- package/dist/src/runtime/orchestration/worker-capabilities/index.js +2 -0
- package/dist/src/runtime/orchestration/worker-capabilities/payload-assignment-validation.d.ts +3 -0
- package/dist/src/runtime/orchestration/worker-capabilities/payload-assignment-validation.js +30 -0
- package/dist/src/runtime/orchestration/worker-capabilities/payload-author.js +8 -19
- package/dist/src/runtime/orchestration/worker-capabilities/payload-contracts.d.ts +5 -1
- package/dist/src/runtime/orchestration/worker-capabilities/payload-instructions.js +1 -1
- package/dist/src/runtime/orchestration/worker-capabilities/payload-source-provenance.d.ts +14 -0
- package/dist/src/runtime/orchestration/worker-capabilities/payload-source-provenance.js +132 -0
- package/dist/src/runtime/request/capability-brief.d.ts +5 -0
- package/dist/src/runtime/request/capability-brief.js +24 -0
- package/dist/src/runtime/request/execution-scope.d.ts +2 -1
- package/dist/src/runtime/request/role-executor-composition.js +1 -1
- package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -1
- package/dist/src/runtime/request/worker-capability-composition.js +6 -1
- package/dist/src/runtime/request/worker-capability-payload.js +11 -8
- package/dist/src/runtime/steps/execution-agent/prompt.js +4 -3
- package/dist/src/runtime/steps/planner-decision/capability-catalog-context.d.ts +14 -0
- package/dist/src/runtime/steps/planner-decision/capability-catalog-context.js +87 -0
- package/dist/src/runtime/steps/planner-decision/contracts.d.ts +3 -5
- package/dist/src/runtime/steps/planner-decision/contracts.js +3 -3
- package/dist/src/runtime/steps/planner-decision/format.d.ts +3 -2
- package/dist/src/runtime/steps/planner-decision/format.js +73 -76
- package/dist/src/runtime/steps/planner-decision/input.d.ts +4 -3
- package/dist/src/runtime/steps/planner-decision/input.js +10 -7
- package/dist/src/runtime/steps/planner-decision/parser.d.ts +3 -2
- package/dist/src/runtime/steps/planner-decision/parser.js +10 -19
- package/dist/src/runtime/steps/planner-decision/plan-parser.js +18 -12
- package/dist/src/runtime/steps/planner-decision/prompt.js +33 -28
- package/dist/src/runtime/steps/planner-decision/resume.d.ts +1 -1
- package/dist/src/runtime/steps/planner-decision/resume.js +38 -1
- package/dist/src/runtime/steps/planner-decision/run.d.ts +3 -2
- package/dist/src/runtime/steps/reviewer-decision/audit-coverage.d.ts +10 -0
- package/dist/src/runtime/steps/reviewer-decision/audit-coverage.js +186 -0
- package/dist/src/runtime/steps/reviewer-decision/contracts.d.ts +3 -8
- package/dist/src/runtime/steps/reviewer-decision/contracts.js +12 -6
- package/dist/src/runtime/steps/reviewer-decision/delegated-context.d.ts +24 -0
- package/dist/src/runtime/steps/reviewer-decision/delegated-context.js +70 -0
- package/dist/src/runtime/steps/reviewer-decision/diagnostics.js +1 -1
- package/dist/src/runtime/steps/reviewer-decision/format.js +37 -24
- package/dist/src/runtime/steps/reviewer-decision/input.js +1 -1
- package/dist/src/runtime/steps/reviewer-decision/model-context.d.ts +4 -3
- package/dist/src/runtime/steps/reviewer-decision/model-context.js +92 -10
- package/dist/src/runtime/steps/reviewer-decision/parser.js +19 -1
- package/dist/src/runtime/steps/reviewer-decision/projection.js +42 -68
- package/dist/src/runtime/steps/reviewer-decision/prompt.js +10 -5
- package/dist/src/runtime/steps/reviewer-decision/run.js +12 -3
- package/dist/src/runtime/steps/reviewer-decision/verification-coverage.d.ts +14 -0
- package/dist/src/runtime/steps/reviewer-decision/verification-coverage.js +52 -0
- package/dist/src/runtime/steps/supervisor-decision/capability-brief.d.ts +14 -0
- package/dist/src/runtime/steps/supervisor-decision/capability-brief.js +38 -0
- package/dist/src/runtime/steps/supervisor-decision/contracts.d.ts +7 -3
- package/dist/src/runtime/steps/supervisor-decision/diagnostics.d.ts +2 -0
- package/dist/src/runtime/steps/supervisor-decision/diagnostics.js +8 -2
- package/dist/src/runtime/steps/supervisor-decision/format.js +32 -20
- package/dist/src/runtime/steps/supervisor-decision/input.d.ts +4 -1
- package/dist/src/runtime/steps/supervisor-decision/input.js +19 -1
- package/dist/src/runtime/steps/supervisor-decision/parser.js +62 -59
- package/dist/src/runtime/steps/supervisor-decision/prompt.js +6 -7
- package/dist/src/runtime/steps/supervisor-decision/resume.js +47 -1
- package/dist/src/runtime/steps/supervisor-decision/run.js +10 -0
- package/dist/src/runtime/steps/supervisor-decision/working-directory.js +2 -1
- package/dist/src/runtime/steps/worker-decision/contracts.d.ts +2 -1
- package/dist/src/runtime/steps/worker-decision/input/canonical-state.js +8 -1
- package/dist/src/runtime/steps/worker-decision/input/diagnostic-projection.js +2 -2
- package/dist/src/runtime/steps/worker-decision/input/prompt-context.d.ts +1 -0
- package/dist/src/runtime/steps/worker-decision/input/prompt-context.js +4 -1
- package/dist/src/runtime/steps/worker-decision/input/reference-context.js +34 -14
- package/dist/src/runtime/steps/worker-decision/input/types.d.ts +2 -1
- package/dist/src/runtime/steps/worker-decision/input.d.ts +1 -0
- package/dist/src/runtime/steps/worker-decision/input.js +1 -0
- package/dist/src/runtime/steps/worker-decision/payload-dependency-results.d.ts +8 -0
- package/dist/src/runtime/steps/worker-decision/payload-dependency-results.js +19 -0
- package/dist/src/runtime/steps/worker-decision/prompt.js +8 -8
- package/dist/src/runtime/steps/worker-decision/result-author.js +18 -11
- package/dist/src/runtime/steps/worker-decision/run.js +2 -2
- package/dist/src/web-ui/app/ARCHITECTURE.md +19 -6
- package/dist/src/web-ui/app/app.js +6 -7
- package/dist/src/web-ui/app/components/composer-context-window.d.ts +25 -0
- package/dist/src/web-ui/app/components/composer-context-window.js +155 -0
- package/dist/src/web-ui/app/components/composer-plan.d.ts +9 -0
- package/dist/src/web-ui/app/components/composer-plan.js +128 -0
- package/dist/src/web-ui/app/components/conversation-activity.d.ts +5 -6
- package/dist/src/web-ui/app/components/conversation-activity.js +64 -157
- package/dist/src/web-ui/app/components/conversation-role-cards.d.ts +23 -0
- package/dist/src/web-ui/app/components/conversation-role-cards.js +181 -0
- package/dist/src/web-ui/app/components/conversation-sidebar-layout.js +12 -0
- package/dist/src/web-ui/app/components/conversation-sources.d.ts +7 -0
- package/dist/src/web-ui/app/components/conversation-sources.js +182 -0
- package/dist/src/web-ui/app/components/conversation-view.js +34 -6
- package/dist/src/web-ui/app/components/model-selector.js +4 -1
- package/dist/src/web-ui/app/components/operations-section.js +46 -0
- package/dist/src/web-ui/app/components/workspace-shell.js +86 -78
- package/dist/src/web-ui/app/controllers/realtime-event-controller.d.ts +1 -0
- package/dist/src/web-ui/app/controllers/realtime-event-controller.js +55 -90
- package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +2 -0
- package/dist/src/web-ui/app/controllers/session-controller.js +17 -12
- package/dist/src/web-ui/app/index.html +209 -210
- package/dist/src/web-ui/app/lib/composer-plan-model.d.ts +32 -0
- package/dist/src/web-ui/app/lib/composer-plan-model.js +108 -0
- package/dist/src/web-ui/app/lib/conversation-role-model.d.ts +19 -0
- package/dist/src/web-ui/app/lib/conversation-role-model.js +193 -0
- package/dist/src/web-ui/app/lib/event-presentation.js +30 -9
- package/dist/src/web-ui/app/lib/source-url-policy.d.ts +2 -0
- package/dist/src/web-ui/app/lib/source-url-policy.js +31 -0
- package/dist/src/web-ui/app/lib/task-progress.d.ts +53 -0
- package/dist/src/web-ui/app/lib/task-progress.js +233 -0
- package/dist/src/web-ui/app/lib/tool-invocation-count.d.ts +5 -0
- package/dist/src/web-ui/app/lib/tool-invocation-count.js +21 -0
- package/dist/src/web-ui/app/lib/web-source-event.d.ts +8 -0
- package/dist/src/web-ui/app/lib/web-source-event.js +21 -0
- package/dist/src/web-ui/app/lib/web-sources.d.ts +36 -0
- package/dist/src/web-ui/app/lib/web-sources.js +177 -0
- package/dist/src/web-ui/app/styles/00-tokens-base.css +15 -3
- package/dist/src/web-ui/app/styles/10-shell-sessions.css +24 -34
- package/dist/src/web-ui/app/styles/12-conversation-sidebar.css +93 -0
- package/dist/src/web-ui/app/styles/20-chat-composer.css +55 -472
- package/dist/src/web-ui/app/styles/21-composer-controls.css +368 -0
- package/dist/src/web-ui/app/styles/22-composer-context-window.css +90 -0
- package/dist/src/web-ui/app/styles/23-composer-plan.css +171 -0
- package/dist/src/web-ui/app/styles/24-conversation-role-cards.css +205 -0
- package/dist/src/web-ui/app/styles/25-conversation-sources.css +141 -0
- package/dist/src/web-ui/app/styles/30-inspector-config.css +21 -209
- package/dist/src/web-ui/app/styles/35-memory-onboarding.css +8 -8
- package/dist/src/web-ui/app/styles/36-memory-management.css +13 -13
- package/dist/src/web-ui/app/styles/37-config-operations.css +197 -0
- package/dist/src/web-ui/app/styles/40-config-workspace.css +36 -36
- package/dist/src/web-ui/app/styles/90-responsive.css +14 -77
- package/dist/src/web-ui/app/styles/foundation.css +2 -2
- package/dist/src/web-ui/app/styles.css +7 -0
- package/dist/src/web-ui/app/ui-behavior.d.ts +1 -1
- package/dist/src/web-ui/app/ui-behavior.js +1 -1
- package/docs/configuration.md +15 -8
- package/docs/installation.md +7 -4
- package/docs/known-limitations.md +21 -0
- package/docs/plugins.md +28 -13
- package/docs/runtime-invariant-coverage.md +18 -17
- package/docs/runtime-prompt-policy-contracts.md +27 -17
- package/package.json +4 -3
- package/plugins/capability-brief/source/index.ts +5 -48
- package/plugins/capability-brief/src/index.cjs +46 -33
- package/plugins/system-probe/plugin.json +1 -0
- package/plugins/web/README.md +125 -0
- package/plugins/web/plugin.json +1 -1
- package/plugins/web/skills/web_fetch_skill/SKILL.md +2 -2
- package/plugins/web/skills/web_search_skill/SKILL.md +8 -4
- package/plugins/web/source/errors.ts +5 -1
- package/plugins/web/source/fetch-presentation.ts +61 -0
- package/plugins/web/source/fetch-service.ts +2 -31
- package/plugins/web/source/light/config.ts +196 -0
- package/plugins/web/source/light/crawl/origin-gate.ts +134 -0
- package/plugins/web/source/light/crawl/robots-cache.ts +71 -0
- package/plugins/web/source/light/crawl/robots-parser.ts +132 -0
- package/plugins/web/source/light/crawl/robots-policy.ts +154 -0
- package/plugins/web/source/light/crawl/session-budget.ts +141 -0
- package/plugins/web/source/light/crawl/transport.ts +216 -0
- package/plugins/web/source/light/discovery/candidate-values.ts +63 -0
- package/plugins/web/source/light/discovery/feed-document.ts +127 -0
- package/plugins/web/source/light/discovery/html-links.ts +80 -0
- package/plugins/web/source/light/discovery/html-robots-directives.ts +29 -0
- package/plugins/web/source/light/discovery/markup-tree.ts +145 -0
- package/plugins/web/source/light/discovery/origin-dates.ts +71 -0
- package/plugins/web/source/light/discovery/sitemap-document.ts +63 -0
- package/plugins/web/source/light/documents/cache-policy.ts +28 -0
- package/plugins/web/source/light/documents/document-cache.ts +99 -0
- package/plugins/web/source/light/documents/document-charset.ts +89 -0
- package/plugins/web/source/light/documents/document-contract.ts +20 -0
- package/plugins/web/source/light/documents/document-reader.ts +75 -0
- package/plugins/web/source/light/documents/extract-document.ts +124 -0
- package/plugins/web/source/light/documents/http-cache-freshness.ts +68 -0
- package/plugins/web/source/light/documents/response-decoding.ts +120 -0
- package/plugins/web/source/light/ranking/document-ranking.ts +114 -0
- package/plugins/web/source/light/ranking/query-normalization.ts +69 -0
- package/plugins/web/source/light/search-collection.ts +136 -0
- package/plugins/web/source/light/search-frontier.ts +246 -0
- package/plugins/web/source/light/search-metadata.ts +84 -0
- package/plugins/web/source/light/search-service.ts +154 -0
- package/plugins/web/source/light/search-unavailable.ts +33 -0
- package/plugins/web/source/light/sources/catalog.ts +312 -0
- package/plugins/web/source/light/sources/source-definition.ts +9 -0
- package/plugins/web/source/light/sources/source-selection.ts +35 -0
- package/plugins/web/source/plugin.ts +70 -56
- package/plugins/web/source/public-http.ts +10 -1
- package/plugins/web/source/search-presentation.ts +63 -63
- package/plugins/web/source/search-service-selector.ts +31 -0
- package/plugins/web/source/search-service.ts +6 -0
- package/plugins/web/source/search-source-presentation.ts +76 -0
- package/plugins/web/source/search-types.ts +4 -0
- package/plugins/web/source/source-output-receipts.ts +267 -0
- package/plugins/web/source/source-receipt-budget.ts +51 -0
- package/plugins/web/source/source-receipt-contract.ts +18 -0
- package/plugins/web/src/index.cjs +3214 -288
- package/src/runtime/README.md +30 -9
- package/dist/src/model-gateway/structured-output/budget.d.ts +0 -7
- package/dist/src/model-gateway/structured-output/budget.js +0 -20
- package/dist/src/model-gateway/structured-output/schema-character-estimator.d.ts +0 -1
- package/dist/src/model-gateway/structured-output/schema-character-estimator.js +0 -211
- package/dist/src/model-gateway/structured-output-budget.d.ts +0 -1
- package/dist/src/model-gateway/structured-output-budget.js +0 -1
|
@@ -6,10 +6,14 @@ export * from "./operation-supervision-state-validation.js";
|
|
|
6
6
|
export * from "./capability-selection-reconsideration.js";
|
|
7
7
|
export * from "./capability-selection-supervision.js";
|
|
8
8
|
export * from "./reconsideration-cause.js";
|
|
9
|
+
export * from "./result-receipt.js";
|
|
10
|
+
export * from "./return-result-receipt.js";
|
|
11
|
+
export * from "./work-result-lineage.js";
|
|
12
|
+
export * from "./work-result-receipt.js";
|
|
9
13
|
export * from "./assignment-scope.js";
|
|
10
14
|
export * from "./child-return.js";
|
|
11
15
|
export * from "./dependency-results.js";
|
|
12
|
-
export
|
|
16
|
+
export { createRoleCallLedger } from "./ledger.js";
|
|
13
17
|
export * from "./plan.js";
|
|
14
18
|
export * from "./reducer.js";
|
|
15
19
|
export * from "./transactions.js";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type RoleCallLedger, type RoleCallPolicyInput } from "./contracts.js";
|
|
1
|
+
import { type RoleCallLedger, type RoleCallLedgerHead, type RoleCallPolicyInput } from "./contracts.js";
|
|
2
2
|
export declare function createRoleCallLedger(params: {
|
|
3
3
|
requestId: string;
|
|
4
4
|
policy: RoleCallPolicyInput;
|
|
5
5
|
}): RoleCallLedger;
|
|
6
|
+
/** Confirms exact current-head ownership without trusting structural ledgers. */
|
|
7
|
+
export declare function isCurrentRoleCallLedgerHead(ledger: RoleCallLedger, head: RoleCallLedgerHead): boolean;
|
|
@@ -10,6 +10,7 @@ import { isIssuedRoleCapabilitySelectionSupervisionState, issueCanonicalRoleCapa
|
|
|
10
10
|
import { applyRoleCallCommand, createInitialRoleCallState, sealRoleCallPolicy, validateRoleCallCandidate, } from "./reducer.js";
|
|
11
11
|
import { createRoleCallTransactions } from "./transactions.js";
|
|
12
12
|
import { ROLE_CALL_WORKING_DIRECTORY_MAX_LENGTH } from "./working-directory.js";
|
|
13
|
+
const issuedRoleCallLedgerHeads = new WeakMap();
|
|
13
14
|
export function createRoleCallLedger(params) {
|
|
14
15
|
const initialState = createInitialRoleCallState(params.requestId);
|
|
15
16
|
const capabilitySelectionSupervisionIssuanceAuthority = resolveRoleCapabilitySelectionSupervisionIssuanceAuthority(initialState);
|
|
@@ -40,7 +41,7 @@ export function createRoleCallLedger(params) {
|
|
|
40
41
|
expectedHead: input.expectedHead,
|
|
41
42
|
run(transaction) {
|
|
42
43
|
const admittedCommand = projectAdmittedCapabilityExecutionCommand(commandType, capturedCommand, capabilityExecutionAdmission);
|
|
43
|
-
const transition = applyRoleCallCommand(transaction.head.state, admittedCommand, transaction.head.policy);
|
|
44
|
+
const transition = applyRoleCallCommand(transaction.head.state, admittedCommand, transaction.head.policy, transaction.head.revision);
|
|
44
45
|
if (!transition.ok) {
|
|
45
46
|
return {
|
|
46
47
|
kind: "transition_rejected",
|
|
@@ -129,7 +130,7 @@ export function createRoleCallLedger(params) {
|
|
|
129
130
|
return committed;
|
|
130
131
|
};
|
|
131
132
|
const transactions = createRoleCallTransactions(apply);
|
|
132
|
-
|
|
133
|
+
const ledger = Object.freeze({
|
|
133
134
|
current() {
|
|
134
135
|
return channel.reader.current();
|
|
135
136
|
},
|
|
@@ -137,6 +138,12 @@ export function createRoleCallLedger(params) {
|
|
|
137
138
|
transactions,
|
|
138
139
|
apply,
|
|
139
140
|
});
|
|
141
|
+
issuedRoleCallLedgerHeads.set(ledger, () => channel.reader.current());
|
|
142
|
+
return ledger;
|
|
143
|
+
}
|
|
144
|
+
/** Confirms exact current-head ownership without trusting structural ledgers. */
|
|
145
|
+
export function isCurrentRoleCallLedgerHead(ledger, head) {
|
|
146
|
+
return issuedRoleCallLedgerHeads.get(ledger)?.() === head;
|
|
140
147
|
}
|
|
141
148
|
function createRoleCallStateHeadFactory(capabilitySelectionSupervisionIssuanceAuthority) {
|
|
142
149
|
return createCanonicalStateHeadFactory({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type RoleCallPolicy, type RoleCallPolicyInput, type RoleCallState, type RoleCallTransitionResult, type RoleCallValidationIssue } from "./contracts.js";
|
|
2
2
|
export { hasRoleCallCapabilityAuthority } from "./candidate-validation.js";
|
|
3
3
|
export declare function createInitialRoleCallState(requestId: string): RoleCallState;
|
|
4
|
-
export declare function applyRoleCallCommand(state: RoleCallState, commandInput: unknown, policy: RoleCallPolicy): RoleCallTransitionResult;
|
|
4
|
+
export declare function applyRoleCallCommand(state: RoleCallState, commandInput: unknown, policy: RoleCallPolicy, admittedHeadRevision?: number): RoleCallTransitionResult;
|
|
5
5
|
export declare function validateRoleCallCandidate(params: {
|
|
6
6
|
state: RoleCallState;
|
|
7
7
|
policy: RoleCallPolicy;
|
|
@@ -31,7 +31,7 @@ export function createInitialRoleCallState(requestId) {
|
|
|
31
31
|
}
|
|
32
32
|
return state;
|
|
33
33
|
}
|
|
34
|
-
export function applyRoleCallCommand(state, commandInput, policy) {
|
|
34
|
+
export function applyRoleCallCommand(state, commandInput, policy, admittedHeadRevision) {
|
|
35
35
|
const policyIssues = validateRoleCallPolicy(policy);
|
|
36
36
|
if (policyIssues.length > 0) {
|
|
37
37
|
return reject(state, "invalid_policy", policyIssues);
|
|
@@ -44,7 +44,7 @@ export function applyRoleCallCommand(state, commandInput, policy) {
|
|
|
44
44
|
if (!command.ok) {
|
|
45
45
|
return reject(state, command.code);
|
|
46
46
|
}
|
|
47
|
-
const transition = dispatchRoleCallCommand(state, command.value, policy);
|
|
47
|
+
const transition = dispatchRoleCallCommand(state, command.value, policy, admittedHeadRevision);
|
|
48
48
|
if (!transition.ok)
|
|
49
49
|
return transition;
|
|
50
50
|
const reservationIssue = findRoleActivationReservationIssue(state, policy, command.value);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type RoleCallFrame, type RoleCallPolicy, type RoleCallResult, type RoleCallState } from "./contracts.js";
|
|
2
|
+
import { type RoleCallWorkResultReceipt } from "./work-result-receipt.js";
|
|
3
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND: "reviewer_verdict_v1";
|
|
4
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_MAX_GAPS = 5;
|
|
5
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_MAX_REFS_PER_GAP = 1;
|
|
6
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH = 256;
|
|
7
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_KIND_MAX_LENGTH = 160;
|
|
8
|
+
export declare const ROLE_CALL_REVIEWER_VERDICT_GAP_SUMMARY_MAX_LENGTH = 224;
|
|
9
|
+
export type RoleCallReviewerVerdictGap = Readonly<{
|
|
10
|
+
kind: string;
|
|
11
|
+
subjectRefs: readonly string[];
|
|
12
|
+
factRefs: readonly string[];
|
|
13
|
+
evidenceRefs: readonly string[];
|
|
14
|
+
summary: string;
|
|
15
|
+
}>;
|
|
16
|
+
export type RoleCallReviewerVerdictReceipt = Readonly<{
|
|
17
|
+
kind: typeof ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND;
|
|
18
|
+
reviewerCallId: string;
|
|
19
|
+
callerCallId: string;
|
|
20
|
+
reviewScopeId: string;
|
|
21
|
+
sourceRevision: number;
|
|
22
|
+
verdict: "pass" | "report_gaps";
|
|
23
|
+
gaps: readonly RoleCallReviewerVerdictGap[];
|
|
24
|
+
}>;
|
|
25
|
+
export type RoleCallResultReceipt = RoleCallReviewerVerdictReceipt | RoleCallWorkResultReceipt;
|
|
26
|
+
export declare function createRoleCallReviewerVerdictReceipt(input: Omit<RoleCallReviewerVerdictReceipt, "kind">): RoleCallReviewerVerdictReceipt;
|
|
27
|
+
export declare function normalizeRoleCallResultReceipt(input: unknown): RoleCallResultReceipt | undefined | null;
|
|
28
|
+
export declare function isRoleCallResultReceiptValidForReturn(params: {
|
|
29
|
+
receipt: RoleCallResultReceipt | undefined;
|
|
30
|
+
caller: RoleCallFrame;
|
|
31
|
+
child: RoleCallFrame;
|
|
32
|
+
outcome: RoleCallResult["outcome"];
|
|
33
|
+
policy: RoleCallPolicy;
|
|
34
|
+
admittedHeadRevision: number | undefined;
|
|
35
|
+
}): boolean;
|
|
36
|
+
export declare function isRoleCallResultReceiptValidForStoredResult(params: {
|
|
37
|
+
receipt: RoleCallResultReceipt | undefined;
|
|
38
|
+
producer: RoleCallFrame;
|
|
39
|
+
result: RoleCallResult;
|
|
40
|
+
policy: RoleCallPolicy;
|
|
41
|
+
state?: RoleCallState;
|
|
42
|
+
}): boolean;
|
|
43
|
+
export declare function isRoleCallReviewerVerdictReceiptBoundToChild(params: {
|
|
44
|
+
receipt: RoleCallReviewerVerdictReceipt;
|
|
45
|
+
callerCallId: string;
|
|
46
|
+
childCallId: string;
|
|
47
|
+
childRoleId: RoleCallFrame["roleId"];
|
|
48
|
+
outcome: RoleCallResult["outcome"];
|
|
49
|
+
}): boolean;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { exactKeys, isRecord } from "../../validation/strict-record.js";
|
|
2
|
+
import { ROLE_CALL_RESULT_MAX_LENGTH, SUPERVISOR_WORKER_V1_AUTHORITY_SNAPSHOT, } from "./contracts.js";
|
|
3
|
+
import { isRoleCallWorkResultReceiptValidForStoredResult, mustIssueSupervisorWorkResultReceipt, normalizeRoleCallWorkResultReceipt, ROLE_CALL_WORK_RESULT_RECEIPT_KIND, } from "./work-result-receipt.js";
|
|
4
|
+
export const ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND = "reviewer_verdict_v1";
|
|
5
|
+
export const ROLE_CALL_REVIEWER_VERDICT_MAX_GAPS = 5;
|
|
6
|
+
export const ROLE_CALL_REVIEWER_VERDICT_MAX_REFS_PER_GAP = 1;
|
|
7
|
+
export const ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH = 256;
|
|
8
|
+
export const ROLE_CALL_REVIEWER_VERDICT_KIND_MAX_LENGTH = 160;
|
|
9
|
+
export const ROLE_CALL_REVIEWER_VERDICT_GAP_SUMMARY_MAX_LENGTH = 224;
|
|
10
|
+
export function createRoleCallReviewerVerdictReceipt(input) {
|
|
11
|
+
const receipt = normalizeRoleCallReviewerVerdictReceipt({
|
|
12
|
+
kind: ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND,
|
|
13
|
+
...input,
|
|
14
|
+
});
|
|
15
|
+
if (!receipt)
|
|
16
|
+
throw new Error("reviewer_verdict_receipt_invalid");
|
|
17
|
+
return receipt;
|
|
18
|
+
}
|
|
19
|
+
export function normalizeRoleCallResultReceipt(input) {
|
|
20
|
+
if (input === undefined)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (isRecord(input) && input.kind === ROLE_CALL_WORK_RESULT_RECEIPT_KIND) {
|
|
23
|
+
return normalizeRoleCallWorkResultReceipt(input);
|
|
24
|
+
}
|
|
25
|
+
return normalizeRoleCallReviewerVerdictReceipt(input);
|
|
26
|
+
}
|
|
27
|
+
function normalizeRoleCallReviewerVerdictReceipt(input) {
|
|
28
|
+
if (!isRecord(input) ||
|
|
29
|
+
!exactKeys(input, [
|
|
30
|
+
"kind",
|
|
31
|
+
"reviewerCallId",
|
|
32
|
+
"callerCallId",
|
|
33
|
+
"reviewScopeId",
|
|
34
|
+
"sourceRevision",
|
|
35
|
+
"verdict",
|
|
36
|
+
"gaps",
|
|
37
|
+
]) ||
|
|
38
|
+
input.kind !== ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND ||
|
|
39
|
+
!isBoundedText(input.reviewerCallId, ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH) ||
|
|
40
|
+
!isBoundedText(input.callerCallId, ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH) ||
|
|
41
|
+
!isBoundedText(input.reviewScopeId, ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH) ||
|
|
42
|
+
!Number.isSafeInteger(input.sourceRevision) ||
|
|
43
|
+
input.sourceRevision < 0 ||
|
|
44
|
+
(input.verdict !== "pass" && input.verdict !== "report_gaps") ||
|
|
45
|
+
!Array.isArray(input.gaps) ||
|
|
46
|
+
input.gaps.length > ROLE_CALL_REVIEWER_VERDICT_MAX_GAPS ||
|
|
47
|
+
(input.verdict === "pass" && input.gaps.length !== 0) ||
|
|
48
|
+
(input.verdict === "report_gaps" && input.gaps.length === 0)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const gaps = input.gaps.map(normalizeGap);
|
|
52
|
+
if (gaps.some((gap) => gap === null))
|
|
53
|
+
return null;
|
|
54
|
+
const receipt = {
|
|
55
|
+
kind: ROLE_CALL_REVIEWER_VERDICT_RECEIPT_KIND,
|
|
56
|
+
reviewerCallId: input.reviewerCallId.trim(),
|
|
57
|
+
callerCallId: input.callerCallId.trim(),
|
|
58
|
+
reviewScopeId: input.reviewScopeId.trim(),
|
|
59
|
+
sourceRevision: input.sourceRevision,
|
|
60
|
+
verdict: input.verdict,
|
|
61
|
+
gaps: gaps,
|
|
62
|
+
};
|
|
63
|
+
if (JSON.stringify(receipt).length > ROLE_CALL_RESULT_MAX_LENGTH)
|
|
64
|
+
return null;
|
|
65
|
+
return deepFreeze(receipt);
|
|
66
|
+
}
|
|
67
|
+
export function isRoleCallResultReceiptValidForReturn(params) {
|
|
68
|
+
if (params.receipt === undefined)
|
|
69
|
+
return true;
|
|
70
|
+
if (params.receipt.kind === ROLE_CALL_WORK_RESULT_RECEIPT_KIND)
|
|
71
|
+
return false;
|
|
72
|
+
return (Number.isSafeInteger(params.admittedHeadRevision) &&
|
|
73
|
+
params.receipt.sourceRevision === params.admittedHeadRevision &&
|
|
74
|
+
isRoleCallResultReceiptBound({
|
|
75
|
+
receipt: params.receipt,
|
|
76
|
+
callerCallId: params.caller.callId,
|
|
77
|
+
childCallId: params.child.callId,
|
|
78
|
+
childRoleId: params.child.roleId,
|
|
79
|
+
outcome: params.outcome,
|
|
80
|
+
policy: params.policy,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
export function isRoleCallResultReceiptValidForStoredResult(params) {
|
|
84
|
+
if (params.receipt === undefined) {
|
|
85
|
+
return !mustIssueSupervisorWorkResultReceipt({
|
|
86
|
+
child: params.producer,
|
|
87
|
+
policy: params.policy,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (params.receipt.kind === ROLE_CALL_WORK_RESULT_RECEIPT_KIND) {
|
|
91
|
+
if (!params.state)
|
|
92
|
+
return false;
|
|
93
|
+
return isRoleCallWorkResultReceiptValidForStoredResult({
|
|
94
|
+
state: params.state,
|
|
95
|
+
producer: params.producer,
|
|
96
|
+
result: params.result,
|
|
97
|
+
receipt: params.receipt,
|
|
98
|
+
policy: params.policy,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return (params.producer.parentCallId !== null &&
|
|
102
|
+
isRoleCallResultReceiptBound({
|
|
103
|
+
receipt: params.receipt,
|
|
104
|
+
callerCallId: params.producer.parentCallId,
|
|
105
|
+
childCallId: params.producer.callId,
|
|
106
|
+
childRoleId: params.producer.roleId,
|
|
107
|
+
outcome: params.result.outcome,
|
|
108
|
+
policy: params.policy,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
export function isRoleCallReviewerVerdictReceiptBoundToChild(params) {
|
|
112
|
+
const normalized = normalizeRoleCallReviewerVerdictReceipt(params.receipt);
|
|
113
|
+
return (normalized !== null &&
|
|
114
|
+
normalized !== undefined &&
|
|
115
|
+
params.childRoleId === "reviewer" &&
|
|
116
|
+
params.outcome === "completed" &&
|
|
117
|
+
normalized.reviewerCallId === params.childCallId &&
|
|
118
|
+
normalized.callerCallId === params.callerCallId &&
|
|
119
|
+
normalized.reviewScopeId ===
|
|
120
|
+
`review:${params.childCallId}:r${normalized.sourceRevision}`);
|
|
121
|
+
}
|
|
122
|
+
function isRoleCallResultReceiptBound(params) {
|
|
123
|
+
const normalized = normalizeRoleCallReviewerVerdictReceipt(params.receipt);
|
|
124
|
+
return (normalized !== null &&
|
|
125
|
+
normalized !== undefined &&
|
|
126
|
+
hasDelegatedReviewerReceiptAuthority(params.policy) &&
|
|
127
|
+
isRoleCallReviewerVerdictReceiptBoundToChild({
|
|
128
|
+
receipt: normalized,
|
|
129
|
+
callerCallId: params.callerCallId,
|
|
130
|
+
childCallId: params.childCallId,
|
|
131
|
+
childRoleId: params.childRoleId,
|
|
132
|
+
outcome: params.outcome,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
function hasDelegatedReviewerReceiptAuthority(policy) {
|
|
136
|
+
const expected = SUPERVISOR_WORKER_V1_AUTHORITY_SNAPSHOT;
|
|
137
|
+
return (policy.authority.id === expected.id &&
|
|
138
|
+
policy.authority.version === expected.version &&
|
|
139
|
+
policy.authority.definitionHash === expected.definitionHash);
|
|
140
|
+
}
|
|
141
|
+
function normalizeGap(value) {
|
|
142
|
+
if (!isRecord(value) ||
|
|
143
|
+
!exactKeys(value, [
|
|
144
|
+
"kind",
|
|
145
|
+
"subjectRefs",
|
|
146
|
+
"factRefs",
|
|
147
|
+
"evidenceRefs",
|
|
148
|
+
"summary",
|
|
149
|
+
]) ||
|
|
150
|
+
!isBoundedText(value.kind, ROLE_CALL_REVIEWER_VERDICT_KIND_MAX_LENGTH) ||
|
|
151
|
+
!isBoundedText(value.summary, ROLE_CALL_REVIEWER_VERDICT_GAP_SUMMARY_MAX_LENGTH)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const subjectRefs = normalizeRefs(value.subjectRefs);
|
|
155
|
+
const factRefs = normalizeRefs(value.factRefs);
|
|
156
|
+
const evidenceRefs = normalizeRefs(value.evidenceRefs);
|
|
157
|
+
if (!subjectRefs || !factRefs || !evidenceRefs)
|
|
158
|
+
return null;
|
|
159
|
+
return Object.freeze({
|
|
160
|
+
kind: value.kind.trim(),
|
|
161
|
+
subjectRefs,
|
|
162
|
+
factRefs,
|
|
163
|
+
evidenceRefs,
|
|
164
|
+
summary: value.summary.trim(),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function normalizeRefs(value) {
|
|
168
|
+
if (!Array.isArray(value) ||
|
|
169
|
+
value.length > ROLE_CALL_REVIEWER_VERDICT_MAX_REFS_PER_GAP ||
|
|
170
|
+
value.some((entry) => !isBoundedText(entry, ROLE_CALL_REVIEWER_VERDICT_REFERENCE_MAX_LENGTH))) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return Object.freeze(value.map((entry) => entry.trim()));
|
|
174
|
+
}
|
|
175
|
+
function isBoundedText(value, maximumLength) {
|
|
176
|
+
return (typeof value === "string" &&
|
|
177
|
+
value.trim().length > 0 &&
|
|
178
|
+
value.length <= maximumLength);
|
|
179
|
+
}
|
|
180
|
+
function deepFreeze(value) {
|
|
181
|
+
if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
Object.freeze(value);
|
|
185
|
+
for (const child of Object.values(value))
|
|
186
|
+
deepFreeze(child);
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RoleCallFrame, RoleCallPolicy, RoleCallResult, RoleCallState } from "./contracts.js";
|
|
2
|
+
import { type RoleCallResultReceipt } from "./result-receipt.js";
|
|
3
|
+
export type CanonicalResultReceiptResolution = Readonly<{
|
|
4
|
+
ok: true;
|
|
5
|
+
receipt?: RoleCallResultReceipt;
|
|
6
|
+
}> | Readonly<{
|
|
7
|
+
ok: false;
|
|
8
|
+
issueCode: "work_result_receipt_forged" | "work_result_lineage_invalid" | "result_receipt_invalid";
|
|
9
|
+
}>;
|
|
10
|
+
export declare function resolveCanonicalResultReceiptForReturn(params: Readonly<{
|
|
11
|
+
state: RoleCallState;
|
|
12
|
+
caller: RoleCallFrame;
|
|
13
|
+
child: RoleCallFrame;
|
|
14
|
+
resultRef: string;
|
|
15
|
+
outcome: RoleCallResult["outcome"];
|
|
16
|
+
suppliedReceipt?: RoleCallResultReceipt;
|
|
17
|
+
policy: RoleCallPolicy;
|
|
18
|
+
admittedHeadRevision?: number;
|
|
19
|
+
}>): CanonicalResultReceiptResolution;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isRoleCallResultReceiptValidForReturn, } from "./result-receipt.js";
|
|
2
|
+
import { createCanonicalRoleCallWorkResultReceipt, mustIssueSupervisorWorkResultReceipt, ROLE_CALL_WORK_RESULT_RECEIPT_KIND, } from "./work-result-receipt.js";
|
|
3
|
+
export function resolveCanonicalResultReceiptForReturn(params) {
|
|
4
|
+
if (params.suppliedReceipt?.kind === ROLE_CALL_WORK_RESULT_RECEIPT_KIND) {
|
|
5
|
+
return invalidResolution("work_result_receipt_forged");
|
|
6
|
+
}
|
|
7
|
+
if (mustIssueSupervisorWorkResultReceipt({
|
|
8
|
+
child: params.child,
|
|
9
|
+
policy: params.policy,
|
|
10
|
+
})) {
|
|
11
|
+
return resolveRuntimeOwnedWorkReceipt(params);
|
|
12
|
+
}
|
|
13
|
+
if (!isRoleCallResultReceiptValidForReturn({
|
|
14
|
+
receipt: params.suppliedReceipt,
|
|
15
|
+
caller: params.caller,
|
|
16
|
+
child: params.child,
|
|
17
|
+
outcome: params.outcome,
|
|
18
|
+
policy: params.policy,
|
|
19
|
+
admittedHeadRevision: params.admittedHeadRevision,
|
|
20
|
+
})) {
|
|
21
|
+
return invalidResolution("result_receipt_invalid");
|
|
22
|
+
}
|
|
23
|
+
return params.suppliedReceipt
|
|
24
|
+
? Object.freeze({ ok: true, receipt: params.suppliedReceipt })
|
|
25
|
+
: Object.freeze({ ok: true });
|
|
26
|
+
}
|
|
27
|
+
function resolveRuntimeOwnedWorkReceipt(params) {
|
|
28
|
+
if (params.suppliedReceipt !== undefined) {
|
|
29
|
+
return invalidResolution("work_result_receipt_forged");
|
|
30
|
+
}
|
|
31
|
+
if (!isNonNegativeSafeInteger(params.admittedHeadRevision)) {
|
|
32
|
+
return invalidResolution("work_result_lineage_invalid");
|
|
33
|
+
}
|
|
34
|
+
const receipt = createCanonicalRoleCallWorkResultReceipt({
|
|
35
|
+
state: params.state,
|
|
36
|
+
caller: params.caller,
|
|
37
|
+
child: params.child,
|
|
38
|
+
resultRef: params.resultRef,
|
|
39
|
+
outcome: params.outcome,
|
|
40
|
+
admittedHeadRevision: params.admittedHeadRevision,
|
|
41
|
+
policy: params.policy,
|
|
42
|
+
});
|
|
43
|
+
return receipt
|
|
44
|
+
? Object.freeze({ ok: true, receipt })
|
|
45
|
+
: invalidResolution("work_result_lineage_invalid");
|
|
46
|
+
}
|
|
47
|
+
function invalidResolution(issueCode) {
|
|
48
|
+
return Object.freeze({ ok: false, issueCode });
|
|
49
|
+
}
|
|
50
|
+
function isNonNegativeSafeInteger(value) {
|
|
51
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
52
|
+
}
|
|
@@ -36,6 +36,7 @@ export function createRoleCallTransactions(apply) {
|
|
|
36
36
|
childCallId: input.childCallId,
|
|
37
37
|
outcome: input.outcome,
|
|
38
38
|
summary: input.summary,
|
|
39
|
+
...(input.receipt ? { receipt: input.receipt } : {}),
|
|
39
40
|
},
|
|
40
41
|
}), "child_returned", "child_return_transition_invalid", (effect) => effect.callerCallId === input.callerCallId &&
|
|
41
42
|
effect.childCallId === input.childCallId);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { RoleCallFrame, RoleCallPlanItemStatus, RoleCallResult, RoleCallState } from "./contracts.js";
|
|
2
|
+
import type { RoleCallWorkResultReceipt } from "./work-result-receipt.js";
|
|
3
|
+
export declare const ROLE_CALL_WORK_RESULT_LINEAGE_KIND: "work_result_lineage_v1";
|
|
4
|
+
type TerminalPlanItemStatus = Exclude<RoleCallPlanItemStatus, "in_progress">;
|
|
5
|
+
export type RoleCallWorkResultPlanItem = Readonly<{
|
|
6
|
+
itemId: string;
|
|
7
|
+
status: TerminalPlanItemStatus;
|
|
8
|
+
resultRef: string | null;
|
|
9
|
+
}>;
|
|
10
|
+
export type RoleCallWorkResultPlanSnapshot = Readonly<{
|
|
11
|
+
planId: string;
|
|
12
|
+
planVersion: number;
|
|
13
|
+
items: readonly RoleCallWorkResultPlanItem[];
|
|
14
|
+
}>;
|
|
15
|
+
export type RoleCallWorkResultLineage = Readonly<{
|
|
16
|
+
kind: typeof ROLE_CALL_WORK_RESULT_LINEAGE_KIND;
|
|
17
|
+
lineageFingerprint: string;
|
|
18
|
+
capabilityExecutionIds: readonly string[];
|
|
19
|
+
planner?: RoleCallWorkResultPlanSnapshot;
|
|
20
|
+
}>;
|
|
21
|
+
export type RoleCallWorkLineageProjection = RoleCallWorkResultLineage;
|
|
22
|
+
export type CanonicalRoleCallWorkResultLineageInput = Readonly<{
|
|
23
|
+
state: RoleCallState;
|
|
24
|
+
producer: RoleCallFrame;
|
|
25
|
+
resultRef: string;
|
|
26
|
+
outcome: RoleCallResult["outcome"];
|
|
27
|
+
sourceRevision: number;
|
|
28
|
+
}>;
|
|
29
|
+
export declare function createCanonicalRoleCallWorkResultLineage(input: CanonicalRoleCallWorkResultLineageInput): RoleCallWorkResultLineage | null;
|
|
30
|
+
export declare function projectRoleCallWorkResultLineage(input: {
|
|
31
|
+
state: RoleCallState;
|
|
32
|
+
receipt: RoleCallWorkResultReceipt;
|
|
33
|
+
}): RoleCallWorkResultLineage | null;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export const ROLE_CALL_WORK_RESULT_LINEAGE_KIND = "work_result_lineage_v1";
|
|
3
|
+
export function createCanonicalRoleCallWorkResultLineage(input) {
|
|
4
|
+
if (!hasCanonicalWorkResultIdentity(input))
|
|
5
|
+
return null;
|
|
6
|
+
const capabilityExecutionIds = resolveSubtreeCapabilityExecutionIds(input.state, input.producer);
|
|
7
|
+
if (!capabilityExecutionIds)
|
|
8
|
+
return null;
|
|
9
|
+
const planner = resolvePlannerSnapshot(input.state, input.producer);
|
|
10
|
+
if (planner === null)
|
|
11
|
+
return null;
|
|
12
|
+
const callerCallId = input.producer.parentCallId;
|
|
13
|
+
if (!callerCallId)
|
|
14
|
+
return null;
|
|
15
|
+
const lineageFingerprint = createLineageFingerprint({
|
|
16
|
+
resultRef: input.resultRef,
|
|
17
|
+
producerCallId: input.producer.callId,
|
|
18
|
+
callerCallId,
|
|
19
|
+
roleId: input.producer.roleId,
|
|
20
|
+
outcome: input.outcome,
|
|
21
|
+
sourceRevision: input.sourceRevision,
|
|
22
|
+
dependencyResultRefs: input.producer.dependencyResultRefs,
|
|
23
|
+
capabilityExecutionIds,
|
|
24
|
+
...(planner ? { planner } : {}),
|
|
25
|
+
});
|
|
26
|
+
return deepFreeze({
|
|
27
|
+
kind: ROLE_CALL_WORK_RESULT_LINEAGE_KIND,
|
|
28
|
+
lineageFingerprint,
|
|
29
|
+
capabilityExecutionIds,
|
|
30
|
+
...(planner ? { planner } : {}),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function projectRoleCallWorkResultLineage(input) {
|
|
34
|
+
const result = findUniqueProducerResult(input.state, input.receipt);
|
|
35
|
+
if (!result)
|
|
36
|
+
return null;
|
|
37
|
+
const producer = input.state.calls.find(({ callId }) => callId === input.receipt.producerCallId);
|
|
38
|
+
if (!producer || !isStoredResultBoundToProducer(producer, result)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (producer.parentCallId !== input.receipt.callerCallId)
|
|
42
|
+
return null;
|
|
43
|
+
const lineage = createCanonicalRoleCallWorkResultLineage({
|
|
44
|
+
state: input.state,
|
|
45
|
+
producer,
|
|
46
|
+
resultRef: result.resultRef,
|
|
47
|
+
outcome: result.outcome,
|
|
48
|
+
sourceRevision: input.receipt.sourceRevision,
|
|
49
|
+
});
|
|
50
|
+
if (!lineage)
|
|
51
|
+
return null;
|
|
52
|
+
if (lineage.lineageFingerprint !== input.receipt.lineageFingerprint) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (!matchesPlannerPlanReference(lineage, input.receipt))
|
|
56
|
+
return null;
|
|
57
|
+
return lineage;
|
|
58
|
+
}
|
|
59
|
+
function hasCanonicalWorkResultIdentity(input) {
|
|
60
|
+
if (input.producer.roleId !== "planner" && input.producer.roleId !== "worker") {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (!input.producer.parentCallId)
|
|
64
|
+
return false;
|
|
65
|
+
if (!input.resultRef.trim())
|
|
66
|
+
return false;
|
|
67
|
+
if (input.outcome !== "completed" && input.outcome !== "failed")
|
|
68
|
+
return false;
|
|
69
|
+
return Number.isSafeInteger(input.sourceRevision) && input.sourceRevision >= 0;
|
|
70
|
+
}
|
|
71
|
+
function resolveSubtreeCapabilityExecutionIds(state, producer) {
|
|
72
|
+
const subtreeCallIds = resolveSubtreeCallIds(state, producer);
|
|
73
|
+
if (!subtreeCallIds)
|
|
74
|
+
return null;
|
|
75
|
+
const executions = state.capabilityExecutions.filter(({ callId }) => subtreeCallIds.has(callId));
|
|
76
|
+
if (executions.some(({ status }) => status !== "settled"))
|
|
77
|
+
return null;
|
|
78
|
+
return Object.freeze(executions.map(({ executionId }) => executionId));
|
|
79
|
+
}
|
|
80
|
+
function resolveSubtreeCallIds(state, producer) {
|
|
81
|
+
const callById = new Map(state.calls.map((call) => [call.callId, call]));
|
|
82
|
+
if (callById.get(producer.callId) !== producer)
|
|
83
|
+
return null;
|
|
84
|
+
const visited = new Set();
|
|
85
|
+
const pending = [producer.callId];
|
|
86
|
+
while (pending.length > 0) {
|
|
87
|
+
const callId = pending.pop();
|
|
88
|
+
if (!callId || visited.has(callId))
|
|
89
|
+
return null;
|
|
90
|
+
const call = callById.get(callId);
|
|
91
|
+
if (!call)
|
|
92
|
+
return null;
|
|
93
|
+
visited.add(callId);
|
|
94
|
+
for (const childCallId of call.childCallIds) {
|
|
95
|
+
const child = callById.get(childCallId);
|
|
96
|
+
if (!child || child.parentCallId !== callId)
|
|
97
|
+
return null;
|
|
98
|
+
pending.push(childCallId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return visited;
|
|
102
|
+
}
|
|
103
|
+
function resolvePlannerSnapshot(state, producer) {
|
|
104
|
+
if (producer.roleId !== "planner")
|
|
105
|
+
return undefined;
|
|
106
|
+
const plans = state.plans.filter(({ definition }) => definition.plannerCallId === producer.callId);
|
|
107
|
+
if (plans.length === 0)
|
|
108
|
+
return undefined;
|
|
109
|
+
if (plans.length !== 1)
|
|
110
|
+
return null;
|
|
111
|
+
const plan = plans[0];
|
|
112
|
+
if (plan.definition.items.length !== plan.itemStates.length)
|
|
113
|
+
return null;
|
|
114
|
+
const items = plan.definition.items.map(({ itemId }) => {
|
|
115
|
+
const itemState = plan.itemStates.find((item) => item.itemId === itemId);
|
|
116
|
+
return itemState
|
|
117
|
+
? resolveTerminalPlanItem(state, producer, itemState)
|
|
118
|
+
: null;
|
|
119
|
+
});
|
|
120
|
+
if (items.some((item) => item === null))
|
|
121
|
+
return null;
|
|
122
|
+
return deepFreeze({
|
|
123
|
+
planId: plan.definition.planId,
|
|
124
|
+
planVersion: plan.definition.version,
|
|
125
|
+
items: items,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function resolveTerminalPlanItem(state, producer, item) {
|
|
129
|
+
if (item.status === "in_progress")
|
|
130
|
+
return null;
|
|
131
|
+
if (item.status === "pending") {
|
|
132
|
+
if (item.childCallId !== null)
|
|
133
|
+
return null;
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
itemId: item.itemId,
|
|
136
|
+
status: item.status,
|
|
137
|
+
resultRef: null,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (!item.childCallId)
|
|
141
|
+
return null;
|
|
142
|
+
const child = state.calls.find(({ callId }) => callId === item.childCallId);
|
|
143
|
+
if (!child || child.parentCallId !== producer.callId || !child.resultRef) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const result = state.results.find(({ resultRef }) => resultRef === child.resultRef);
|
|
147
|
+
if (!result || result.producerCallId !== child.callId)
|
|
148
|
+
return null;
|
|
149
|
+
return Object.freeze({
|
|
150
|
+
itemId: item.itemId,
|
|
151
|
+
status: item.status,
|
|
152
|
+
resultRef: result.resultRef,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function findUniqueProducerResult(state, receipt) {
|
|
156
|
+
const results = state.results.filter(({ producerCallId }) => producerCallId === receipt.producerCallId);
|
|
157
|
+
return results.length === 1 ? results[0] : undefined;
|
|
158
|
+
}
|
|
159
|
+
function isStoredResultBoundToProducer(producer, result) {
|
|
160
|
+
return (producer.status === "completed" &&
|
|
161
|
+
producer.resultRef === result.resultRef &&
|
|
162
|
+
producer.roleId === result.roleId);
|
|
163
|
+
}
|
|
164
|
+
function matchesPlannerPlanReference(lineage, receipt) {
|
|
165
|
+
if (!lineage.planner)
|
|
166
|
+
return receipt.plannerPlanRef === undefined;
|
|
167
|
+
return (receipt.plannerPlanRef?.planId === lineage.planner.planId &&
|
|
168
|
+
receipt.plannerPlanRef.planVersion === lineage.planner.planVersion);
|
|
169
|
+
}
|
|
170
|
+
function createLineageFingerprint(input) {
|
|
171
|
+
const canonical = JSON.stringify({
|
|
172
|
+
kind: ROLE_CALL_WORK_RESULT_LINEAGE_KIND,
|
|
173
|
+
...input,
|
|
174
|
+
});
|
|
175
|
+
return `sha256:${createHash("sha256").update(canonical).digest("hex")}`;
|
|
176
|
+
}
|
|
177
|
+
function deepFreeze(value) {
|
|
178
|
+
if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
Object.freeze(value);
|
|
182
|
+
for (const child of Object.values(value))
|
|
183
|
+
deepFreeze(child);
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type RoleCallFrame, type RoleCallPolicy, type RoleCallResult, type RoleCallState } from "./contracts.js";
|
|
2
|
+
export declare const ROLE_CALL_WORK_RESULT_RECEIPT_KIND: "work_result_v1";
|
|
3
|
+
export declare const ROLE_CALL_WORK_RESULT_FINGERPRINT_PATTERN: RegExp;
|
|
4
|
+
export type RoleCallWorkResultReceipt = Readonly<{
|
|
5
|
+
kind: typeof ROLE_CALL_WORK_RESULT_RECEIPT_KIND;
|
|
6
|
+
producerCallId: string;
|
|
7
|
+
callerCallId: string;
|
|
8
|
+
sourceRevision: number;
|
|
9
|
+
lineageFingerprint: string;
|
|
10
|
+
plannerPlanRef?: Readonly<{
|
|
11
|
+
planId: string;
|
|
12
|
+
planVersion: number;
|
|
13
|
+
}>;
|
|
14
|
+
}>;
|
|
15
|
+
export type CanonicalRoleCallWorkResultReceiptInput = Readonly<{
|
|
16
|
+
state: RoleCallState;
|
|
17
|
+
caller: RoleCallFrame;
|
|
18
|
+
child: RoleCallFrame;
|
|
19
|
+
resultRef: string;
|
|
20
|
+
outcome: RoleCallResult["outcome"];
|
|
21
|
+
policy: RoleCallPolicy;
|
|
22
|
+
admittedHeadRevision: number | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function normalizeRoleCallWorkResultReceipt(input: unknown): RoleCallWorkResultReceipt | undefined | null;
|
|
25
|
+
export declare function mustIssueSupervisorWorkResultReceipt(input: {
|
|
26
|
+
child: RoleCallFrame;
|
|
27
|
+
policy: RoleCallPolicy;
|
|
28
|
+
}): boolean;
|
|
29
|
+
export declare function createCanonicalRoleCallWorkResultReceipt(input: CanonicalRoleCallWorkResultReceiptInput): RoleCallWorkResultReceipt | null;
|
|
30
|
+
export declare function isRoleCallWorkResultReceiptValidForStoredResult(input: {
|
|
31
|
+
state: RoleCallState;
|
|
32
|
+
receipt: RoleCallWorkResultReceipt;
|
|
33
|
+
producer: RoleCallFrame;
|
|
34
|
+
result: RoleCallResult;
|
|
35
|
+
policy: RoleCallPolicy;
|
|
36
|
+
}): boolean;
|