@dipoleml/dcode-cli 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/dist/THIRD-PARTY-NOTICES.md +1081 -12
- package/dist/dcode.cjs +59253 -45604
- package/dist/packages/browser-use-plugin/README.md +12 -12
- package/dist/packages/browser-use-plugin/docs/api.json +1 -1
- package/dist/packages/browser-use-plugin/docs/overview.md +5 -4
- package/dist/packages/browser-use-plugin/docs/workflow.md +1 -1
- package/dist/packages/browser-use-plugin/scripts/build.mjs +1 -0
- package/dist/packages/browser-use-plugin/skills/control-browser/SKILL.md +10 -7
- package/dist/packages/bundled-skills/skills/dynamic-workflows/SKILL.md +760 -687
- package/dist/packages/bundled-skills/skills/dynamic-workflows/examples.md +310 -1
- package/dist/packages/bundled-skills/skills/dynamic-workflows/patterns.md +336 -4
- package/dist/packages/node-repl-host/.dcode-plugin/plugin.json +1 -1
- package/dist/packages/node-repl-host/dist/mcp/server.js +9 -14
- package/dist/packages/node-repl-host/scripts/build.mjs +1 -0
- package/dist/provider/dcode-builtin.json +6612 -202
- package/node_modules/@dcode/contracts/dist/compact/index.d.ts +7 -7
- package/node_modules/@dcode/contracts/dist/config/index.d.ts +1 -1
- package/node_modules/@dcode/contracts/dist/events/event-reducer.js +1 -0
- package/node_modules/@dcode/contracts/dist/events/in-memory-session-event-store.js +3 -2
- package/node_modules/@dcode/contracts/dist/events/session-event-retention.d.ts +8 -0
- package/node_modules/@dcode/contracts/dist/events/session-event-retention.js +18 -0
- package/node_modules/@dcode/contracts/dist/events/session.events.d.ts +94 -16
- package/node_modules/@dcode/contracts/dist/events/session.events.js +10 -0
- package/node_modules/@dcode/contracts/dist/hooks/index.d.ts +134 -134
- package/node_modules/@dcode/contracts/dist/hooks/workspace-hook-trust.d.ts +14 -14
- package/node_modules/@dcode/contracts/dist/index.d.ts +2 -0
- package/node_modules/@dcode/contracts/dist/index.js +2 -0
- package/node_modules/@dcode/contracts/dist/interfaces/browser-control.port.d.ts +22 -0
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run-hole.port.d.ts +92 -0
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run-hole.port.js +9 -0
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run-retune.port.d.ts +4 -4
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run-retune.port.js +7 -3
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run-workspace.port.js +8 -3
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run.port.d.ts +119 -18
- package/node_modules/@dcode/contracts/dist/interfaces/dynamic-workflow-run.port.js +13 -0
- package/node_modules/@dcode/contracts/dist/interfaces/index.d.ts +1 -0
- package/node_modules/@dcode/contracts/dist/interfaces/index.js +1 -0
- package/node_modules/@dcode/contracts/dist/interfaces/mcp.port.d.ts +161 -1
- package/node_modules/@dcode/contracts/dist/interfaces/mcp.port.js +17 -0
- package/node_modules/@dcode/contracts/dist/interfaces/permission-full-access.d.ts +15 -15
- package/node_modules/@dcode/contracts/dist/interfaces/permission-full-access.js +1 -1
- package/node_modules/@dcode/contracts/dist/interfaces/permission.port.d.ts +15 -1
- package/node_modules/@dcode/contracts/dist/interfaces/provider-endpoint-routing.port.d.ts +19 -0
- package/node_modules/@dcode/contracts/dist/interfaces/provider-endpoint-routing.port.js +1 -0
- package/node_modules/@dcode/contracts/dist/interfaces/session-store.port.d.ts +4 -2
- package/node_modules/@dcode/contracts/dist/interfaces/session-store.port.js +5 -0
- package/node_modules/@dcode/contracts/dist/interfaces/session.port.d.ts +92 -3
- package/node_modules/@dcode/contracts/dist/interfaces/session.port.js +4 -1
- package/node_modules/@dcode/contracts/dist/interfaces/topic-resource.port.d.ts +25 -0
- package/node_modules/@dcode/contracts/dist/interfaces/topic-resource.port.js +1 -0
- package/node_modules/@dcode/contracts/dist/model/index.d.ts +15 -1
- package/node_modules/@dcode/contracts/dist/model/index.js +5 -0
- package/node_modules/@dcode/contracts/dist/model/invocation-context.d.ts +6 -1
- package/node_modules/@dcode/contracts/dist/plugins/index.d.ts +23 -0
- package/node_modules/@dcode/contracts/dist/plugins/index.js +2 -1
- package/node_modules/@dcode/contracts/dist/telemetry/agent-execution.d.ts +2 -0
- package/node_modules/@dcode/contracts/dist/telemetry/agent-execution.js +2 -0
- package/node_modules/@dcode/contracts/dist/telemetry/index.d.ts +5 -1
- package/node_modules/@dcode/contracts/dist/telemetry/index.js +12 -0
- package/node_modules/@dcode/contracts/dist/tools/agent.d.ts +12 -12
- package/node_modules/@dcode/contracts/dist/tools/amend-workflow.d.ts +39 -15
- package/node_modules/@dcode/contracts/dist/tools/amend-workflow.js +12 -6
- package/node_modules/@dcode/contracts/dist/tools/automation.d.ts +32 -32
- package/node_modules/@dcode/contracts/dist/tools/automation.js +1 -1
- package/node_modules/@dcode/contracts/dist/tools/bash.d.ts +16 -16
- package/node_modules/@dcode/contracts/dist/tools/bash.js +1 -1
- package/node_modules/@dcode/contracts/dist/tools/create-workflow.d.ts +365 -66
- package/node_modules/@dcode/contracts/dist/tools/create-workflow.js +92 -11
- package/node_modules/@dcode/contracts/dist/tools/edit.d.ts +16 -16
- package/node_modules/@dcode/contracts/dist/tools/eval-workflow-snippet.d.ts +6 -6
- package/node_modules/@dcode/contracts/dist/tools/eval-workflow-snippet.js +5 -1
- package/node_modules/@dcode/contracts/dist/tools/fill-workflow-hole.d.ts +729 -0
- package/node_modules/@dcode/contracts/dist/tools/fill-workflow-hole.js +102 -0
- package/node_modules/@dcode/contracts/dist/tools/get-workflow-run.d.ts +136 -28
- package/node_modules/@dcode/contracts/dist/tools/get-workflow-run.js +36 -0
- package/node_modules/@dcode/contracts/dist/tools/grep.d.ts +4 -4
- package/node_modules/@dcode/contracts/dist/tools/grep.js +4 -0
- package/node_modules/@dcode/contracts/dist/tools/index.d.ts +2 -0
- package/node_modules/@dcode/contracts/dist/tools/index.js +4 -0
- package/node_modules/@dcode/contracts/dist/tools/list-saved-workflows.d.ts +8 -8
- package/node_modules/@dcode/contracts/dist/tools/list-workflow-runs.d.ts +8 -8
- package/node_modules/@dcode/contracts/dist/tools/node-repl.d.ts +2 -2
- package/node_modules/@dcode/contracts/dist/tools/off-peak.d.ts +3 -3
- package/node_modules/@dcode/contracts/dist/tools/off-peak.js +2 -2
- package/node_modules/@dcode/contracts/dist/tools/performance.d.ts +22 -22
- package/node_modules/@dcode/contracts/dist/tools/plan-mode.d.ts +12 -12
- package/node_modules/@dcode/contracts/dist/tools/plan-mode.js +6 -4
- package/node_modules/@dcode/contracts/dist/tools/read-session-context.d.ts +86 -13
- package/node_modules/@dcode/contracts/dist/tools/read-session-context.js +37 -6
- package/node_modules/@dcode/contracts/dist/tools/read.d.ts +38 -38
- package/node_modules/@dcode/contracts/dist/tools/save-workflow.d.ts +21 -10
- package/node_modules/@dcode/contracts/dist/tools/save-workflow.js +22 -2
- package/node_modules/@dcode/contracts/dist/tools/saved-workflow.d.ts +4 -4
- package/node_modules/@dcode/contracts/dist/tools/send-message.d.ts +2 -2
- package/node_modules/@dcode/contracts/dist/tools/skill.js +1 -0
- package/node_modules/@dcode/contracts/dist/tools/task-output.d.ts +6 -6
- package/node_modules/@dcode/contracts/dist/tools/tool-result-metadata.d.ts +1228 -259
- package/node_modules/@dcode/contracts/dist/tools/tool-result-metadata.js +41 -0
- package/node_modules/@dcode/contracts/dist/tools/webfetch.d.ts +2 -2
- package/node_modules/@dcode/contracts/dist/tools/workflow-observation-display.d.ts +20 -20
- package/node_modules/@dcode/contracts/dist/tools/workflow-settings.d.ts +55 -0
- package/node_modules/@dcode/contracts/dist/tools/workflow-settings.js +86 -0
- package/node_modules/@dcode/contracts/dist/tools/workflow.d.ts +8 -8
- package/node_modules/@dcode/contracts/dist/tools/write.d.ts +18 -18
- package/node_modules/@dcode/contracts/dist/workflow/index.d.ts +98 -98
- package/node_modules/@dcode/contracts/dist/workflow/script.d.ts +12 -12
- package/node_modules/@dcode/i18n/dist/index.js +2 -2
- package/node_modules/@dcode/i18n/dist/locale.d.ts +1 -1
- package/node_modules/@dcode/i18n/dist/locale.js +4 -4
- package/node_modules/@dcode/i18n/dist/locales/en-US.js +5 -5
- package/node_modules/@dcode/i18n/dist/locales/fr-CA.d.ts +3 -0
- package/node_modules/@dcode/i18n/dist/locales/fr-CA.js +354 -0
- package/node_modules/@dcode/model-option-map/package.json +1 -1
- package/node_modules/@dcode/shared/dist/api-key-usage-scene.d.ts +7 -0
- package/node_modules/@dcode/shared/dist/api-key-usage-scene.js +6 -0
- package/node_modules/@dcode/shared/dist/attachment-source.d.ts +8 -0
- package/node_modules/@dcode/shared/dist/attachment-source.js +4 -0
- package/node_modules/@dcode/shared/dist/background-bash-output.d.ts +4 -4
- package/node_modules/@dcode/shared/dist/bots.d.ts +763 -15
- package/node_modules/@dcode/shared/dist/bots.js +236 -2
- package/node_modules/@dcode/shared/dist/browser-use/command-metadata.d.ts +2 -2
- package/node_modules/@dcode/shared/dist/browser-use/commands.d.ts +4 -3
- package/node_modules/@dcode/shared/dist/browser-use/commands.js +3 -1
- package/node_modules/@dcode/shared/dist/browser-use/nodeReplBroker.d.ts +5 -4
- package/node_modules/@dcode/shared/dist/browser-use/result.d.ts +6 -6
- package/node_modules/@dcode/shared/dist/channel-mention.d.ts +173 -0
- package/node_modules/@dcode/shared/dist/channel-mention.js +120 -0
- package/node_modules/@dcode/shared/dist/channels.d.ts +128 -1
- package/node_modules/@dcode/shared/dist/channels.js +66 -0
- package/node_modules/@dcode/shared/dist/clientConfig.d.ts +1 -0
- package/node_modules/@dcode/shared/dist/clientConfig.js +18 -2
- package/node_modules/@dcode/shared/dist/cloudContent.d.ts +160 -0
- package/node_modules/@dcode/shared/dist/cloudContent.js +116 -0
- package/node_modules/@dcode/shared/dist/coding-plan-subscription.d.ts +59 -0
- package/node_modules/@dcode/shared/dist/conversation-message-projection-policy.js +2 -0
- package/node_modules/@dcode/shared/dist/conversation-share.d.ts +351 -47
- package/node_modules/@dcode/shared/dist/conversation-share.js +8 -6
- package/node_modules/@dcode/shared/dist/conversationSelection.d.ts +23 -0
- package/node_modules/@dcode/shared/dist/conversationSelection.js +30 -0
- package/node_modules/@dcode/shared/dist/database-startup.d.ts +5 -5
- package/node_modules/@dcode/shared/dist/dcode-agent-model-state.js +14 -6
- package/node_modules/@dcode/shared/dist/dcode-agent-policy.d.ts +16 -1
- package/node_modules/@dcode/shared/dist/dcode-agent-policy.js +17 -1
- package/node_modules/@dcode/shared/dist/dcode-agent-runtime.js +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol/index.d.ts +1733 -318
- package/node_modules/@dcode/shared/dist/dcode-protocol/index.js +555 -24
- package/node_modules/@dcode/shared/dist/dcode-protocol/trace.d.ts +9 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol/trace.js +10 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-legacy-types.d.ts +30 -20
- package/node_modules/@dcode/shared/dist/dcode-protocol-legacy-types.js +3 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/apply.js +12 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/attachment-ref.d.ts +5 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/attachment-ref.js +3 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/coalesce.d.ts +3 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/coalesce.js +3 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/command.d.ts +359 -28
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/command.js +67 -45
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/controller.d.ts +170 -65
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/create-session-config.d.ts +20 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/create-session-config.js +15 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/create-workflow-display.d.ts +34 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/create-workflow-display.js +45 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/delta.d.ts +1453 -278
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/delta.js +45 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/index.d.ts +1 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/index.js +1 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/input-intent.d.ts +173 -6
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/input-intent.js +29 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/rows.d.ts +731 -125
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/rows.js +23 -11
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/sessions-index-workflow-activity.d.ts +30 -11
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/sessions-index-workflow-activity.js +35 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/sessions-index.d.ts +40 -25
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/snapshot.d.ts +1444 -216
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/snapshot.js +3 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/submission.d.ts +1 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/submission.js +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/telemetry.d.ts +62 -58
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/toolDisplay.d.ts +185 -50
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/toolDisplay.js +31 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/transport.d.ts +7145 -1002
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/transport.js +18 -5
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/wire-assembler.js +2 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/wire-fault.js +4 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/wire-reassembly.js +5 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-artifacts.d.ts +29 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-artifacts.js +64 -4
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-command-rejections.d.ts +13 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-command-rejections.js +23 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-observation-display.d.ts +14 -14
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-row-meta.d.ts +52 -8
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-row-meta.js +22 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-run-settings-command.d.ts +4 -4
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-run-settings-command.js +2 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-actor-session.d.ts +21 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-actor-session.js +44 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-actor-status.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-actor-status.js +3 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-caps.js +5 -4
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-concurrency.d.ts +26 -19
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-concurrency.js +40 -32
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-delta.d.ts +4 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-delta.js +4 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-entries.d.ts +12 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-entries.js +44 -6
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-eviction.d.ts +2 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-eviction.js +17 -10
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-holes.d.ts +33 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-holes.js +202 -0
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-legacy.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-legacy.js +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-phases.js +10 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-reducer.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-reducer.js +29 -22
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-started.js +5 -2
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-tables.js +2 -1
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs-unlisted.js +6 -3
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs.d.ts +125 -40
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-runs.js +101 -26
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workflow-workspace.d.ts +4 -4
- package/node_modules/@dcode/shared/dist/dcode-protocol-v4/workspace-hook-review.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/dcode-session-content-profile.d.ts +5 -0
- package/node_modules/@dcode/shared/dist/dcode-session-content-profile.js +49 -0
- package/node_modules/@dcode/shared/dist/dcode-slash-command-help.js +4 -4
- package/node_modules/@dcode/shared/dist/dcode-task-mode-schema.d.ts +6 -1
- package/node_modules/@dcode/shared/dist/dcode-task-mode-schema.js +13 -1
- package/node_modules/@dcode/shared/dist/dcode-task-types-core.d.ts +12 -2
- package/node_modules/@dcode/shared/dist/dcode-task-types.d.ts +23 -0
- package/node_modules/@dcode/shared/dist/dcodeEndpoint.d.ts +20 -1
- package/node_modules/@dcode/shared/dist/dcodeEndpoint.js +98 -17
- package/node_modules/@dcode/shared/dist/desktopMenu.js +48 -48
- package/node_modules/@dcode/shared/dist/dynamic-workflow-feature.d.ts +35 -6
- package/node_modules/@dcode/shared/dist/dynamic-workflow-feature.js +45 -6
- package/node_modules/@dcode/shared/dist/env.d.ts +5 -4
- package/node_modules/@dcode/shared/dist/env.js +9 -9
- package/node_modules/@dcode/shared/dist/errors.d.ts +24 -0
- package/node_modules/@dcode/shared/dist/errors.js +54 -0
- package/node_modules/@dcode/shared/dist/execution-state.d.ts +4 -2
- package/node_modules/@dcode/shared/dist/execution-state.js +1 -1
- package/node_modules/@dcode/shared/dist/feedback.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/gen-ui/contract.d.ts +140 -0
- package/node_modules/@dcode/shared/dist/gen-ui/contract.example.d.ts +5 -0
- package/node_modules/@dcode/shared/dist/gen-ui/contract.example.js +36 -0
- package/node_modules/@dcode/shared/dist/gen-ui/contract.js +196 -0
- package/node_modules/@dcode/shared/dist/gen-ui/contract.test.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/gen-ui/contract.test.js +75 -0
- package/node_modules/@dcode/shared/dist/gen-ui/index.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/gen-ui/index.js +2 -0
- package/node_modules/@dcode/shared/dist/gen-ui/module.d.ts +7 -0
- package/node_modules/@dcode/shared/dist/gen-ui/module.js +7 -0
- package/node_modules/@dcode/shared/dist/gen-ui/tweakProtocol.d.ts +202 -0
- package/node_modules/@dcode/shared/dist/gen-ui/tweakProtocol.js +126 -0
- package/node_modules/@dcode/shared/dist/helpAppConfig.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/helpAppConfig.js +2 -2
- package/node_modules/@dcode/shared/dist/highspeed.d.ts +181 -0
- package/node_modules/@dcode/shared/dist/highspeed.js +112 -0
- package/node_modules/@dcode/shared/dist/index.d.ts +27 -5
- package/node_modules/@dcode/shared/dist/index.js +24 -2
- package/node_modules/@dcode/shared/dist/localTtft.d.ts +27 -27
- package/node_modules/@dcode/shared/dist/marketingTouch.d.ts +930 -0
- package/node_modules/@dcode/shared/dist/marketingTouch.js +170 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/appTools.d.ts +83 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/appTools.js +124 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/content.d.ts +4 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/content.js +8 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.d.ts +241 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.example.d.ts +31 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.example.js +42 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.js +101 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.test.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/contract.test.js +64 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/hostContract.d.ts +47 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/hostContract.js +8 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/index.d.ts +9 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/index.js +9 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/instance.d.ts +10 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/instance.js +11 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/module.d.ts +12 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/module.js +12 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/resourceMime.d.ts +8 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/resourceMime.js +73 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/sampling.d.ts +101 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/sampling.js +107 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/sampling.test.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/sampling.test.js +55 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/schemas.d.ts +78 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/schemas.js +65 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/toolMeta.d.ts +39 -0
- package/node_modules/@dcode/shared/dist/mcp-apps/toolMeta.js +199 -0
- package/node_modules/@dcode/shared/dist/mcp.d.ts +6 -2
- package/node_modules/@dcode/shared/dist/memory.d.ts +9 -0
- package/node_modules/@dcode/shared/dist/memory.js +2 -0
- package/node_modules/@dcode/shared/dist/model-execution.d.ts +31 -0
- package/node_modules/@dcode/shared/dist/model-execution.js +38 -0
- package/node_modules/@dcode/shared/dist/networkCapture.d.ts +49 -0
- package/node_modules/@dcode/shared/dist/networkCapture.js +41 -0
- package/node_modules/@dcode/shared/dist/node/genUiPaths.d.ts +6 -0
- package/node_modules/@dcode/shared/dist/node/genUiPaths.js +16 -0
- package/node_modules/@dcode/shared/dist/node/genUiPaths.test.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/node/genUiPaths.test.js +30 -0
- package/node_modules/@dcode/shared/dist/node/networkCapture.d.ts +8 -0
- package/node_modules/@dcode/shared/dist/node/networkCapture.js +96 -0
- package/node_modules/@dcode/shared/dist/node/officialPluginCache.d.ts +1 -2
- package/node_modules/@dcode/shared/dist/node/subagentMarkdownMigration.d.ts +1 -2
- package/node_modules/@dcode/shared/dist/node.d.ts +2 -0
- package/node_modules/@dcode/shared/dist/node.js +2 -0
- package/node_modules/@dcode/shared/dist/output-style.d.ts +17 -0
- package/node_modules/@dcode/shared/dist/output-style.js +2 -0
- package/node_modules/@dcode/shared/dist/platform.d.ts +149 -1
- package/node_modules/@dcode/shared/dist/platform.js +2 -0
- package/node_modules/@dcode/shared/dist/platformUpdate.d.ts +61 -0
- package/node_modules/@dcode/shared/dist/platformUpdate.js +2 -0
- package/node_modules/@dcode/shared/dist/plugin-marketplaces.d.ts +5 -0
- package/node_modules/@dcode/shared/dist/plugin-marketplaces.js +20 -14
- package/node_modules/@dcode/shared/dist/project-access-token-client.d.ts +42 -0
- package/node_modules/@dcode/shared/dist/project-access-token-client.js +260 -0
- package/node_modules/@dcode/shared/dist/project-access-token-response.d.ts +4 -0
- package/node_modules/@dcode/shared/dist/project-access-token-response.js +9 -0
- package/node_modules/@dcode/shared/dist/project-access-token.d.ts +45 -0
- package/node_modules/@dcode/shared/dist/project-access-token.js +164 -0
- package/node_modules/@dcode/shared/dist/protocol.d.ts +41 -4
- package/node_modules/@dcode/shared/dist/protocol.js +1 -1
- package/node_modules/@dcode/shared/dist/provider-provisioning.d.ts +26 -2
- package/node_modules/@dcode/shared/dist/provider-provisioning.js +19 -3
- package/node_modules/@dcode/shared/dist/providers.d.ts +1 -2
- package/node_modules/@dcode/shared/dist/providers.js +1 -1
- package/node_modules/@dcode/shared/dist/remote-workspace-identity.d.ts +6 -1
- package/node_modules/@dcode/shared/dist/remote-workspace-identity.js +35 -1
- package/node_modules/@dcode/shared/dist/remoteAppConfig.js +1 -1
- package/node_modules/@dcode/shared/dist/remoteEnvironmentKey.js +19 -0
- package/node_modules/@dcode/shared/dist/remoteTarget.d.ts +14 -1
- package/node_modules/@dcode/shared/dist/remoteTarget.js +4 -0
- package/node_modules/@dcode/shared/dist/remoteUsageTelemetry.d.ts +27 -0
- package/node_modules/@dcode/shared/dist/remoteUsageTelemetry.js +43 -0
- package/node_modules/@dcode/shared/dist/rendererActionTrace.d.ts +35 -35
- package/node_modules/@dcode/shared/dist/request-security-edition/index.d.ts +3 -0
- package/node_modules/@dcode/shared/dist/request-security-edition/index.js +3 -0
- package/node_modules/@dcode/shared/dist/request-security-edition/policy.d.ts +3 -0
- package/node_modules/@dcode/shared/dist/request-security-edition/policy.js +5 -0
- package/node_modules/@dcode/shared/dist/request-security-edition/verification-policy.d.ts +19 -0
- package/node_modules/@dcode/shared/dist/request-security-edition/verification-policy.js +29 -0
- package/node_modules/@dcode/shared/dist/rewardsBridge.d.ts +8 -0
- package/node_modules/@dcode/shared/dist/rewardsBridge.js +80 -0
- package/node_modules/@dcode/shared/dist/rewardsEmbedded.d.ts +37 -0
- package/node_modules/@dcode/shared/dist/rewardsEmbedded.js +50 -0
- package/node_modules/@dcode/shared/dist/sessionCreateTelemetry.d.ts +3 -3
- package/node_modules/@dcode/shared/dist/subagent-profile-frontmatter.d.ts +10 -0
- package/node_modules/@dcode/shared/dist/subagent-profile-frontmatter.js +212 -0
- package/node_modules/@dcode/shared/dist/subagent-profile-parser.d.ts +10 -0
- package/node_modules/@dcode/shared/dist/subagent-profile-parser.js +200 -0
- package/node_modules/@dcode/shared/dist/subagent-profile.d.ts +82 -0
- package/node_modules/@dcode/shared/dist/subagent-profile.js +28 -0
- package/node_modules/@dcode/shared/dist/subagent-runtime-config.d.ts +135 -0
- package/node_modules/@dcode/shared/dist/subagent-runtime-config.js +39 -0
- package/node_modules/@dcode/shared/dist/subagents-types.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/task-realtime-core.d.ts +57 -24
- package/node_modules/@dcode/shared/dist/task-realtime-core.js +8 -2
- package/node_modules/@dcode/shared/dist/test-ids-workflow.d.ts +4 -0
- package/node_modules/@dcode/shared/dist/test-ids-workflow.js +5 -0
- package/node_modules/@dcode/shared/dist/test-ids.d.ts +25 -0
- package/node_modules/@dcode/shared/dist/test-ids.js +25 -0
- package/node_modules/@dcode/shared/dist/tool-identity.d.ts +1 -1
- package/node_modules/@dcode/shared/dist/tool-identity.js +4 -0
- package/node_modules/@dcode/shared/dist/tool-plan-adapter.js +14 -1
- package/node_modules/@dcode/shared/dist/usage-stats.d.ts +13 -0
- package/node_modules/@dcode/shared/dist/validation.d.ts +1461 -85
- package/node_modules/@dcode/shared/dist/validation.js +423 -14
- package/node_modules/@dcode/shared/dist/validationAppSettings.d.ts +71 -15
- package/node_modules/@dcode/shared/dist/validationAppSettings.js +74 -12
- package/node_modules/@dcode/shared/dist/web-remote-control-heartbeat.d.ts +8 -0
- package/node_modules/@dcode/shared/dist/web-remote-control-heartbeat.js +40 -0
- package/node_modules/@dcode/shared/dist/web-remote-control-rpc-transport.d.ts +183 -0
- package/node_modules/@dcode/shared/dist/web-remote-control-rpc-transport.js +562 -0
- package/node_modules/@dcode/shared/dist/web-remote-control.d.ts +645 -0
- package/node_modules/@dcode/shared/dist/web-remote-control.js +174 -0
- package/node_modules/@dcode/shared/package.json +5 -2
- package/node_modules/@dcode/tui/dist/app-approval-panel.js +3 -2
- package/node_modules/@dcode/tui/dist/app-approval.d.ts +3 -1
- package/node_modules/@dcode/tui/dist/app-approval.js +9 -5
- package/node_modules/@dcode/tui/dist/app-compact-timeline.d.ts +3 -0
- package/node_modules/@dcode/tui/dist/app-compact-timeline.js +5 -2
- package/node_modules/@dcode/tui/dist/app-empty-transcript.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-empty-transcript.js +1 -1
- package/node_modules/@dcode/tui/dist/app-file-mentions.d.ts +2 -0
- package/node_modules/@dcode/tui/dist/app-file-mentions.js +2 -2
- package/node_modules/@dcode/tui/dist/app-input-pane.d.ts +38 -0
- package/node_modules/@dcode/tui/dist/app-input-pane.js +19 -19
- package/node_modules/@dcode/tui/dist/app-input-status.d.ts +17 -0
- package/node_modules/@dcode/tui/dist/app-input-status.js +4 -4
- package/node_modules/@dcode/tui/dist/app-input.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-input.js +1 -1
- package/node_modules/@dcode/tui/dist/app-markdown-theme.d.ts +2 -1
- package/node_modules/@dcode/tui/dist/app-markdown-theme.js +1 -1
- package/node_modules/@dcode/tui/dist/app-markdown.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-markdown.js +1 -1
- package/node_modules/@dcode/tui/dist/app-mode-command.d.ts +3 -0
- package/node_modules/@dcode/tui/dist/app-mode-command.js +4 -4
- package/node_modules/@dcode/tui/dist/app-mode-suggestion-panel.d.ts +5 -0
- package/node_modules/@dcode/tui/dist/app-mode-suggestion-panel.js +1 -1
- package/node_modules/@dcode/tui/dist/app-mode.d.ts +1 -1
- package/node_modules/@dcode/tui/dist/app-mode.js +1 -1
- package/node_modules/@dcode/tui/dist/app-model-ref.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-model-ref.js +1 -1
- package/node_modules/@dcode/tui/dist/app-motion.d.ts +13 -0
- package/node_modules/@dcode/tui/dist/app-motion.js +17 -7
- package/node_modules/@dcode/tui/dist/app-session-event-handler.d.ts +33 -0
- package/node_modules/@dcode/tui/dist/app-session-event-handler.js +4 -4
- package/node_modules/@dcode/tui/dist/app-shiki-diff-view.d.ts +18 -1
- package/node_modules/@dcode/tui/dist/app-shiki-diff-view.js +3 -3
- package/node_modules/@dcode/tui/dist/app-shiki-highlighter.d.ts +3 -0
- package/node_modules/@dcode/tui/dist/app-shiki-highlighter.js +7 -2
- package/node_modules/@dcode/tui/dist/app-sidebar-layout.d.ts +10 -0
- package/node_modules/@dcode/tui/dist/app-sidebar-layout.js +4 -4
- package/node_modules/@dcode/tui/dist/app-submit.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-submit.js +1 -1
- package/node_modules/@dcode/tui/dist/app-thought-components.d.ts +7 -0
- package/node_modules/@dcode/tui/dist/app-thought-components.js +2 -2
- package/node_modules/@dcode/tui/dist/app-tool-transcript.d.ts +1 -0
- package/node_modules/@dcode/tui/dist/app-tool-transcript.js +3 -0
- package/node_modules/@dcode/tui/dist/app-view.d.ts +27 -0
- package/node_modules/@dcode/tui/dist/app-view.js +1 -1
- package/node_modules/@dcode/tui/dist/app-workflow-card.js +1 -1
- package/node_modules/@dcode/tui/dist/app-workflow-seed.d.ts +18 -1
- package/node_modules/@dcode/tui/dist/app-workflow-seed.js +4 -4
- package/node_modules/@dcode/tui/dist/index.js +5118 -2579
- package/node_modules/@dcode/tui/dist/tui.d.ts +3 -0
- package/node_modules/@dcode/tui/dist/tui.js +1 -1
- package/node_modules/@dcode/tui/dist/types.d.ts +1 -1
- package/node_modules/oniguruma-parser/LICENSE +1 -1
- package/node_modules/oniguruma-parser/README.md +15 -61
- package/node_modules/oniguruma-parser/dist/oniguruma-parser.min.js +4 -4
- package/node_modules/oniguruma-parser/dist/parser/parse.js +1 -1
- package/node_modules/oniguruma-parser/dist/traverser/traverse.js +1 -1
- package/node_modules/oniguruma-parser/package.json +5 -5
- package/node_modules/oniguruma-to-es/dist/cjs/generate.d.ts +1 -1
- package/node_modules/oniguruma-to-es/dist/cjs/index.js +121 -120
- package/node_modules/oniguruma-to-es/dist/cjs/subclass.d.ts +2 -2
- package/node_modules/oniguruma-to-es/dist/cjs/transform.d.ts +3 -5
- package/node_modules/oniguruma-to-es/dist/cjs/unicode.d.ts +1 -1
- package/node_modules/oniguruma-to-es/dist/esm/generate.d.ts +1 -1
- package/node_modules/oniguruma-to-es/dist/esm/index.js +1 -3
- package/node_modules/oniguruma-to-es/dist/esm/subclass.d.ts +2 -2
- package/node_modules/oniguruma-to-es/dist/esm/transform.d.ts +3 -5
- package/node_modules/oniguruma-to-es/dist/esm/unicode.d.ts +1 -1
- package/node_modules/oniguruma-to-es/dist/index.min.js +6 -6
- package/node_modules/oniguruma-to-es/package.json +5 -5
- package/package.json +5 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dynamic-workflows
|
|
3
|
-
description: "Use when writing, debugging, or resubmitting a dynamic-workflow script for the CreateWorkflow tool: choosing subagent topology, typing subagent results, fanning out over files or git, gating loops on world.run commands, testing pieces with EvalWorkflowSnippet, planner-reviewer loops, confirming findings before reporting them, report() salvage, the report shape a run returns, publishing artifacts the user opens, and handling a backgrounded run."
|
|
3
|
+
description: "Use when writing, debugging, or resubmitting a dynamic-workflow script for the CreateWorkflow tool: choosing subagent topology, typing subagent results, fanning out over files or git, gating loops on world.run commands, testing pieces with EvalWorkflowSnippet, planner-reviewer loops, confirming findings before reporting them, report() salvage, the report shape a run returns, publishing artifacts the user opens, leaving typed holes to fill mid-run, and handling a backgrounded run."
|
|
4
4
|
when_to_use: "Only for CreateWorkflow scripts. A single delegation or a few independent lookups belong to the Agent tool instead."
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,8 +8,8 @@ when_to_use: "Only for CreateWorkflow scripts. A single delegation or a few inde
|
|
|
8
8
|
|
|
9
9
|
This skill is the whole authoring contract for `CreateWorkflow`. The tool descriptions are
|
|
10
10
|
short on purpose; the facade the compiler checks against, the rules a script must satisfy and
|
|
11
|
-
the fields each tool takes are in §16, and `CreateWorkflow`, `AmendWorkflow`, `
|
|
12
|
-
and `EvalWorkflowSnippet` refuse to run until this skill has been loaded
|
|
11
|
+
the fields each tool takes are in §16, and `CreateWorkflow`, `AmendWorkflow`, `FillWorkflowHole`,
|
|
12
|
+
`SaveWorkflow` and `EvalWorkflowSnippet` refuse to run until this skill has been loaded. The
|
|
13
13
|
rest is the judgment layer: how many subagents a request deserves, which of them should share
|
|
14
14
|
a context, what each one should hand back, and how to keep the run's work from dying with the
|
|
15
15
|
run.
|
|
@@ -28,11 +28,10 @@ on every plan and every draft (§3), an independent confirmation of every findin
|
|
|
28
28
|
deterministic checks wherever a command can decide, and a report that says what was
|
|
29
29
|
verified, what was not, and what it all means.
|
|
30
30
|
Depth is measured by what is at stake, not by how many subagents re-read the same work:
|
|
31
|
-
verification
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
when a wrong claim costs little or a command has already decided it.
|
|
31
|
+
verification goes where a wrong claim would cost the user something, and each piece of work
|
|
32
|
+
gets the one check that decides it. When a shortcut and the expert's way disagree, take the
|
|
33
|
+
expert's way; trim the work only when the task is small, and trim the checking when a wrong
|
|
34
|
+
claim costs little or a command has already decided it.
|
|
36
35
|
|
|
37
36
|
## 1. Is this the right tool, and how big should it be?
|
|
38
37
|
|
|
@@ -40,39 +39,37 @@ when a wrong claim costs little or a command has already decided it.
|
|
|
40
39
|
| --- | --- |
|
|
41
40
|
| One thing delegated to one agent | `Agent` |
|
|
42
41
|
| A few independent lookups, nobody reading anybody's answer | `Agent`, in parallel |
|
|
43
|
-
| Anything else the user did not name a workflow for
|
|
42
|
+
| Anything else the user did not name a workflow for, however many steps it needs | `Agent`, or do it yourself |
|
|
44
43
|
| The user said "use a workflow" / "使用 workflow" / "用工作流" — any phrasing naming workflow as the means | `CreateWorkflow`, mandatory, even if `Agent` would have done or one reply could answer |
|
|
45
44
|
|
|
46
|
-
**Only an explicit request starts a workflow.**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
**Only an explicit request starts a workflow.** A workflow begins with `/workflow` or with
|
|
46
|
+
the user naming workflow/工作流 as the means, never with your own judgement that a task
|
|
47
|
+
looks orchestration-shaped. Results feeding later steps, a bounded loop, a branch on a typed
|
|
48
|
+
result — those are shapes the script is good at once one has been requested, not reasons
|
|
49
|
+
there should be one. Delegate with `Agent` or do the work yourself.
|
|
51
50
|
|
|
52
|
-
**An explicit request is binding.**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
should be, and the smallest task still gets a small workflow rather than something else.
|
|
56
|
-
|
|
57
|
-
Once a workflow has been requested, these are the shapes it is good at, and what the script
|
|
58
|
-
should reach for: results feeding later steps (pipelines, fan-out then fan-in), a loop with a
|
|
59
|
-
stopping condition, and control flow branching on a typed result. They describe how to build
|
|
60
|
-
the workflow the user asked for — they never decide that there should be one.
|
|
51
|
+
**An explicit request is binding.** Once the user names workflow/工作流 as the means, the
|
|
52
|
+
routing question is closed — not `Agent`, not inline, not "too small for a workflow"; what
|
|
53
|
+
remains is only how big the script should be, and the smallest task gets a small workflow.
|
|
61
54
|
|
|
62
55
|
An explicit workflow request is a request for depth, and the bar above is the measure.
|
|
63
56
|
Default to the thorough shape — a fresh subagent per unit of work, a deterministic gate
|
|
64
57
|
wherever a command can decide, an independent confirmation of every finding the user will
|
|
65
|
-
act on as fact (§10) —
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
act on as fact (§10) — sized to the stakes: a bug the user will fix on your word gets a
|
|
59
|
+
confirmer; a poem or a survey gets a reader at most. Every task is a full model session, so
|
|
60
|
+
put sessions where they raise confidence, not where they repeat each other: "review the
|
|
61
|
+
changed files" wants a reviewer per file plus a confirmer per finding; "write me twenty
|
|
62
|
+
poems" wants twenty poets and no confirmers.
|
|
63
|
+
|
|
64
|
+
**Write only as much of that shape as you know for sure.** Where a later stage depends on
|
|
65
|
+
what an earlier one finds, write up to that point, end in a hole (§15), and let the findings
|
|
66
|
+
write the rest. Guessing a topology is not depth.
|
|
71
67
|
|
|
72
68
|
## 2. Subagent topology
|
|
73
69
|
|
|
74
|
-
This is the decision that separates a good script from a bad one
|
|
75
|
-
|
|
70
|
+
This is the decision that separates a good script from a bad one. It is made twice: now,
|
|
71
|
+
for what the request already tells you, and at a hole (§15), for what only the run can tell
|
|
72
|
+
you. This section is about the first, in four parts.
|
|
76
73
|
|
|
77
74
|
**Fresh subagent per item, or one shared subagent?** Every `agent()` call creates a new context.
|
|
78
75
|
Sharing a context means sharing the *variable*:
|
|
@@ -87,36 +84,33 @@ const judge = agent("judge", "You rank consistently across a whole batch.");
|
|
|
87
84
|
items.map((i) => judge.ask<Verdict>(`Judge ${i.id}`));
|
|
88
85
|
```
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
edit any file", a judge of a string is handed the string and told to judge it as given. A
|
|
118
|
-
subagent asked to run a check runs it; one told not to edit does not. None of this can
|
|
119
|
-
change after `agent()` — there is no per-task override.
|
|
87
|
+
Independent is right for unrelated items; shared is right when the answers must be
|
|
88
|
+
consistent with each other, at the price of serialization. Hoisting the `agent()` call out
|
|
89
|
+
of a loop for tidiness turns a fan-out into a queue, and nothing rejects that script.
|
|
90
|
+
|
|
91
|
+
**A name is an identity, and it has to be unique.** No two subagents in one run may share a
|
|
92
|
+
non-empty name — a duplicate fails the run. One fixed name inside a fan-out is a duplicate
|
|
93
|
+
per item, so write `` agent(`judge-${i.id}`) ``; the compiler catches the literal form, a
|
|
94
|
+
name built at run time costs you the run. Anonymous is always safe.
|
|
95
|
+
|
|
96
|
+
Names are worth giving anyway: a **revised** re-run finds its cache by them (§13),
|
|
97
|
+
importing every ask whose instructions did not change at zero tokens. Anonymous subagents
|
|
98
|
+
start empty.
|
|
99
|
+
|
|
100
|
+
**Persona, frozen at creation.** A persona stacks on the harness's own subagent contract —
|
|
101
|
+
citing `path:line`, never reporting a check it did not run, saying what it could not do,
|
|
102
|
+
escalating instead of faking — so write the role and the standard of judgement and leave
|
|
103
|
+
those rules out. Every subagent has the same tools; what it may do with them is said in the
|
|
104
|
+
ask: a reviewer that must not touch the code is told "do not edit any file".
|
|
105
|
+
|
|
106
|
+
**Per-subagent model**, only when asked or a light tier is obvious (judges, routers):
|
|
107
|
+
`agent("judge", { model: "Raven Flash" })`, ids from `ListModels`. A literal or a `model()`
|
|
108
|
+
ModelRef; to route, map the router's typed key to a `model()` table (`patterns.md` #13).
|
|
109
|
+
|
|
110
|
+
**Where each item goes next.** A run with more than one stage is a pipeline: an item leaves
|
|
111
|
+
its stage as soon as it is done, and the next stage takes it while the rest are still being
|
|
112
|
+
worked on. Decide this at every hand-off when you lay out the topology, and let a stage wait
|
|
113
|
+
for all of its items only where the next step needs every one. §7 says how to write each case.
|
|
120
114
|
|
|
121
115
|
**Loops.** Bound every loop with a round cap, and carry the feedback forward:
|
|
122
116
|
|
|
@@ -130,14 +124,12 @@ for (let round = 0; round < 5; round++) {
|
|
|
130
124
|
}
|
|
131
125
|
```
|
|
132
126
|
|
|
133
|
-
Reuse the same two subagents across rounds
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
reuse costs you is freshness: by round three the reviewer is anchored on its own earlier
|
|
137
|
-
critique. Keep the persistent reviewer for continuity and add an independent one at the end (§3).
|
|
127
|
+
Reuse the same two subagents across rounds: a subagent asked again keeps its context, so
|
|
128
|
+
round five is cheap. Reuse costs freshness — by round three the reviewer is anchored on its
|
|
129
|
+
own critique — so add an independent one at the end (§3).
|
|
138
130
|
|
|
139
|
-
**No nesting.** Subagents cannot call `CreateWorkflow
|
|
140
|
-
|
|
131
|
+
**No nesting.** Subagents cannot call `CreateWorkflow`; model a big sub-task as more subagents
|
|
132
|
+
here.
|
|
141
133
|
|
|
142
134
|
## 3. Fresh eyes
|
|
143
135
|
|
|
@@ -156,29 +148,23 @@ Four rules make the eyes actually fresh:
|
|
|
156
148
|
- **Ask for failures, not approval.** "Is this good?" gets a yes. "What would break this?
|
|
157
149
|
What is missing? Restate the plan in your own words" gets findings. Write the ask so
|
|
158
150
|
that approving takes evidence and objecting is the easy move.
|
|
159
|
-
- **Give the eyes the same evidence.** A reviewer
|
|
160
|
-
|
|
161
|
-
|
|
151
|
+
- **Give the eyes the same evidence.** A reviewer judging a plan about code from its text
|
|
152
|
+
alone can only judge coherence: tell plan reviewers to read the files the plan touches,
|
|
153
|
+
and not to edit them.
|
|
162
154
|
- **Give a prose deliverable an independent read.** When the deliverable is text nothing else
|
|
163
|
-
checked — a guide, an analysis
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
re-reading work two have already read. Two mechanisms on one deliverable is the ceiling, and
|
|
177
|
-
it needs a reason you can say. And the rules above are about the subagents *inside* the
|
|
178
|
-
script, not a gate on submitting it: reading your own script once against the request is
|
|
179
|
-
normally enough, and the run confirmation already puts the plan in front of the user. An
|
|
180
|
-
independent read of the script by a fresh `Agent` is an option for a genuinely hard one — many
|
|
181
|
-
phases, subtle gates — not a routine step.
|
|
155
|
+
checked — a guide, an analysis — hand it, before the script returns, to a reader-proxy
|
|
156
|
+
subagent asked what is unclear, what the text fails to support, and what the user will ask
|
|
157
|
+
next; then fix those. Say it judges from the text alone — checking claims is a confirmer's
|
|
158
|
+
job. A report whose
|
|
159
|
+
findings were each confirmed (§10) has had its eyes; add no reader on top.
|
|
160
|
+
|
|
161
|
+
Three cautions. Correlated reviewers add little — same model, same prompt, same blind spots
|
|
162
|
+
— so give each a distinct lens. Bound it: one deliverable gets one mechanism — a plan a
|
|
163
|
+
reviewer who reads the code, findings a confirmer, prose a reader; two is the ceiling, with
|
|
164
|
+
a reason you can say. And these rules are about the subagents *inside* the script, not a gate
|
|
165
|
+
on submitting it: read your own script once against the request, and at every `Promise.all`
|
|
166
|
+
ask whether the next step needs every item; where it does not, pipeline it (§7). The
|
|
167
|
+
confirmation window then puts the plan in front of the user.
|
|
182
168
|
|
|
183
169
|
## 4. Typed results
|
|
184
170
|
|
|
@@ -200,24 +186,20 @@ interface Finding {
|
|
|
200
186
|
}
|
|
201
187
|
```
|
|
202
188
|
|
|
203
|
-
Without the comments you get whatever the subagent guessed `severity` meant.
|
|
204
|
-
a calibrated field, for the price of three lines.
|
|
189
|
+
Without the comments you get whatever the subagent guessed `severity` meant.
|
|
205
190
|
|
|
206
|
-
Keep results narrow
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
spends tokens to tell it something it could have fetched itself.
|
|
191
|
+
Keep results narrow: a result crosses a schema boundary and gets interpolated into the next
|
|
192
|
+
prompt, so a wide one costs tokens twice. **Pass paths, not file contents** — a subagent has
|
|
193
|
+
its own file tools; a stringified 4000-line file spends tokens on what it could have read.
|
|
210
194
|
|
|
211
195
|
## 5. Getting the world in
|
|
212
196
|
|
|
213
|
-
`files.glob` and `git.changedFiles` are how a script learns what to fan out over
|
|
214
|
-
executed by the harness, recorded, and replayed
|
|
197
|
+
`files.glob` and `git.changedFiles` are how a script learns what to fan out over; both are
|
|
198
|
+
executed by the harness, recorded, and replayed on resume.
|
|
215
199
|
|
|
216
|
-
Caps **reject rather than truncate
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
— which is exactly what you need for `git`, since every `git` call rejects outside a
|
|
220
|
-
repository:
|
|
200
|
+
Caps **reject rather than truncate** (§16.2), so narrow the pattern instead of fanning out
|
|
201
|
+
over a silently partial view. Reads are catchable, so a coarser fallback is a `catch` —
|
|
202
|
+
which `git` needs, since every `git` call rejects outside a repository:
|
|
221
203
|
|
|
222
204
|
```ts
|
|
223
205
|
let paths: string[];
|
|
@@ -229,7 +211,7 @@ try {
|
|
|
229
211
|
```
|
|
230
212
|
|
|
231
213
|
Reach for `files.read` or `files.grep` only when the *script itself* must shard or branch on
|
|
232
|
-
content
|
|
214
|
+
content; reading files is subagent work.
|
|
233
215
|
|
|
234
216
|
**`world.run` is the deterministic gate.** When a check is fixed and machine-checkable — the
|
|
235
217
|
build passes, the proof checks, the tests are green — run it as code and branch on the exit
|
|
@@ -240,28 +222,23 @@ const check = await world.run("lake", ["build"], { timeoutMs: 1_800_000 });
|
|
|
240
222
|
if (check.exitCode !== 0) feedback = check.stderr;
|
|
241
223
|
```
|
|
242
224
|
|
|
243
|
-
A nonzero exit code is a **value**, not an exception:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
subagent with tools; `world.run` is for checks whose outcome your control flow branches on.
|
|
225
|
+
A nonzero exit code is a **value**, not an exception: read `exitCode` and carry `stderr`
|
|
226
|
+
forward as the next round's feedback, with no `catch`; rejections are for the world failing
|
|
227
|
+
to answer (spawn failure, timeout, output over the cap). The command name must be a
|
|
228
|
+
compile-time string literal, because the user approves the script's command set at
|
|
229
|
+
confirmation: interpolate paths, flags and round numbers into the **args array**, never into
|
|
230
|
+
the command. Open-ended editing belongs to a subagent; `world.run` is for checks your
|
|
231
|
+
control flow branches on.
|
|
251
232
|
|
|
252
233
|
**Choose the gate before you write it.** A gate decides exactly as much as the check it
|
|
253
|
-
runs
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
least once before the final `return` — even when the fast tier already said yes, because
|
|
262
|
-
the fast tier cannot see what it does not test. When the strong tier is slow, give it the
|
|
263
|
-
`timeoutMs` it needs; a faster substitute is a different check, not a cheaper version of
|
|
264
|
-
the same one.
|
|
234
|
+
runs. Before the first `world.run`, find out what checks the repository has — `package.json`
|
|
235
|
+
scripts, `Makefile` targets, the CI config, the README's "run this to verify" line — and
|
|
236
|
+
rank them by how much they decide: a unit suite decides less than an end-to-end suite, which decides less than
|
|
237
|
+
the acceptance command the README names, and none decides a performance request the way
|
|
238
|
+
the bench does. Then build the gate in two tiers: the fast tier may drive a loop's rounds;
|
|
239
|
+
the **strongest** tier the request implies decides the exit and runs for real at least once
|
|
240
|
+
before the final `return`, even when the fast tier said yes. Give a slow tier the
|
|
241
|
+
`timeoutMs` it needs; a faster substitute is a different check.
|
|
265
242
|
|
|
266
243
|
```ts
|
|
267
244
|
phase("Fix until the unit tests pass");
|
|
@@ -282,28 +259,26 @@ unverified work (§10).
|
|
|
282
259
|
## 6. Test the pieces before you commit
|
|
283
260
|
|
|
284
261
|
A workflow script is final at submit. The fixed logic inside it does not have to be: run it
|
|
285
|
-
through the `EvalWorkflowSnippet` tool first,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
result into a container and fishing it out later, or routing it through a clever indirection,
|
|
306
|
-
earns an analyzability diagnostic instead.
|
|
262
|
+
through the `EvalWorkflowSnippet` tool first (§16.6), synchronously and without persisting
|
|
263
|
+
anything. What passed there pastes into the workflow verbatim. Send the snippet
|
|
264
|
+
as `code`, or as `path` to a file holding it — the second try then costs an `Edit`.
|
|
265
|
+
|
|
266
|
+
Snippet work is the non-subagent part: what a glob really returns, whether a grep pattern
|
|
267
|
+
overruns its cap, how `world.run("lean", ...)`'s stderr parses, whether a gate predicate does
|
|
268
|
+
what you meant. A snippet has `files.*`, `git.*`, `world.run` and `log`, but no `agent()`.
|
|
269
|
+
Once you know which check decides the result (§5), run it once here too: that shows its
|
|
270
|
+
output, whether it exits nonzero as you assumed, and how long it takes — the `timeoutMs` you
|
|
271
|
+
write, not a guess.
|
|
272
|
+
|
|
273
|
+
## 7. Pipeline by default; join only where the next step needs every item
|
|
274
|
+
|
|
275
|
+
A workflow with more than one stage should run like a pipeline: every stage works at the
|
|
276
|
+
same time, and each item moves on the moment it is ready. A reviewed file goes to its
|
|
277
|
+
confirmer while the other files are still being reviewed; a fact goes to its checker while
|
|
278
|
+
the researchers are still reading. Write it this way wherever the next step can take items
|
|
279
|
+
one at a time, which is nearly every hand-off. Let a stage wait for all of its items only
|
|
280
|
+
where the next step needs every one: a deduplication across files, a ranking on one scale, a
|
|
281
|
+
synthesis. Those are the barriers, and a script has few of them.
|
|
307
282
|
|
|
308
283
|
`Promise.all` is a join, and a join is a barrier: nothing after it starts until the slowest
|
|
309
284
|
item before it has landed. Parallelism comes from *not awaiting yet*:
|
|
@@ -318,20 +293,21 @@ const all = await Promise.all(
|
|
|
318
293
|
for (const p of paths) results.push(await agent(`reviewer-${p}`).ask<Review>(`Review ${p}`));
|
|
319
294
|
```
|
|
320
295
|
|
|
321
|
-
**
|
|
322
|
-
one — a reviewer per file and a confirmer per finding, a migrator per file and a checker per
|
|
323
|
-
file — a barrier between them makes every confirmer wait for the slowest reviewer while the
|
|
324
|
-
concurrency slots sit idle. Chain the stages per item inside the fan-out instead, and join
|
|
325
|
-
once at the end:
|
|
296
|
+
**Decide, at every hand-off, how an item leaves its stage:**
|
|
326
297
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
);
|
|
298
|
+
| The next step takes | The stages | Write |
|
|
299
|
+
| --- | --- | --- |
|
|
300
|
+
| one item at a time | one to one: a reviewer per file, a confirmer per finding, a migrator per file and a checker per file | the stages chained per item inside one fan-out, one join at the end |
|
|
301
|
+
| one item at a time | a pool of shared workers serves a stage; items are still being found while the next stage works; a later stage sends work back; the stages read better as separate blocks | a `channel` between the stages, a `future` per stage |
|
|
302
|
+
| every item at once | deduplication, a ranking on one scale, a synthesis, the final report | a join, with a comment saying what needs every item |
|
|
333
303
|
|
|
334
|
-
|
|
304
|
+
**Chaining.** When two stages map one to one, a barrier between them makes every worker of
|
|
305
|
+
the second stage wait for the slowest worker of the first while the run's concurrency slots
|
|
306
|
+
sit idle. Chain the stages per item inside the fan-out instead, and join once at the end:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
// One join: each file's findings go to their confirmers the moment its review lands
|
|
310
|
+
// (two Promise.all — review every file, then confirm every finding — is the barrier).
|
|
335
311
|
const confirmed = (
|
|
336
312
|
await Promise.all(
|
|
337
313
|
paths.map(async (p) => {
|
|
@@ -344,22 +320,88 @@ const confirmed = (
|
|
|
344
320
|
).flat();
|
|
345
321
|
```
|
|
346
322
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
calibrated subagent is not one of them: asks on it queue FIFO, so feeding it per item as
|
|
350
|
-
results land keeps it consistent *and* keeps the pipeline moving (§11).
|
|
323
|
+
A shared, calibrated subagent is not a barrier: asks on it queue first in, first out, so feed
|
|
324
|
+
it each item as it lands and it stays consistent while the pipeline keeps moving (§11).
|
|
351
325
|
|
|
352
326
|
One rejection inside `Promise.all` rejects the whole join and the sibling results with it.
|
|
353
327
|
When one bad item should cost one item, catch inside the callback (examples #3) or use
|
|
354
328
|
`Promise.allSettled` and read each outcome.
|
|
355
329
|
|
|
330
|
+
**Channels.** Chaining covers stages that map one to one. It cannot write a stage served by a
|
|
331
|
+
pool of shared workers, a producer still finding items while consumers work, stages laid out
|
|
332
|
+
as separate blocks, or a feedback loop to an earlier stage. For those, a `channel<T>()`
|
|
333
|
+
carries items between two stages and each stage is a `future(async () => { … })`. An item
|
|
334
|
+
sent into the channel is taken by the next stage at once, by a worker that is waiting for it
|
|
335
|
+
or by a new one started for it:
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
const facts = channel<Fact>("facts");
|
|
339
|
+
const verified: Fact[] = [];
|
|
340
|
+
|
|
341
|
+
const research = future(async () => {
|
|
342
|
+
phase("Research the topic from each angle");
|
|
343
|
+
try {
|
|
344
|
+
await Promise.all(
|
|
345
|
+
angles.map(async (angle) => {
|
|
346
|
+
const found = await agent(`researcher-${angle}`).ask<Research>(`Research ${angle}.`);
|
|
347
|
+
for (const fact of found.facts) facts.send(fact);
|
|
348
|
+
}),
|
|
349
|
+
);
|
|
350
|
+
} finally {
|
|
351
|
+
facts.close(); // the producer side owns the close; a failed researcher still ends the stream
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const verify = future(async () => {
|
|
356
|
+
phase("Check each fact as it arrives");
|
|
357
|
+
await Promise.all(
|
|
358
|
+
[1, 2, 3].map(async (k) => {
|
|
359
|
+
const verifier = agent(`verifier-${k}`);
|
|
360
|
+
for await (const fact of facts) {
|
|
361
|
+
const verdict = await verifier.ask<Verdict>(`Does this hold? ${JSON.stringify(fact)}`);
|
|
362
|
+
if (verdict.holds) verified.push(fact);
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
await Promise.all([research, verify]); // start every stage, then join once
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The rules, in the order the code reads:
|
|
372
|
+
|
|
373
|
+
- **A stage is a future.** Its marker first, then the workers (a `Promise.all` over K
|
|
374
|
+
`for await` loops on the input channel), then the output's `close()` in a `finally`. Start
|
|
375
|
+
every stage, then join all of them once with `Promise.all`, with no `await` between: while
|
|
376
|
+
you await one stage, a failure in another has no listener and surfaces as an unhandled
|
|
377
|
+
rejection instead of failing the run with its error.
|
|
378
|
+
- **A channel where the next stage should start before the previous one ends; a join where it
|
|
379
|
+
needs every item.** Never a channel between two stages that need a barrier.
|
|
380
|
+
- **A new subagent per item inside a consumer is a `future` inside the `for await`**, pushed
|
|
381
|
+
into an array and joined before the stage ends (examples #6); without that join the stage
|
|
382
|
+
ends when the channel closes with checks still running, and nothing reports it.
|
|
383
|
+
- **A cycle is counted.** A feedback channel (a verifier sends a doubtful fact back for more
|
|
384
|
+
research) has no single producer who knows when it is done, so keep one count of open work
|
|
385
|
+
items: increment *before* finishing the item that produced the new work, close the feedback
|
|
386
|
+
channel when the count hits zero, bound the loop with a depth field on the item
|
|
387
|
+
(`patterns.md` #12).
|
|
388
|
+
- **Pools trade cache reuse for consistency.** A pool of shared workers (`verifier-1…3`
|
|
389
|
+
above) judges on one scale, but which item lands on which worker depends on timing, so an
|
|
390
|
+
amendment that changes one upstream item misses the cache for the whole pool; a fresh
|
|
391
|
+
`verifier-${fact.id}` per item misses only itself. `send` never waits (the buffer is
|
|
392
|
+
unbounded); a channel nobody can send to any more fails the run as `ChannelDeadlock`.
|
|
393
|
+
|
|
394
|
+
**Keep the data flow visible.** The harness recovers the dependency graph by reading your
|
|
395
|
+
code before it runs: plain variables, template interpolation, destructuring and small local
|
|
396
|
+
helpers are traced exactly; a result stashed in a container or behind an indirection earns a
|
|
397
|
+
diagnostic.
|
|
398
|
+
|
|
356
399
|
## 8. Group the run into named phases
|
|
357
400
|
|
|
358
|
-
Phases are required
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
are inferred from the same analysis:
|
|
401
|
+
Phases are required. The user experiences a workflow through its phase graph: the
|
|
402
|
+
confirmation dialog is drawn one node per phase, and thirty step cards is a dialog nobody
|
|
403
|
+
reads. Cover the whole script — every stage gets a `phase("...")` marker at its head; the
|
|
404
|
+
arrows between phases are inferred:
|
|
363
405
|
|
|
364
406
|
<!-- compile -->
|
|
365
407
|
```ts
|
|
@@ -403,57 +445,47 @@ const head = await world.run("git", ["rev-parse", "HEAD"]);
|
|
|
403
445
|
return { approach: winner, commit: head.stdout.trim() };
|
|
404
446
|
```
|
|
405
447
|
|
|
406
|
-
Five nodes
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
grows to thirty steps. That is the entire payoff: the user sees the story you had in your
|
|
410
|
-
head instead of a wall of cards.
|
|
448
|
+
Five nodes, with an arrow back from the bench to "Make one improvement" — and still five
|
|
449
|
+
when the real script grows to thirty steps: the user sees the story instead of a wall of
|
|
450
|
+
cards.
|
|
411
451
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
round survives the tests — not once at the start to print a baseline and never again. A
|
|
415
|
-
loop that gates on `cargo test` alone would crown the first round that compiles (§5).
|
|
452
|
+
The unit tests are the fast tier that drives the rounds; the bench is the check the request
|
|
453
|
+
was about, and it decides every round that survives them, not once at the start (§5).
|
|
416
454
|
|
|
417
455
|
**Write the names for the user, not for the graph.** A phase name is a short natural
|
|
418
456
|
phrase saying what this stage accomplishes for the user, written in the language the
|
|
419
457
|
user is speaking in this session — "Research each changed file in parallel",
|
|
420
|
-
"汇总并产出最终报告".
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
**Put the marker where the steps are.** A marker claims the rest of the block it sits
|
|
427
|
-
in, nested blocks and inlined helper calls included, so a marker inside an `if` covers
|
|
428
|
-
that branch and stops at its closing brace. Mark the block where the `ask` and
|
|
458
|
+
"汇总并产出最终报告" (§9). Names are compile-time string literals, so you cannot number
|
|
459
|
+
rounds by interpolation, and should not want to: two markers with the same name are one
|
|
460
|
+
node, so a loop body stays one box across its rounds.
|
|
461
|
+
|
|
462
|
+
**Put the marker where the steps are.** A marker claims the rest of the block it sits in,
|
|
463
|
+
nested blocks and inlined helper calls included, so mark the block where the `ask` and
|
|
429
464
|
`world.run` calls actually live.
|
|
430
465
|
|
|
431
|
-
**Not inside a concurrent fan-out callback.**
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
the
|
|
446
|
-
narrates: an `if` whose body is nothing but `report(...)` and `log(...)` does not get
|
|
447
|
-
its own marker.
|
|
466
|
+
**Not inside a concurrent fan-out callback.** Twenty `map(async …)` callbacks re-entering
|
|
467
|
+
`phase("Review")` out of order would count every re-entry as a round. A per-item pipeline
|
|
468
|
+
(§7) is one phase named for what it does to each item, with the markers at the top level
|
|
469
|
+
around it.
|
|
470
|
+
|
|
471
|
+
**One marker at the head of each stage's future.** Concurrent stages written as futures (§7)
|
|
472
|
+
each open their body with their own `phase("...")`. Stamping is lexical — a step gets the
|
|
473
|
+
phase the analyzer places it in, not the marker the engine passed last — so two stages
|
|
474
|
+
running at once keep their own steps; still no marker in the per-item callback or the
|
|
475
|
+
`for await` body.
|
|
476
|
+
|
|
477
|
+
**Every phase must contain at least one `ask` or one `world.run`.** Plain script logic —
|
|
478
|
+
reading `args`, shaping a prompt, building the `return` — shows no progress, so it is not a
|
|
479
|
+
stage: fold it into the phase before or after it, and open none for the setup at the top,
|
|
480
|
+
the `return` at the bottom, or a branch that only narrates with `report` and `log`.
|
|
448
481
|
|
|
449
482
|
## 9. Write for the user
|
|
450
483
|
|
|
451
484
|
Six things you write are read by the user, not by the script: phase names, subagent names,
|
|
452
485
|
`log` lines, artifact titles and the markdown you publish, the four report fields, and any
|
|
453
|
-
question a subagent escalates. Write each one
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
pipeline — is yours, not theirs, and so is the numbering.
|
|
486
|
+
question a subagent escalates. Write each one as you would tell a colleague across the desk
|
|
487
|
+
what is happening: what the work is, in the user's words and language. The machinery —
|
|
488
|
+
fan-out, gate, node, stage, pipeline — is yours, not theirs, and so is the numbering.
|
|
457
489
|
|
|
458
490
|
| Read by the user | Write | Not |
|
|
459
491
|
| --- | --- | --- |
|
|
@@ -468,19 +500,15 @@ pipeline — is yours, not theirs, and so is the numbering.
|
|
|
468
500
|
| Artifact title | Review report / 评审报告 | report-artifact-v1 / 产物输出 |
|
|
469
501
|
| Escalation question | Should the threshold be 94 rather than 96? / 阈值应该是 94 而不是 96 吗? | Requesting clarification regarding gate configuration parameters / 请求对门控配置参数进行澄清 |
|
|
470
502
|
|
|
471
|
-
The method names in this skill — fresh eyes, independent read — are
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
read are written by subagents answering the ask you wrote, so write those asks in the user's
|
|
477
|
-
language, or say in the ask which language to answer in. Otherwise a Chinese report arrives
|
|
478
|
-
wrapping English findings.
|
|
503
|
+
The method names in this skill — fresh eyes, independent read — are idioms for you, not
|
|
504
|
+
words for the user: in Chinese that is 独立复核 or 换人复审, never 冷读 or 冷眼.
|
|
505
|
+
The language travels through your asks: findings and summaries are written by subagents
|
|
506
|
+
answering the ask you wrote, so write asks in the user's language, or say which language to
|
|
507
|
+
answer in; otherwise a Chinese report arrives wrapping English findings.
|
|
479
508
|
|
|
480
509
|
## 10. Verify, report, deliver
|
|
481
510
|
|
|
482
|
-
`log(...)` is narration for the human watching the run
|
|
483
|
-
would otherwise wonder whether anything is happening — after a fan-out is sized, at the top
|
|
511
|
+
`log(...)` is narration for the human watching the run: after a fan-out is sized, at the top
|
|
484
512
|
of each loop round.
|
|
485
513
|
|
|
486
514
|
**Verify before you report, in proportion to what a wrong claim costs.** Verification
|
|
@@ -489,40 +517,32 @@ is real: a bug they will fix, a security claim, a number they will quote, a fact
|
|
|
489
517
|
rests on. Each finding of that kind is confirmed independently before it reaches the user: a
|
|
490
518
|
second subagent that reproduces the finding from its evidence alone — reading the code,
|
|
491
519
|
running a check when one decides it, never editing — or a `world.run` command when one can
|
|
492
|
-
decide. The reviewer that found
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
520
|
+
decide. The reviewer that found it does not confirm it. A finding that fails confirmation
|
|
521
|
+
is **kept and labelled** `unconfirmed`, never silently dropped — a real issue the confirmer
|
|
522
|
+
could not reproduce is still worth a human's eyes, and the label tells the user "seen" from
|
|
523
|
+
"suspected".
|
|
496
524
|
|
|
497
525
|
Three things that look like verification and are waste. A confirmer on a finding a
|
|
498
|
-
`world.run` already decided: the exit code is the confirmation
|
|
499
|
-
`verified
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
script runs the full suite after you; do not run it yourself") so the subagents spend their
|
|
504
|
-
turns on what only they can do.
|
|
526
|
+
`world.run` already decided: the exit code is the confirmation; record the command in
|
|
527
|
+
`verified`. A confirmer on work nobody will act on as fact — poems, brainstormed options, a
|
|
528
|
+
first-draft survey — which gets at most one independent read (§3). A suite run three times
|
|
529
|
+
because the hunter, the confirmer and the gate each ran it: a gate runs once, by the script,
|
|
530
|
+
and the asks say so ("the script runs the full suite after you; do not run it yourself").
|
|
505
531
|
|
|
506
532
|
**Gate at the task's scale.** `verified` names the commands that actually decided the
|
|
507
|
-
result, and the reader
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
**
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
after its confirmation, with its status — rather than accumulating an array and returning it
|
|
521
|
-
at the end: the array is what you lose. Items are recorded, so a resumed run never shows the
|
|
522
|
-
same one twice.
|
|
523
|
-
|
|
524
|
-
Give open-ended work an explicit round cap in the script rather than an unbounded loop: the
|
|
525
|
-
harness enforces no node limit, so a loop that never goes dry only ends when the user cancels.
|
|
533
|
+
result, and the reader holds them against what they asked for. A unit suite in `verified`
|
|
534
|
+
and the end-to-end suite in `notCovered` is an unverified deliverable with a disclosure
|
|
535
|
+
attached. `notCovered` is for what *could not* be checked — no test exists, the environment
|
|
536
|
+
lacks the tool, the check needs something only the user has — never for a check that exists
|
|
537
|
+
and was skipped because it is slow. If the strongest check the request implies exists and
|
|
538
|
+
did not run, the run is not done: run it, or say in `conclusion` that the work is unverified
|
|
539
|
+
and why (§5).
|
|
540
|
+
|
|
541
|
+
**Salvage by report.** `report(...)` is not `log`: reported items are delivered with the
|
|
542
|
+
completion notification **even when the run fails**, which is how a run that dies on its
|
|
543
|
+
twelfth task keeps eleven tasks' worth of work. Report each finding the moment it lands —
|
|
544
|
+
after its confirmation, with its status — rather than accumulating an array to return at the
|
|
545
|
+
end: the array is what you lose. Items are recorded, so a resumed run never shows one twice.
|
|
526
546
|
|
|
527
547
|
**Deliver a report.** The script's final `return` is the handoff the main agent presents,
|
|
528
548
|
in the order below; what the user themselves keep is the artifact of the next section.
|
|
@@ -561,9 +581,6 @@ const result: WorkflowReport = {
|
|
|
561
581
|
return result;
|
|
562
582
|
```
|
|
563
583
|
|
|
564
|
-
Before returning it, give it an independent read (§3): a reader-proxy subagent that has seen nothing else
|
|
565
|
-
tells you what is unclear, unsupported, or missing, while there is still time to fix it.
|
|
566
|
-
|
|
567
584
|
Each field has a reader. `conclusion` is the answer to what the user asked. `findings` carry
|
|
568
585
|
their evidence and their status, so the user can tell what was seen from what was suspected.
|
|
569
586
|
`verified` says what this run actually checked and how — the commands it ran, the files it
|
|
@@ -575,44 +592,31 @@ speaking in this session.
|
|
|
575
592
|
is the other channel: things the *user* opens, shown as cards beside the run while it is
|
|
576
593
|
still going and kept after it ends. Two habits:
|
|
577
594
|
|
|
578
|
-
- **Every run publishes its deliverable.**
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
**Show what matters.** More artifacts is not more delivery: every card competes with the
|
|
605
|
-
deliverable for the user's attention. Two tests decide what earns a card. Would the user open
|
|
606
|
-
it on its own? If not, it is a section of the deliverable. Does it repeat another artifact? A
|
|
607
|
-
CSV and a table of the same rows, a report and a copy of it, a chart and a metrics tile of the
|
|
608
|
-
same number — one of each pair is noise. The common run publishes one deliverable, one
|
|
609
|
-
dashboard when there is something to watch, and further files only when a subagent produced
|
|
610
|
-
something else a person opens.
|
|
611
|
-
|
|
612
|
-
Ids and the report tag are compile-time string literals. What a run can publish is therefore
|
|
613
|
-
fixed at the moment the user approves the script, and an id assembled at runtime is a compile
|
|
614
|
-
diagnostic rather than a surprise. Publishing an id a second time mints the next version and
|
|
615
|
-
keeps the old one, so a file worth republishing each round costs you nothing to name once.
|
|
595
|
+
- **Every run publishes its deliverable.** When the user asked for a thing — a webpage, a PDF
|
|
596
|
+
— a subagent writes it into the workspace and returns the path ("write it to `out/…` and
|
|
597
|
+
return the path" belongs in the ask), and the script publishes it with `artifact.file`;
|
|
598
|
+
until it does, nothing the run left in the workspace exists for the user. When the user
|
|
599
|
+
asked for an answer — findings, a review — the `return` is the compact handoff and the
|
|
600
|
+
deliverable is the long form of the same facts: markdown built from the values the return
|
|
601
|
+
is built from, published once, at the end. The exception is a run whose whole answer is a
|
|
602
|
+
line. With more than one artifact, mark the deliverable `{ primary: true }`: the completion
|
|
603
|
+
card, the run pane and the notification lead with it. One primary per run.
|
|
604
|
+
- **A dashboard is for the person watching the run.** Declare one when the run has state worth
|
|
605
|
+
watching while it runs — the key number after each round, which items are done or failed:
|
|
606
|
+
metrics or a chart for a number, a table or board for items with a status. Declare it once
|
|
607
|
+
at the top, then tag the items you already report: `report(item, "perf")`. It is a
|
|
608
|
+
projection of that stream, so it grows live and survives a resume. A run that is over
|
|
609
|
+
before anyone would look needs none.
|
|
610
|
+
|
|
611
|
+
**Show what matters.** Two tests decide what earns a card: would the user open it on its
|
|
612
|
+
own (else it is a section of the deliverable), and does it repeat another artifact (a CSV and
|
|
613
|
+
a table of its rows, a report and a copy of it — one of each pair is noise). The common run
|
|
614
|
+
publishes one deliverable, one dashboard when there is something to watch, and further files
|
|
615
|
+
only when a subagent produced something else a person opens.
|
|
616
|
+
|
|
617
|
+
Ids and the report tag are compile-time string literals: what a run can publish is fixed
|
|
618
|
+
when the user approves the script, and an id assembled at runtime is a compile diagnostic.
|
|
619
|
+
Publishing an id a second time mints the next version and keeps the old one.
|
|
616
620
|
|
|
617
621
|
**A rejected publish is a repair opportunity, not an error to swallow.** Content publishes
|
|
618
622
|
reject catchably — the file is missing, the path escaped the workspace, the bytes are over the
|
|
@@ -685,77 +689,73 @@ return {
|
|
|
685
689
|
```
|
|
686
690
|
|
|
687
691
|
One `report` call feeds both surfaces: the tagged item lands on the chart *and* in the run's
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
chart's points, so a card for it would say nothing new.
|
|
692
|
+
results. Three cards, none repeating another: the chart is what the user watched, the profile
|
|
693
|
+
is what a person opens, the report is what they keep; the CSV the bench wrote stays in the
|
|
694
|
+
workspace, since its rows are the chart's points.
|
|
692
695
|
|
|
693
696
|
## 11. A complete example
|
|
694
697
|
|
|
695
698
|
The complete review workflow that used to sit here — a reviewer per changed file, triage
|
|
696
699
|
through one shared subagent that is fed as reviews land, a confirmer per kept finding chained
|
|
697
700
|
inside the same callback, one join for the cross-file deduplication — is
|
|
698
|
-
`${DCODE_SKILL_DIR}/examples.md` §5
|
|
699
|
-
and
|
|
701
|
+
`${DCODE_SKILL_DIR}/examples.md` §5; §7 and §10 carry its rules. The open-ended form — a
|
|
702
|
+
seed that surveys and ends in a tail hole, grown fill by fill — is `examples.md` #7 (§15).
|
|
700
703
|
|
|
701
704
|
## 12. Anti-patterns
|
|
702
705
|
|
|
703
706
|
| What you wrote | What it costs you |
|
|
704
707
|
| --- | --- |
|
|
705
|
-
|
|
|
706
|
-
|
|
|
707
|
-
| A fresh subagent each loop round | Round five re-learns
|
|
708
|
-
|
|
|
709
|
-
|
|
|
710
|
-
| A
|
|
711
|
-
|
|
|
712
|
-
|
|
|
713
|
-
|
|
|
714
|
-
|
|
|
715
|
-
|
|
|
716
|
-
|
|
|
717
|
-
|
|
|
718
|
-
|
|
|
719
|
-
|
|
|
720
|
-
|
|
|
721
|
-
|
|
|
722
|
-
|
|
|
723
|
-
|
|
|
724
|
-
|
|
|
725
|
-
|
|
|
726
|
-
|
|
|
727
|
-
|
|
|
728
|
-
|
|
|
729
|
-
|
|
|
730
|
-
|
|
|
731
|
-
|
|
|
732
|
-
|
|
|
733
|
-
|
|
|
734
|
-
|
|
|
708
|
+
| One subagent hoisted out of a fan-out for tidiness | The fan-out became a FIFO queue (§2) |
|
|
709
|
+
| One fixed name for every subagent in a fan-out | A literal duplicate fails compile, a computed one kills the run; name per item or stay anonymous (§2) |
|
|
710
|
+
| A fresh subagent each loop round | Round five re-learns what round four knew, at full price (§2) |
|
|
711
|
+
| An unbounded `while` | The run dies on a cap instead of finishing (§2) |
|
|
712
|
+
| Findings accumulated in an array, returned at the end | A failure on the last task loses them all; `report` as you go (§10) |
|
|
713
|
+
| A whole file interpolated into a prompt | Tokens spent on what the subagent's own tools read; pass the path (§4) |
|
|
714
|
+
| A wide `files.grep` with no glob | The call rejects; there is no partial result (§5) |
|
|
715
|
+
| A subagent asked to run the tests and say if they passed | A session paid for what `world.run` decides as code, and a claim it can fake (§5) |
|
|
716
|
+
| A `world.run` command name built at run time | Compile fails: the command is a literal; runtime values go in the args array (§5) |
|
|
717
|
+
| The gate written from habit, or only the unit tests gated | The project named a stronger check; survey its checks, and run the strongest one before `return` (§5) |
|
|
718
|
+
| A workflow submitted to see whether a parse function works | A full run for what `EvalWorkflowSnippet` answers now (§6) |
|
|
719
|
+
| An unguarded `.find()` / `.match()` result or optional property | Compile fails under `strict`; plain `items[i]` needs no guard (§16.3) |
|
|
720
|
+
| `Date.now()` / `Math.random()` / `fetch` / `fs` | Compile fails: a replayable run cannot contain them |
|
|
721
|
+
| An `await` per item in a loop with no ordering need | Serial wall-clock for concurrent work (§7) |
|
|
722
|
+
| A stage that waits for the whole previous stage though it handles items one at a time | Every worker of the second stage waits for the slowest of the first while slots idle; chain per item, or use a channel (§7) |
|
|
723
|
+
| A join with no comment saying what needs every item | On the next revision nobody can tell the barrier from a habit; say why, or pipeline it (§7) |
|
|
724
|
+
| A channel nobody closes | `ChannelDeadlock`; the producing stage closes it in a `finally` (§7) |
|
|
725
|
+
| An `await` between starting the stage futures and joining them | A stage failing while you await another has no listener: an unhandled rejection, not a failed run; start all, then join once (§7) |
|
|
726
|
+
| A shared pool where per-item names were wanted | One changed upstream item misses the cache for the whole pool (§7) |
|
|
727
|
+
| Phases or subagents named after the machinery ("fan-out", "文件评审阶段", "节点3"), or no markers | A graph that says nothing about the work, or thirty cards (§8, §9) |
|
|
728
|
+
| A reviewer asked "is this good?" | It approves; ask what would break it (§3) |
|
|
729
|
+
| A reviewer loop, a final reviewer, a confirmer and a reader on one deliverable | Four sessions re-reading one piece of work; one mechanism, two with a reason (§3) |
|
|
730
|
+
| Findings reported unconfirmed, or a slow existing check put in `notCovered` | The user cannot tell "seen" from "suspected", or verified from skipped (§10) |
|
|
731
|
+
| A confirmer on a finding `world.run` already decided, or the suite run by hunter, confirmer and gate | One check paid three times; the exit code is the confirmation (§10) |
|
|
732
|
+
| A bare array returned, or nothing published | The main agent improvises the handoff and the user keeps nothing; return the report shape and publish the deliverable (§10) |
|
|
733
|
+
| A CSV and a table of its rows, or a dashboard nobody watches | Cards that are noise (§10) |
|
|
734
|
+
| A persona that says only "make the check pass" | Faking is the obedient reading of an impossible gate; tell it to escalate (§14) |
|
|
735
|
+
| A tunable constant interpolated into an ask | Amending it rewrites every such prompt and re-pays everything downstream (§13) |
|
|
736
|
+
| A wrong run left to finish, or stopped and left | `AmendWorkflow` it now, while it runs (§13) |
|
|
737
|
+
| A revised script pasted inline after a diagnostic | Twenty thousand tokens re-streamed to change one line; `Edit` the named file and pass `path` (§13) |
|
|
738
|
+
| A hole for what an `if` or a subagent could decide, or one in a fan-out callback | A run parked on you for nothing; the fan-out case does not compile (§15) |
|
|
735
739
|
|
|
736
740
|
## 13. After you submit
|
|
737
741
|
|
|
738
|
-
Compilation happens first. **Diagnostics mean nothing ran
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
re-streaming twenty thousand tokens to change one line is slow enough that some providers
|
|
746
|
-
stall on it, while the `Edit` that fixes it costs a few lines. (If the response names no
|
|
747
|
-
file — a checkout the tool could not write to — then fix the script and resubmit it inline,
|
|
748
|
-
as before.)
|
|
742
|
+
Compilation happens first. **Diagnostics mean nothing ran**, and they name the file your
|
|
743
|
+
script is in: an inline `script` is written under `.dcode/workflow-drafts/` before it is
|
|
744
|
+
compiled and the response hands you the path; a `path` submission is that file already. Each
|
|
745
|
+
diagnostic reads `{path}:L{line}:C{column} {message}`, counted in the file.
|
|
746
|
+
**Edit that file and resubmit with `path`. Do not paste the script inline again**: the
|
|
747
|
+
`Edit` costs a few lines; the re-stream costs twenty thousand tokens and may stall the
|
|
748
|
+
provider. (If the response names no file, resubmit inline.)
|
|
749
749
|
|
|
750
750
|
On a clean compile the run starts in the background and you get a run ID. **Do not poll it.**
|
|
751
|
-
The completion notification arrives on its own
|
|
752
|
-
reported item.
|
|
751
|
+
The completion notification arrives on its own with the final return value and every
|
|
752
|
+
reported item. Do other work, unless the user asked you to wait.
|
|
753
753
|
|
|
754
754
|
When you genuinely need to look at a run:
|
|
755
755
|
|
|
756
|
-
- `TaskOutput` blocks until a run *this session started* finishes
|
|
757
|
-
- `GetWorkflowRun` is an instant snapshot
|
|
758
|
-
|
|
756
|
+
- `TaskOutput` blocks until a run *this session started* finishes: the waiting tool.
|
|
757
|
+
- `GetWorkflowRun` is an instant snapshot; use it when you must not block, or for a run
|
|
758
|
+
another session owns, which `TaskOutput` cannot see.
|
|
759
759
|
- `ListWorkflowRuns` enumerates the project's runs, including other sessions'.
|
|
760
760
|
|
|
761
761
|
Read the terminal state precisely. A run ends in exactly one of three states:
|
|
@@ -765,109 +765,77 @@ Read the terminal state precisely. A run ends in exactly one of three states:
|
|
|
765
765
|
whose source file was missing). Replaying it would fail the same way, so
|
|
766
766
|
`ResumeWorkflowRun` refuses it; edit the run's script file, which the notification names,
|
|
767
767
|
and resubmit it with `AmendWorkflow` and `path`.
|
|
768
|
-
- **stopped** —
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
Reported items come back on errored and stopped runs too, so a dead run is still worth
|
|
779
|
-
reading. Model errors never reach the script: rate limits, overload, network errors,
|
|
780
|
-
timeouts and unknown provider errors are retried inside the run without limit while the
|
|
781
|
-
fan-out adapts to what the provider accepts, so a run that looks stalled with a "waiting for
|
|
782
|
-
provider" badge is waiting, not broken. If nothing succeeds for twenty minutes you get one
|
|
783
|
-
informational stall notification; the run is still running and needs nothing from you.
|
|
768
|
+
- **stopped** — resumable as-is with `ResumeWorkflowRun`. The `<stop-reason>` says why:
|
|
769
|
+
`user` (leave it alone unless they ask), `model` (you stopped it), `interrupted` (the
|
|
770
|
+
owning process exited; resume it), or `provider` (a deterministic model-side error —
|
|
771
|
+
sign-in expired, quota cap; the `<error>` block names the fix — resolve it with the user,
|
|
772
|
+
then resume). A fifth state, `superseded`, is a run you amended away: not resumable, no
|
|
773
|
+
notification.
|
|
774
|
+
|
|
775
|
+
Reported items come back on errored and stopped runs too. A run with a "waiting for
|
|
776
|
+
provider" badge is retrying a provider error (§16.3), not broken; after twenty minutes you
|
|
777
|
+
get one stall notification, and it still needs nothing from you.
|
|
784
778
|
|
|
785
779
|
**When the script itself was wrong, do not start over.** Any run — errored, stopped,
|
|
786
780
|
completed, or still running — can be superseded: edit the run's script file and call
|
|
787
|
-
`AmendWorkflow` with `run_id
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
world read and every cached ask whose subagent had read or run something runs live even if
|
|
794
|
-
its text is unchanged; asks whose subagent only answered keep settling from the cache. A gate
|
|
795
|
-
command therefore always tests the code the amended run actually produced; the price is
|
|
796
|
-
that doing steps after the first live write are re-paid. The old run is left exactly as it
|
|
797
|
-
was. This is the move after a `ScriptError`, after a bad prompt
|
|
798
|
-
produced a useless result, and when a completed analysis needs one more stage — rewriting
|
|
799
|
-
the workflow from scratch throws away work that was already paid for. Two things make the
|
|
800
|
-
cache hit: names that stay the same across the revision, and asks whose instructions stay
|
|
801
|
-
byte-identical (an upstream change cascades — a changed result changes what interpolates
|
|
802
|
-
into everything downstream, which is what you want).
|
|
781
|
+
`AmendWorkflow` with `run_id` and that `path`. The new run imports the old one's finished
|
|
782
|
+
work, matched per named subagent along its sequence of asks, so every step you did not touch
|
|
783
|
+
settles from cache and only the changed part runs (the boundary is in §16.4). This is the
|
|
784
|
+
move after a `ScriptError`, a bad prompt, or a completed analysis that needs one more stage.
|
|
785
|
+
Two things make the cache hit: names that stay the same, and asks whose instructions stay
|
|
786
|
+
byte-identical (an upstream change cascades downstream).
|
|
803
787
|
|
|
804
788
|
**Every run remembers its script file, so a revision is an `Edit`.** The terminal
|
|
805
|
-
notification names that path
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
nothing stopped and nothing created — that refusal means your `Edit` did not land, not that
|
|
811
|
-
the run cannot be amended (changing only `max_concurrency` or `subagent_model` is a real
|
|
812
|
-
change and goes through).
|
|
789
|
+
notification names that path and `GetWorkflowRun` reports it as `scriptPath`, so the script
|
|
790
|
+
never has to live in your context: compaction may have dropped the text you sent, the file
|
|
791
|
+
on disk has not moved. Edit it in place and pass `path`; pass `script` only for something
|
|
792
|
+
genuinely new. A `path` whose bytes still equal what the run ran is refused as
|
|
793
|
+
`script_unchanged` — your `Edit` did not land — with nothing stopped and nothing created.
|
|
813
794
|
|
|
814
795
|
**Editing a draft asks nothing.** `.dcode/workflow-drafts/` is machine-owned and
|
|
815
|
-
git-ignored, so an `Edit`
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
**Repair a run while it is still going.** The same call works before the run ends, and
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
That cascade rule has a converse that decides whether your revisions are cheap or ruinous.
|
|
833
|
-
Interpolating an upstream **result** into a prompt is safe: on resume the result replays
|
|
834
|
-
byte-identical, so the prompt does too. Interpolating a script **constant** is the
|
|
835
|
-
opposite bet — constants are exactly what an amendment tunes, and every ask whose text
|
|
836
|
-
mentions one is an ask whose cache you forfeit by tuning it, plus everything downstream of
|
|
837
|
-
it:
|
|
796
|
+
git-ignored, so an `Edit` under it opens no confirmation window; the window still stands
|
|
797
|
+
between the file and the run, so fix the file freely and let the submission be what the
|
|
798
|
+
user answers.
|
|
799
|
+
|
|
800
|
+
**Repair a run while it is still going.** The same call works before the run ends, and the
|
|
801
|
+
earlier the cheaper. When a run is heading the wrong way, do not wait for it and do not stop
|
|
802
|
+
it first: call `AmendWorkflow` on it. The tool stops the predecessor, waits for it to settle,
|
|
803
|
+
imports everything that settled before the stop at zero cost, and starts the revision — one
|
|
804
|
+
call, no `TaskStop`, no polling. The old run shows as "superseded" and sends no notification;
|
|
805
|
+
the result you get back names both runs.
|
|
806
|
+
|
|
807
|
+
The cascade rule has a converse that decides whether revisions are cheap or ruinous.
|
|
808
|
+
Interpolating an upstream **result** into a prompt is safe: on resume it replays
|
|
809
|
+
byte-identical, so the prompt does too. Interpolating a script **constant** is the opposite
|
|
810
|
+
bet — constants are what an amendment tunes, and every ask whose text mentions one forfeits
|
|
811
|
+
its cache when you tune it, plus everything downstream:
|
|
838
812
|
|
|
839
813
|
```ts
|
|
840
|
-
// ✗
|
|
841
|
-
//
|
|
842
|
-
// cache at the first revision and re-pays every ask after it — to reproduce
|
|
843
|
-
// answers the old run already holds.
|
|
814
|
+
// ✗ Amending PASS_THRESHOLD (say 96 → 94) rewrites this text, so the resumed run
|
|
815
|
+
// misses cache at the first revision and re-pays every ask after it.
|
|
844
816
|
draft = await writer.ask<Draft>(
|
|
845
817
|
`Scored ${review.score}; passing needs ${PASS_THRESHOLD}. Revise: ${JSON.stringify(review.comments)}`,
|
|
846
818
|
);
|
|
847
819
|
|
|
848
|
-
// ✓
|
|
849
|
-
//
|
|
850
|
-
// Amending the threshold now moves only where the loop exits — every round
|
|
851
|
-
// before that point settles from cache.
|
|
820
|
+
// ✓ Only replayed upstream values and the fact that the branch was taken; amending
|
|
821
|
+
// the threshold now moves only where the loop exits, and earlier rounds settle from cache.
|
|
852
822
|
draft = await writer.ask<Draft>(
|
|
853
823
|
`The review did not pass. Address each comment: ${JSON.stringify(review.comments)}`,
|
|
854
824
|
);
|
|
855
825
|
```
|
|
856
826
|
|
|
857
|
-
Keep the tunable knobs — thresholds, round caps — in the script's control flow,
|
|
858
|
-
|
|
859
|
-
|
|
827
|
+
Keep the tunable knobs — thresholds, round caps — in the script's control flow, where
|
|
828
|
+
amending them is free, and out of ask text, where it is a cache purge. A subagent rarely
|
|
829
|
+
needs the number; it needs the verdict and the feedback.
|
|
860
830
|
|
|
861
831
|
## 14. When a subagent escalates
|
|
862
832
|
|
|
863
|
-
Every subagent can escalate a blocking question to you while the run is going
|
|
864
|
-
script switches this on
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
a walled-in subagent has two moves left and both are bad — grind until the round cap, or
|
|
870
|
-
fake its way past.
|
|
833
|
+
Every subagent can escalate a blocking question to you while the run is going; nothing in
|
|
834
|
+
the script switches this on. It exists for the one thing a script cannot design around: a
|
|
835
|
+
subagent walled in by something not its fault — a gate it cannot pass (capped at 95 against
|
|
836
|
+
a threshold of 96), two instructions no single output satisfies, a fact only whoever started
|
|
837
|
+
the run knows. With no way to ask, it has two moves left, both bad: grind until the round
|
|
838
|
+
cap, or fake its way past.
|
|
871
839
|
|
|
872
840
|
**What reaches you.** A notification arrives mid-run carrying the run, the subagent, the
|
|
873
841
|
question with whatever evidence the subagent attached, and a globally unique question id shaped
|
|
@@ -890,34 +858,198 @@ you need not drop what you are doing, but you cannot leave it unanswered.
|
|
|
890
858
|
past the cache boundary — everything before it imports from the old run at no token cost,
|
|
891
859
|
and it re-runs against the fixed script.
|
|
892
860
|
|
|
893
|
-
**If the notification never arrives**,
|
|
894
|
-
|
|
895
|
-
snapshot is the
|
|
896
|
-
|
|
861
|
+
**If the notification never arrives**, `GetWorkflowRun` lists what a run still owes you:
|
|
862
|
+
the questions under `pendingQuestions`, ids included, and the holes it is waiting at (§15).
|
|
863
|
+
That snapshot is the way to check on a run you suspect is waiting on you.
|
|
864
|
+
|
|
865
|
+
**Write personas that make honesty the cheap move.** A persona that says "make the check
|
|
866
|
+
pass" and stops there leaves faking a pass as the obedient reading. One sentence closes that
|
|
867
|
+
off: *"If a check is impossible to pass, or your instructions contradict each other, escalate
|
|
868
|
+
and say so plainly rather than working around it."*
|
|
869
|
+
|
|
870
|
+
One ask gets three escalations; the fourth comes back as an ordinary result telling the
|
|
871
|
+
subagent to proceed on its own best judgement — a guard against chatter.
|
|
872
|
+
|
|
873
|
+
## 15. Holes: growing the workflow as the run learns
|
|
874
|
+
|
|
875
|
+
`hole<T>()` is the other mid-run request — §14 is the subagent's, this one is yours. A
|
|
876
|
+
script is what you know for sure; a hole is where knowing stops. Any phase whose subagents,
|
|
877
|
+
asks or gate you would have to guess is a hole: write the part before the guess, end it in
|
|
878
|
+
`hole<T>()`, and the run's findings write the rest. A workflow whose shape the request fixes
|
|
879
|
+
has no holes, and that is fine too.
|
|
880
|
+
|
|
881
|
+
A subagent returns a **value**; a hole returns **code**. Ask a subagent when the script
|
|
882
|
+
already knows what to do with the answer and only the data is missing. Leave a hole when
|
|
883
|
+
what is missing is the rest of the workflow — which phases come next, which subagents exist,
|
|
884
|
+
what each is told, what gate runs. *If you could write the code now and only the data is
|
|
885
|
+
missing, it is not a hole.*
|
|
886
|
+
|
|
887
|
+
| The unknown is… | Use |
|
|
888
|
+
| --- | --- |
|
|
889
|
+
| an answer the script knows how to consume | a subagent ask; fresh eyes if it is a judgment (§3) |
|
|
890
|
+
| a branch among outcomes you can enumerate now | a typed result and an `if` or a loop, in the script |
|
|
891
|
+
| what the remaining workflow should be, knowable only from findings | a hole |
|
|
892
|
+
| a question a subagent hits mid-task that only the run's owner can answer | escalation (§14) |
|
|
893
|
+
|
|
894
|
+
Subagents run without you, in parallel; a hole parks one branch until you take a turn. Spend
|
|
895
|
+
holes on shape, never on answers.
|
|
896
|
+
|
|
897
|
+
Three forms; `T` is always written out:
|
|
898
|
+
|
|
899
|
+
```ts
|
|
900
|
+
const plan = await hole<Plan>("决定分组", `最慢的模块是 ${survey.slowest}`); // decide, then continue
|
|
901
|
+
return await hole<Guide>("第1步:决定导览结构", `盘点:${JSON.stringify(survey)}`); // tail: the rest is not written yet
|
|
902
|
+
const plan = await hole<Plan>("决定分组", `…`, async () => { /* filled: the body stands in for the hole */ });
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
- **The name is a phase name.** A literal, unique among the script's holes and phase markers
|
|
906
|
+
(nested fills included), in the user's language: it labels the station, the notification and
|
|
907
|
+
the fill file. `T` is the contract the body is checked against.
|
|
908
|
+
- **The prompt is the one channel for values.** Interpolate what the decision needs; the
|
|
909
|
+
fill reads values there and types from the code.
|
|
910
|
+
- **The body sees every binding declared before the hole, none after**, and may leave holes
|
|
911
|
+
of its own.
|
|
912
|
+
- **Filled once, run per reach.** A hole in a loop or a helper is filled once and its body
|
|
913
|
+
runs each iteration with that iteration's bindings. Never inside a fan-out callback (`.map`
|
|
914
|
+
or another array-method body): the fill would be owed while the items already run.
|
|
915
|
+
|
|
916
|
+
### Grow by tail holes — the default for a task whose shape is not known upfront
|
|
917
|
+
|
|
918
|
+
When the request does not tell you the workflow — a repository to understand before the
|
|
919
|
+
work can be planned, a bug whose next step depends on what the last one found — do not
|
|
920
|
+
guess the topology. Write the part you know and end the script with a tail hole. The script
|
|
921
|
+
then grows by **nesting**: each fill is the statements of the innermost body, does one step,
|
|
922
|
+
and ends in the next tail hole, until one returns instead.
|
|
923
|
+
|
|
924
|
+
```ts
|
|
925
|
+
// 0. The seed you submit: what is known, then a typed gap.
|
|
926
|
+
phase("盘点仓库顶层目录");
|
|
927
|
+
const survey = await agent("勘察员").ask<Survey>("列出顶层目录,各用一句话说明作用。");
|
|
928
|
+
return await hole<Guide>("第1步:决定导览结构", `盘点:${JSON.stringify(survey.dirs)}`);
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
```ts
|
|
932
|
+
// 1. After the first fill: the hole has a body — one step, then the next hole.
|
|
933
|
+
return await hole<Guide>("第1步:决定导览结构", `盘点:…`, async () => {
|
|
934
|
+
phase("分章并行撰写初稿");
|
|
935
|
+
const drafts = await Promise.all(
|
|
936
|
+
survey.dirs.map((d) => agent(`写手·${d.path}`).ask<Chapter>(`写「${d.path}」一章:${d.purpose}`)),
|
|
937
|
+
);
|
|
938
|
+
return await hole<Guide>("第2步:审读与交付", `${drafts.length} 章初稿已就绪`);
|
|
939
|
+
});
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
```ts
|
|
943
|
+
// 2. After the second fill: the chain closes with a value, which is the run's result.
|
|
944
|
+
return await hole<Guide>("第1步:决定导览结构", `盘点:…`, async () => {
|
|
945
|
+
/* step 1 as above; `survey` and `drafts` are in scope below */
|
|
946
|
+
return await hole<Guide>("第2步:审读与交付", `…`, async () => {
|
|
947
|
+
phase("独立审读并修订");
|
|
948
|
+
const critique = await agent("审读员").ask<string>(`只凭文本挑毛病:${JSON.stringify(drafts)}`);
|
|
949
|
+
const chapters = await agent("修订编辑").ask<Chapter[]>(`按意见修订:${critique}`);
|
|
950
|
+
return { title: "仓库导览", chapters, notCovered: [] };
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
You send only the innermost statements; the tool splices them in and rewrites the draft
|
|
956
|
+
with the effective script, so the draft you read before the next fill is the script that is
|
|
957
|
+
running. The chain's rules: a fresh name per step (`第N步:<what it does>`; a repeated name
|
|
958
|
+
is a 9012); the prompt is the progress ledger; results stay in bindings (`survey`, `drafts`),
|
|
959
|
+
because every inner body sees the ones around it; a step may add phases, subagents and
|
|
960
|
+
holes of its own. The timeline grows to the right, one head per step. This is the normal
|
|
961
|
+
way to run a task whose shape only appears as the work proceeds, not a fallback.
|
|
962
|
+
|
|
963
|
+
### A stage shaped by discovery
|
|
964
|
+
|
|
965
|
+
The survey's *value* goes to the script as data; the fill writes the *topology* of the next
|
|
966
|
+
stage, which the survey decided: three reviewers or one, fanned out or sequential, which
|
|
967
|
+
check gates them.
|
|
968
|
+
|
|
969
|
+
```ts
|
|
970
|
+
const hot = await agent("剖析员").ask<Hotspots>("找出最慢的三个模块,说明各自的耦合。");
|
|
971
|
+
const reviews = await hole<Review[]>("怎么审查这些热点", `热点:${JSON.stringify(hot.modules)}`);
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
A fill for two independent modules and one shared one: two reviewers in a `Promise.all`,
|
|
975
|
+
a calibrated reviewer over the shared module, then a bounded fix-and-recheck loop — none of
|
|
976
|
+
it writable before `hot` was known.
|
|
977
|
+
|
|
978
|
+
### A procedure decided at first sight, run every round
|
|
979
|
+
|
|
980
|
+
```ts
|
|
981
|
+
for (const failure of failures) {
|
|
982
|
+
const triage = await hole<Triage>("每个失败怎么分诊", `第一个失败:${failure.name}\n${failure.output}`);
|
|
983
|
+
report(triage);
|
|
984
|
+
}
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
Filled at the first failure, the body runs for every one after with that round's `failure`.
|
|
988
|
+
The fill is a *procedure* — which subagent to send, what to ask, when to mark `unconfirmed`
|
|
989
|
+
— not an answer about one failure; that would be a subagent ask inside the loop.
|
|
897
990
|
|
|
898
|
-
|
|
899
|
-
wrote, so a persona that says "make the check pass" and stops there leaves faking a pass as
|
|
900
|
-
the obedient reading. One sentence closes that off; adapt this one: *"If a check is
|
|
901
|
-
impossible to pass, or your instructions contradict each other, escalate and say so plainly
|
|
902
|
-
rather than working around it."*
|
|
991
|
+
### A remedy the plan could not enumerate
|
|
903
992
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
993
|
+
```ts
|
|
994
|
+
const gate = await world.run("pnpm", ["test"]);
|
|
995
|
+
if (gate.exitCode !== 0) {
|
|
996
|
+
await hole<void>("测试没过怎么办", `退出码 ${gate.exitCode}:\n${gate.stderr.slice(0, 2000)}`);
|
|
997
|
+
}
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
If the remedies were known, the script would hold a `Remedy` value and an `if`. The hole is
|
|
1001
|
+
for when the fix may need phases and subagents nobody planned — a bisect, a second opinion,
|
|
1002
|
+
a rollback — decided with the failure in hand.
|
|
907
1003
|
|
|
908
|
-
|
|
1004
|
+
### Propose, judge, then build
|
|
909
1005
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1006
|
+
```ts
|
|
1007
|
+
const proposals = await Promise.all([1, 2, 3].map((k) => agent(`方案${k}`).ask<Proposal>("提一个方案。")));
|
|
1008
|
+
const pick = await agent("评委").ask<Pick>(`选最好的一个:${JSON.stringify(proposals)}`);
|
|
1009
|
+
return await hole<Outcome>("按选定方案施工", `选中:${JSON.stringify(proposals[pick.index])}`);
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
The judge is a subagent, because choosing is a value; the hole writes the stage that builds
|
|
1013
|
+
the winner, whose shape depends on what won.
|
|
1014
|
+
|
|
1015
|
+
**Not a hole:** a verdict, a summary, a choice among options, an answer per item — those are
|
|
1016
|
+
subagent asks — and any branch an `if` over a typed result can express.
|
|
1017
|
+
|
|
1018
|
+
**Filling one.** The notification carries the run, the hole's site id (`hole#21b40fca`), its name
|
|
1019
|
+
and type, the prompt with its values in, the draft's path and the hole's line, and the phases
|
|
1020
|
+
before and after. Then:
|
|
1021
|
+
|
|
1022
|
+
1. Read the draft around the line: the body is compiled where the hole stands and sees what
|
|
1023
|
+
is declared above it.
|
|
1024
|
+
2. Write only the statements — no `hole(...)` call, no arrow — returning a value of `T`, or
|
|
1025
|
+
ending in a new tail hole when the next step is not known yet; rehearse fixed logic in
|
|
1026
|
+
`EvalWorkflowSnippet` first (§6).
|
|
1027
|
+
3. Call `FillWorkflowHole` with `run_id`, `hole_id` and `script` (or `path`, §16.7). The run
|
|
1028
|
+
grows by the body and goes on; the response names the phases added and the draft, now
|
|
1029
|
+
holding the effective script, for any later `AmendWorkflow`.
|
|
1030
|
+
4. Diagnostics mean nothing was spliced and the hole still waits: edit the fill file the
|
|
1031
|
+
response names and resubmit with `path`, never paste it again (§13). A line in the
|
|
1032
|
+
draft's file is the run's recorded script: `AmendWorkflow`, not a draft edit.
|
|
1033
|
+
|
|
1034
|
+
A fill that throws at run time rejects at the site and ends the run errored unless caught;
|
|
1035
|
+
amend the draft as usual. Full scripts: `patterns.md` #14–#16, `examples.md` #7.
|
|
1036
|
+
|
|
1037
|
+
## Going deeper
|
|
1038
|
+
|
|
1039
|
+
- `${DCODE_SKILL_DIR}/patterns.md` — the topology catalogue. Its index puts the pipeline
|
|
1040
|
+
shapes first: per-item chaining, streaming through channels, a feedback loop with a counted
|
|
1041
|
+
close. Then fan-out/fan-in, review sweeps, planner-reviewer loops, judge panels, staged
|
|
1042
|
+
handoffs, bounded discovery, `world.run`-gated verifier loops, model routing, and the hole
|
|
1043
|
+
shapes (growth by tail holes, a stage shaped by discovery, a remedy hole). Read it when you
|
|
1044
|
+
know the shape you want and want it written correctly.
|
|
914
1045
|
- `${DCODE_SKILL_DIR}/examples.md` — complete worked scripts, including a two-subagent
|
|
915
|
-
adversarial prove/disprove loop
|
|
1046
|
+
adversarial prove/disprove loop and a repository guide grown step by step through tail
|
|
1047
|
+
holes. Read one when you want to see a whole script's arc.
|
|
916
1048
|
|
|
917
1049
|
## 16. Tool reference
|
|
918
1050
|
|
|
919
|
-
The
|
|
920
|
-
`EvalWorkflowSnippet` — carry
|
|
1051
|
+
The five authoring tools — `CreateWorkflow`, `AmendWorkflow`, `FillWorkflowHole`,
|
|
1052
|
+
`SaveWorkflow` and `EvalWorkflowSnippet` — carry short descriptions on purpose, and each refuses
|
|
921
1053
|
to run until this skill has been loaded in the session. This section is the part of their
|
|
922
1054
|
contract that the descriptions do not carry: the facade the compiler checks against, the
|
|
923
1055
|
rules a script must satisfy, and the fields each tool takes. Read it before writing or
|
|
@@ -932,14 +1064,12 @@ Compilation errors come back as diagnostics, counted in the script's file (§13)
|
|
|
932
1064
|
**Three sources; pass exactly one.**
|
|
933
1065
|
|
|
934
1066
|
- `script`: a one-off workflow written inline. It is saved to a file under
|
|
935
|
-
`.dcode/workflow-drafts/` and the result names that file,
|
|
936
|
-
|
|
937
|
-
script again.
|
|
1067
|
+
`.dcode/workflow-drafts/` and the result names that file, compiled or not; revise it by
|
|
1068
|
+
editing the file and resubmitting with `path` (§13).
|
|
938
1069
|
- `saved`: a workflow saved in this project or globally, by name —
|
|
939
|
-
`saved: { name: "pr-review", args: { pr: "123" } }
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
a saved workflow the user reviewed and kept beats a rebuilt one. Running a saved workflow
|
|
1070
|
+
`saved: { name: "pr-review", args: { pr: "123" } }`; arguments are validated against its
|
|
1071
|
+
declaration before anything runs. Check `ListSavedWorkflows` before writing one from
|
|
1072
|
+
scratch: a saved workflow the user kept beats a rebuilt one. Running a saved workflow
|
|
943
1073
|
is the one call that does not need this skill loaded.
|
|
944
1074
|
- `path`: a script file on disk, relative to the working directory or absolute — normally
|
|
945
1075
|
the file a previous result named. Pass `args` alongside it when the file declares
|
|
@@ -953,14 +1083,12 @@ Either way the user confirms the run, and the confirmation shows the actual scri
|
|
|
953
1083
|
Always pass it for an inline script; it labels the run everywhere and names its draft
|
|
954
1084
|
file. It defaults to the saved workflow's name.
|
|
955
1085
|
- `max_concurrency`: an upper bound on how many subagents work at once. Set it only when
|
|
956
|
-
the user asks to limit parallelism — never
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
model; pass the name the user used, and if the tool cannot resolve it, pick from the ids
|
|
963
|
-
it lists or call `ListModels`. You stay on the session model either way.
|
|
1086
|
+
the user asks to limit parallelism — never as a reaction to provider rate limits or
|
|
1087
|
+
errors, which the runtime already adapts to.
|
|
1088
|
+
- `subagent_model`: the model the subagents run on, as `providerId/modelId` or a bare model
|
|
1089
|
+
id (optionally `$reasoningLevel`). Set it only when the user asks for a specific model;
|
|
1090
|
+
pass the name they used, and if the tool cannot resolve it, pick from the ids it lists or
|
|
1091
|
+
`ListModels`. You stay on the session model either way.
|
|
964
1092
|
|
|
965
1093
|
This tool starts a new run. To change a run that exists — errored, completed, stopped or
|
|
966
1094
|
still running — call `AmendWorkflow` (§13, §16.4), never `CreateWorkflow` again.
|
|
@@ -974,67 +1102,53 @@ plain interfaces and never uses `declare`.
|
|
|
974
1102
|
|
|
975
1103
|
<!-- facade-dts:start -->
|
|
976
1104
|
```ts
|
|
977
|
-
/**
|
|
978
|
-
* A node: one task assigned to an actor, producing a typed result.
|
|
979
|
-
* Thenable — await it, or combine with Promise.all for joins.
|
|
980
|
-
*/
|
|
1105
|
+
/** The pending result of one ask. Await it, or pass it to Promise.all with others. */
|
|
981
1106
|
declare interface Node<T> extends PromiseLike<T> {}
|
|
982
1107
|
|
|
1108
|
+
/** A model declared with model(). */
|
|
1109
|
+
declare class ModelRef { private constructor(); private readonly modelRef: never }
|
|
1110
|
+
|
|
983
1111
|
/**
|
|
984
|
-
*
|
|
985
|
-
*
|
|
986
|
-
* it may do with them is said in the ask.
|
|
1112
|
+
* Declare a model subagents may run on: "modelId" or "providerId/modelId", optional "$level".
|
|
1113
|
+
* String literal only (checked at launch); choose among ModelRefs at run time.
|
|
987
1114
|
*/
|
|
1115
|
+
declare function model(id: string): ModelRef;
|
|
1116
|
+
|
|
1117
|
+
/** Persona of a subagent, fixed when agent() creates it. Every subagent has the same working tools. */
|
|
988
1118
|
declare interface AgentPersona {
|
|
989
1119
|
/** System prompt describing the actor's role. */
|
|
990
1120
|
system?: string;
|
|
1121
|
+
/** Model id literal or ModelRef; omitted = the run's subagent model. */
|
|
1122
|
+
model?: ModelRef | string;
|
|
991
1123
|
}
|
|
992
1124
|
|
|
993
1125
|
/**
|
|
994
|
-
*
|
|
995
|
-
*
|
|
1126
|
+
* A subagent: one conversation that keeps its context across asks. Asks issued while it is
|
|
1127
|
+
* busy wait their turn, first in, first out.
|
|
996
1128
|
*/
|
|
997
1129
|
declare interface Agent {
|
|
998
1130
|
/**
|
|
999
|
-
*
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1131
|
+
* Give the subagent one task. With a type argument, the answer is a value of type T,
|
|
1132
|
+
* validated against a schema built from it: T is an interface you define in this script
|
|
1133
|
+
* with a plain "interface" declaration (no "declare" modifier). Without one, the answer is
|
|
1134
|
+
* the subagent's final reply text.
|
|
1003
1135
|
*/
|
|
1004
1136
|
ask<T = string>(instructions: string): Node<T>;
|
|
1005
1137
|
}
|
|
1006
1138
|
|
|
1007
1139
|
/**
|
|
1008
|
-
* Create a
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
* unique within the run: two actors under the same name fail the whole run. It is
|
|
1013
|
-
* also the key a revised re-run matches its cache on (AmendWorkflow imports the
|
|
1014
|
-
* finished work of each named actor), so stable, meaningful
|
|
1015
|
-
* names carry work across script revisions. Anonymous actors are legal and never
|
|
1016
|
-
* reuse imported work.
|
|
1017
|
-
*
|
|
1018
|
-
* In a fan-out or a loop each iteration is a separate actor, so a single static name
|
|
1019
|
-
* there is the duplicate case: give each one its own name (agent("reviewer-" + file))
|
|
1020
|
-
* or leave them all anonymous. A literal name in a loop is reported when the script
|
|
1021
|
-
* is compiled; a computed one fails at run time.
|
|
1140
|
+
* Create a subagent. Every call starts a new, empty conversation; to share one, share the
|
|
1141
|
+
* returned value. A non-empty name is an identity: unique within the run (a literal duplicate
|
|
1142
|
+
* is a compile error, a computed one fails the run) and the key AmendWorkflow matches cached
|
|
1143
|
+
* work by. Unnamed subagents are allowed and never reuse cached work.
|
|
1022
1144
|
*/
|
|
1023
1145
|
declare function agent(name?: string, persona?: string | AgentPersona): Agent;
|
|
1024
1146
|
|
|
1025
1147
|
/**
|
|
1026
|
-
* The run's arguments
|
|
1027
|
-
*
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1030
|
-
* declaration and fills in defaults before the run starts, so what lands here is
|
|
1031
|
-
* always a complete, checked bag. For an inline script — and inside a snippet — it is
|
|
1032
|
-
* simply empty.
|
|
1033
|
-
*
|
|
1034
|
-
* Always defined, so reading args.target is a plain property read rather than a crash.
|
|
1035
|
-
* The values are typed unknown on purpose: the compiler surface must not change from
|
|
1036
|
-
* one workflow to the next, so narrow them in the script -- String(args.target), or a
|
|
1037
|
-
* typeof guard -- exactly as you would any other external input.
|
|
1148
|
+
* The run's arguments. For a saved workflow they are validated against its declared
|
|
1149
|
+
* arguments, with defaults filled in, before the run starts; an inline script or a snippet
|
|
1150
|
+
* gets {}. Always defined; the values are unknown, so narrow them (String(args.target), a
|
|
1151
|
+
* typeof guard).
|
|
1038
1152
|
*/
|
|
1039
1153
|
declare const args: Readonly<Record<string, unknown>>;
|
|
1040
1154
|
|
|
@@ -1042,31 +1156,17 @@ declare const args: Readonly<Record<string, unknown>>;
|
|
|
1042
1156
|
declare function log(message: string): void;
|
|
1043
1157
|
|
|
1044
1158
|
/**
|
|
1045
|
-
* Publish one intermediate result while the run is
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
1049
|
-
* the
|
|
1050
|
-
*
|
|
1051
|
-
* still did eleven tasks' worth of work, and reported items are how that work
|
|
1052
|
-
* survives.
|
|
1159
|
+
* Publish one intermediate result while the run is going; returns nothing. Items are
|
|
1160
|
+
* recorded: a resumed run never shows one twice, and they reach the completion notification
|
|
1161
|
+
* even when the run fails. The item must be JSON-serializable (plain objects, arrays, strings,
|
|
1162
|
+
* numbers, booleans, null); functions, class instances, Date and promises are compile
|
|
1163
|
+
* errors. Caps fail the whole run, not the call: 65,536 items per run, 1 MiB per serialized
|
|
1164
|
+
* item, 1 GiB per run.
|
|
1053
1165
|
*
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1057
|
-
*
|
|
1058
|
-
* The item must be JSON-serializable: plain objects, arrays, strings, numbers,
|
|
1059
|
-
* booleans, null. Functions, class instances, Date and promises are rejected when
|
|
1060
|
-
* the script is compiled.
|
|
1061
|
-
*
|
|
1062
|
-
* The optional second argument routes the item to a dashboard artifact: pass the id
|
|
1063
|
-
* of a preset declared with artifact.chart / table / metrics / board, and this item
|
|
1064
|
-
* becomes one more point, row, tile value or card on it — the dashboard is nothing
|
|
1065
|
-
* but the items tagged with its id. The tag must be a compile-time string literal
|
|
1066
|
-
* naming a preset the script declares (anywhere in the text, but the declaration must
|
|
1067
|
-
* have executed by the time this call runs); a tag that names nothing, or names a
|
|
1068
|
-
* file/markdown artifact, fails the run. An untagged report is unchanged: it goes to
|
|
1069
|
-
* the run's Results, and a tagged one goes to both.
|
|
1166
|
+
* artifactId routes the item to a dashboard: a compile-time literal naming a preset
|
|
1167
|
+
* (artifact.chart / table / metrics / board) whose declaration has executed by then. The
|
|
1168
|
+
* item becomes one point, row, tile value or card there and still lands in the run's
|
|
1169
|
+
* Results. A tag naming nothing, or a file/markdown artifact, fails the run.
|
|
1070
1170
|
*/
|
|
1071
1171
|
declare function report(item: unknown, artifactId?: string): void;
|
|
1072
1172
|
|
|
@@ -1076,7 +1176,7 @@ declare interface ArtifactRef { id: string; version: number }
|
|
|
1076
1176
|
declare interface ArtifactOptions {
|
|
1077
1177
|
/** Shown as the card title; defaults to the id. In the user's language. */
|
|
1078
1178
|
title?: string;
|
|
1079
|
-
/** A sentence or two, shown beside the title when this artifact
|
|
1179
|
+
/** A sentence or two, shown beside the title when this artifact is the run's primary. */
|
|
1080
1180
|
description?: string;
|
|
1081
1181
|
/** The run's deliverable: the card and the run pane lead with it. At most one id per run; once set it stays set for later versions. */
|
|
1082
1182
|
primary?: boolean;
|
|
@@ -1116,44 +1216,24 @@ declare interface BoardSpec extends ArtifactOptions {
|
|
|
1116
1216
|
detail?: ArtifactField[];
|
|
1117
1217
|
}
|
|
1118
1218
|
/**
|
|
1119
|
-
* Publish what the user
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
1123
|
-
*
|
|
1124
|
-
*
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
1127
|
-
*
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1130
|
-
* Every id is a compile-time string literal (non-empty, at most 64 characters of
|
|
1131
|
-
* [A-Za-z0-9_.-]); the set a run can publish is fixed at submit time, so the compiler
|
|
1132
|
-
* rejects a computed one. Within one run an id belongs to exactly one member.
|
|
1133
|
-
* The two families are deliberately asymmetric, and the asymmetry is the whole design:
|
|
1134
|
-
* - CONTENT (file, markdown) are EFFECTS: async, resolve to an ArtifactRef, and REJECT
|
|
1135
|
-
* catchably — missing file, not a file, path outside the workspace, over the size cap, no
|
|
1136
|
-
* store. try { await artifact.file("book", "out/book.pdf") } catch { …ask a subagent to
|
|
1137
|
-
* write it… } is the intended idiom. Bytes are copied at publish time, so later workspace
|
|
1138
|
-
* edits never rewrite a version; republishing an id mints the NEXT version and keeps the
|
|
1139
|
-
* old ones (at most 16 per id).
|
|
1140
|
-
* - PRESET (chart, table, metrics, board) are DECLARATIONS: synchronous, return nothing,
|
|
1141
|
-
* never touch a file; they say how items tagged with their id are drawn. Declare each ONCE,
|
|
1142
|
-
* at the top, then feed it with report(item, "<id>"). The same id with an identical spec is
|
|
1143
|
-
* a no-op; a DIFFERENT or malformed spec fails the whole run — a void return has no
|
|
1144
|
-
* rejection channel, exactly as with report().
|
|
1219
|
+
* Publish what the user keeps: cards beside the run, kept after it ends. Every id is a
|
|
1220
|
+
* compile-time string literal (non-empty, at most 64 characters of [A-Za-z0-9_.-]) and is
|
|
1221
|
+
* used with one member only.
|
|
1222
|
+
* - CONTENT (file, markdown) are effects: async, resolve to an ArtifactRef, and reject
|
|
1223
|
+
* catchably (missing file, not a file, outside the workspace, over the cap, or no artifact
|
|
1224
|
+
* store in this host).
|
|
1225
|
+
* Bytes are copied at publish time; republishing an id mints the next version and keeps
|
|
1226
|
+
* the old ones.
|
|
1227
|
+
* - PRESET (chart, table, metrics, board) are declarations: synchronous and void, drawn from
|
|
1228
|
+
* the items tagged report(item, "<id>"). Declare each once, at the top level; an identical
|
|
1229
|
+
* re-declaration is a no-op, a different or malformed spec fails the whole run.
|
|
1145
1230
|
* Caps: 32 ids per run, 16 versions per id, 20 MiB per file, 256 KB per markdown, 120
|
|
1146
1231
|
* characters of title and 500 of description.
|
|
1147
1232
|
*/
|
|
1148
1233
|
declare const artifact: {
|
|
1149
|
-
/**
|
|
1150
|
-
* Publish a file from the workspace. path is workspace-relative, resolved by the same
|
|
1151
|
-
* resolver files.read() uses; the bytes are copied at publish time. The content type is
|
|
1152
|
-
* read off the extension unless opts.contentType overrides it. Rejects (catchably)
|
|
1153
|
-
* rather than publishing something empty.
|
|
1154
|
-
*/
|
|
1234
|
+
/** Publish a workspace file, path resolved as in files.read(). The type comes from the extension unless opts.contentType sets it. */
|
|
1155
1235
|
file(id: string, path: string, opts?: ArtifactFileOptions): Promise<ArtifactRef>;
|
|
1156
|
-
/** Publish markdown text the script composed
|
|
1236
|
+
/** Publish markdown text the script composed. */
|
|
1157
1237
|
markdown(id: string, content: string, opts?: ArtifactOptions): Promise<ArtifactRef>;
|
|
1158
1238
|
/** Declare a chart fed by report(item, id): each tagged item is one point. */
|
|
1159
1239
|
chart(id: string, spec: ChartSpec): void;
|
|
@@ -1166,44 +1246,26 @@ declare const artifact: {
|
|
|
1166
1246
|
};
|
|
1167
1247
|
|
|
1168
1248
|
/**
|
|
1169
|
-
* Mark the start of a phase: a
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1175
|
-
* group the whole script, top to bottom.
|
|
1176
|
-
*
|
|
1177
|
-
* Name phases for the user, in the language the user is speaking in this session: a short
|
|
1178
|
-
* natural phrase saying what the stage accomplishes ("Research each changed file in parallel",
|
|
1179
|
-
* "汇总并产出最终报告"). Graph-building vocabulary the user never chose — "fan-out", "gate",
|
|
1180
|
-
* "aggregate" — is not a name; the user approves stages by what they do. Say it the way you
|
|
1181
|
-
* would tell a colleague what is happening: "确认测试仍然通过", not "执行测试验证任务".
|
|
1182
|
-
*
|
|
1183
|
-
* The scope is the rest of the enclosing block: the marker claims every step issued
|
|
1184
|
-
* from it to the end of the block it stands in — nested blocks and inlined helper
|
|
1185
|
-
* calls included — and the enclosing phase resumes once that block ends. A marker
|
|
1186
|
-
* inside an if-branch therefore groups that branch and does not leak past it. Two
|
|
1187
|
-
* markers with the same name are one phase: repeating a name continues that phase,
|
|
1188
|
-
* which is the opposite of an actor's name — that one has to be unique.
|
|
1189
|
-
*
|
|
1190
|
-
* Two rules the compiler enforces. The name must be a compile-time string literal
|
|
1191
|
-
* ("review the diff" or a no-substitution template) and non-empty, because the phase
|
|
1192
|
-
* names label the graph the user confirms before anything runs. And the call must
|
|
1193
|
-
* stand alone as its own statement: a marker in expression position has no
|
|
1194
|
-
* rest-of-block to claim.
|
|
1195
|
-
*
|
|
1196
|
-
* Every phase must contain at least one subagent ask or one world.run. A phase is a
|
|
1197
|
-
* stage the user watches progress through; plain script logic between two asks (reading
|
|
1198
|
-
* args, shaping a prompt, building the return) runs in a flash and shows no progress, so
|
|
1199
|
-
* it is not a stage. Fold it into the phase before or after it; never open a phase for
|
|
1200
|
-
* the setup at the top or the return at the bottom.
|
|
1201
|
-
*
|
|
1202
|
-
* Idiom: one marker at the head of each stage that does work — name the loop body and
|
|
1203
|
-
* its check where they start, name the close-out that asks or runs after the loop.
|
|
1249
|
+
* Mark the start of a phase: a named group of the steps that follow, drawn as one node on
|
|
1250
|
+
* the graph the user approves. Presentation only: it starts, waits for and returns nothing.
|
|
1251
|
+
* Required. The name is a non-empty compile-time literal and the call a standalone
|
|
1252
|
+
* statement. A marker covers every step from it to the end of the block it stands in
|
|
1253
|
+
* (nested blocks and inlined helpers included); two markers with the same name are one
|
|
1254
|
+
* phase. Every phase contains at least one ask or world.run.
|
|
1204
1255
|
*/
|
|
1205
1256
|
declare function phase(name: string): void;
|
|
1206
1257
|
|
|
1258
|
+
/**
|
|
1259
|
+
* A typed gap: code you write later, once an earlier step's findings are in. When the run
|
|
1260
|
+
* reaches an unfilled hole, that branch waits while you write the body (FillWorkflowHole);
|
|
1261
|
+
* the rest of the run keeps going. prompt is the message you will receive, so interpolate
|
|
1262
|
+
* the values the decision needs. The body runs in the hole's place, sees the bindings
|
|
1263
|
+
* declared before it, and returns the hole's value. The filled form passes the body last.
|
|
1264
|
+
*/
|
|
1265
|
+
declare function hole<T>(name: string, prompt?: string): Promise<T>;
|
|
1266
|
+
declare function hole<T>(name: string, body: () => Promise<T>): Promise<T>;
|
|
1267
|
+
declare function hole<T>(name: string, prompt: string, body: () => Promise<T>): Promise<T>;
|
|
1268
|
+
|
|
1207
1269
|
/** One matching line found by files.grep. */
|
|
1208
1270
|
declare interface GrepMatch {
|
|
1209
1271
|
/** Workspace-relative path of the file the match was found in. */
|
|
@@ -1215,30 +1277,18 @@ declare interface GrepMatch {
|
|
|
1215
1277
|
}
|
|
1216
1278
|
|
|
1217
1279
|
/**
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1220
|
-
* letting them read files with their own tools; read() and grep() are for when the
|
|
1221
|
-
* script itself must shard or branch on content. There is no write — writing to the
|
|
1222
|
-
* world is an agent task.
|
|
1280
|
+
* Read-only views of the workspace. Each result is recorded, so a resumed run gets the same
|
|
1281
|
+
* answer back instead of reading again. There is no write: writing is a subagent's task.
|
|
1223
1282
|
*/
|
|
1224
1283
|
declare const files: {
|
|
1225
|
-
/**
|
|
1226
|
-
* List workspace files matching a glob pattern, as workspace-relative paths sorted
|
|
1227
|
-
* lexicographically. Capped at 2000 files: over the cap the call rejects instead of
|
|
1228
|
-
* returning a partial view — narrow the pattern.
|
|
1229
|
-
*/
|
|
1284
|
+
/** Workspace-relative paths matching a glob, sorted. Over 2000 files the call rejects. */
|
|
1230
1285
|
glob(pattern: string): Promise<string[]>;
|
|
1231
1286
|
/** Read one workspace file as UTF-8 text. Size-capped. */
|
|
1232
1287
|
read(path: string): Promise<string>;
|
|
1233
1288
|
/**
|
|
1234
|
-
* Search
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1237
|
-
* line numbers.
|
|
1238
|
-
*
|
|
1239
|
-
* Capped at 2000 matches or 256KB of results, whichever comes first. Over the cap
|
|
1240
|
-
* the call rejects instead of returning a partial view — a silently truncated search
|
|
1241
|
-
* is the one result you cannot reason about — so narrow the pattern or add a glob.
|
|
1289
|
+
* Search contents with a ripgrep-compatible regex, optionally narrowed by a glob over
|
|
1290
|
+
* paths ("*.ts", "src/**"); one entry per matching line. Over 2000 matches or 256KB of
|
|
1291
|
+
* results the call rejects.
|
|
1242
1292
|
*/
|
|
1243
1293
|
grep(pattern: string, glob?: string): Promise<GrepMatch[]>;
|
|
1244
1294
|
};
|
|
@@ -1270,30 +1320,17 @@ declare interface GitCommit {
|
|
|
1270
1320
|
}
|
|
1271
1321
|
|
|
1272
1322
|
/**
|
|
1273
|
-
*
|
|
1274
|
-
*
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
* argument list for one allowlisted subcommand and never a shell string, so there is
|
|
1279
|
-
* no call this surface can express that writes. A base must name a single ref — no
|
|
1280
|
-
* ".." ranges in this version — and paths are workspace-relative.
|
|
1281
|
-
*
|
|
1282
|
-
* Observations are scoped to the workspace, which is the same world files.* observes:
|
|
1283
|
-
* every path you get back is relative to the workspace and safe to pass straight to
|
|
1284
|
-
* files.read(). If the workspace is a subdirectory of the repository, changes outside
|
|
1285
|
-
* it are not reported — the workspace is the world. git.log is the exception, because
|
|
1286
|
-
* commits are repository-wide objects rather than paths.
|
|
1287
|
-
*
|
|
1288
|
-
* Caps reject rather than truncate (diff at 512KB, log at 100 commits), for the same
|
|
1289
|
-
* reason grep does. Outside a git repository, or with no git available, every call
|
|
1290
|
-
* rejects with a catchable error, so the idiom is try/catch with a files.glob fallback.
|
|
1323
|
+
* Read-only git views, recorded like files.* so a resumed run gets the same answer back; no
|
|
1324
|
+
* call can write. A base names a single ref (no ".." ranges). Paths are workspace-relative, and
|
|
1325
|
+
* changes outside the workspace are not reported; git.log alone is repository-wide. Caps
|
|
1326
|
+
* reject rather than truncate: diff at 512KB, log at 100 commits. Outside a git repository,
|
|
1327
|
+
* or without git, every call rejects catchably.
|
|
1291
1328
|
*/
|
|
1292
1329
|
declare const git: {
|
|
1293
1330
|
/**
|
|
1294
|
-
* Workspace-relative paths that changed. With no base: files modified against HEAD
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1331
|
+
* Workspace-relative paths that changed. With no base: files modified against HEAD, plus
|
|
1332
|
+
* untracked files. With a base ref: tracked files whose current state differs from that
|
|
1333
|
+
* ref, uncommitted edits included, untracked files not.
|
|
1297
1334
|
*/
|
|
1298
1335
|
changedFiles(base?: string): Promise<string[]>;
|
|
1299
1336
|
/**
|
|
@@ -1303,10 +1340,7 @@ declare const git: {
|
|
|
1303
1340
|
diff(base?: string, path?: string): Promise<string>;
|
|
1304
1341
|
/** The current working-tree status, for the workspace. */
|
|
1305
1342
|
status(): Promise<GitStatus>;
|
|
1306
|
-
/**
|
|
1307
|
-
* The most recent commits, newest first. Default 20, maximum 100. Unlike the other
|
|
1308
|
-
* members this reads repository-wide history, not workspace paths.
|
|
1309
|
-
*/
|
|
1343
|
+
/** The most recent commits, newest first. Default 20, maximum 100. */
|
|
1310
1344
|
log(count?: number): Promise<GitCommit[]>;
|
|
1311
1345
|
};
|
|
1312
1346
|
|
|
@@ -1321,28 +1355,44 @@ declare interface WorldRunResult {
|
|
|
1321
1355
|
}
|
|
1322
1356
|
|
|
1323
1357
|
/**
|
|
1324
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
* command could not run as an observation at all: spawn failure, or timeout (default
|
|
1332
|
-
* 300000ms, override per call via timeoutMs, no upper cap).
|
|
1333
|
-
*
|
|
1334
|
-
* cmd must be a compile-time string literal: the script's command set is shown to the
|
|
1335
|
-
* user when the run is confirmed, and only those commands are executable. Fixed argv,
|
|
1336
|
-
* never a shell — no pipes, no redirection, no variable expansion; compose with
|
|
1337
|
-
* multiple calls and plain code. cwd is the workspace. Idiom: model generates, code
|
|
1338
|
-
* gates — run the check here, parse its output with pure script logic, and hand
|
|
1339
|
-
* failures to an agent to fix. A helper that needs Node builtins can be inlined as
|
|
1340
|
-
* world.run("node", ["-e", code]) — the code string lives inside the script, so it is
|
|
1341
|
-
* pinned by the journal key like every other argument.
|
|
1358
|
+
* Run a command. Each call runs once and its result is recorded: a resumed run reuses the
|
|
1359
|
+
* recorded result instead of running the command again. A completed process RESOLVES,
|
|
1360
|
+
* nonzero exit included; the promise rejects (catchably) only on spawn failure or timeout
|
|
1361
|
+
* (default 300000ms, timeoutMs overrides, no upper cap). cmd is a compile-time string
|
|
1362
|
+
* literal, shown to the user at confirmation. Fixed argv, never a shell: no pipes,
|
|
1363
|
+
* redirection or expansion. cwd is the workspace. Node builtins are reachable as
|
|
1364
|
+
* world.run("node", ["-e", code]).
|
|
1342
1365
|
*/
|
|
1343
1366
|
declare const world: {
|
|
1344
1367
|
run(cmd: string, args?: string[], opts?: { timeoutMs?: number }): Promise<WorldRunResult>;
|
|
1345
1368
|
};
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
|
+
* A stream of typed items between two stages: one stage send()s, another drains it with
|
|
1372
|
+
* for await. Unbounded, first-in-first-out, each item to exactly one receiver.
|
|
1373
|
+
*/
|
|
1374
|
+
declare interface Channel<T> extends AsyncIterable<T> {
|
|
1375
|
+
/** Enqueue one item; synchronous, never waits. Throws ChannelClosed after close(). */
|
|
1376
|
+
send(item: T): void;
|
|
1377
|
+
/**
|
|
1378
|
+
* End the stream: receivers get the remaining items, then their loops exit. Idempotent.
|
|
1379
|
+
* A channel nobody closes fails the run as ChannelDeadlock, naming it, once nothing in
|
|
1380
|
+
* flight could send to it again.
|
|
1381
|
+
*/
|
|
1382
|
+
close(): void;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
/**
|
|
1386
|
+
* Create a channel. The name labels the deadlock message; it is not an identity. A receiver
|
|
1387
|
+
* on an empty, open channel waits until a send or the close.
|
|
1388
|
+
*/
|
|
1389
|
+
declare function channel<T>(name?: string): Channel<T>;
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* Run an async block as a concurrent stage. It starts immediately, not when awaited, and
|
|
1393
|
+
* returns its promise.
|
|
1394
|
+
*/
|
|
1395
|
+
declare function future<T>(body: () => Promise<T>): Promise<T>;
|
|
1346
1396
|
```
|
|
1347
1397
|
<!-- facade-dts:end -->
|
|
1348
1398
|
|
|
@@ -1362,10 +1412,11 @@ declare const world: {
|
|
|
1362
1412
|
- `world.run` executes a real command. Its first argument must be a compile-time string
|
|
1363
1413
|
literal — the script's command set is shown to the user at confirmation — so interpolate
|
|
1364
1414
|
runtime values into the args array, never into the command name. A nonzero exit code
|
|
1365
|
-
comes back as a value
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1415
|
+
comes back as a value, not an exception (§5).
|
|
1416
|
+
- `hole<T>()` (§15): explicit type argument; a literal name of at most 128 characters,
|
|
1417
|
+
unique among the script's holes and phase markers; the call awaited and written inline;
|
|
1418
|
+
outside every array-method fan-out callback (a `for...of` body is fine); the body reads no
|
|
1419
|
+
binding declared after the hole. All of these are diagnostic 9012.
|
|
1369
1420
|
- Phases are required (§8): cover the whole script with `phase("...")` markers, one at the
|
|
1370
1421
|
head of each stage. The name is a compile-time string literal and the call is a standalone
|
|
1371
1422
|
statement; the marker claims the rest of its enclosing block, nested blocks and inlined
|
|
@@ -1377,20 +1428,24 @@ declare const world: {
|
|
|
1377
1428
|
- Subagent names: the name you pass to `agent("...")` is the card the user sees, so write
|
|
1378
1429
|
it for the user in the session's language (§9). It is also an identity: unique within the
|
|
1379
1430
|
run, and the key an amended run matches its cached results by. Keep names stable across
|
|
1380
|
-
revisions
|
|
1431
|
+
revisions, and give duplicates in a loop their own computed names.
|
|
1381
1432
|
- Artifact ids and the `report` tag are compile-time literals; one id belongs to one
|
|
1382
1433
|
artifact kind; at most one artifact carries `primary: true`; a preset artifact is declared
|
|
1383
|
-
at the top level, not inside a loop, callback or branch (§10)
|
|
1384
|
-
catchably when the file is missing or too large.
|
|
1385
|
-
- Model-side errors never reach the script. Rate limits,
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1434
|
+
at the top level, not inside a loop, callback or branch (§10), and a fill's body is where
|
|
1435
|
+
its hole stands. Publishing rejects catchably when the file is missing or too large.
|
|
1436
|
+
- Model-side errors never reach the script. Rate limits, overload, network errors and
|
|
1437
|
+
timeouts are retried by the runtime without limit while it adapts the fan-out; a
|
|
1438
|
+
deterministic one (expired sign-in, model not in the plan, quota cap) stops the run as
|
|
1439
|
+
`stopped` for the user to fix and resume. Write no retry loops or `try`/`catch` for
|
|
1440
|
+
provider errors; reserve them for logic failures — a result that failed validation, a gate
|
|
1441
|
+
that did not pass, a world read over its cap, a missing artifact source, or a
|
|
1442
|
+
`ContextLimit` (the ask outgrew the model's context even after compaction: split it).
|
|
1443
|
+
- `channel`, `future`, `Channel.send` and `Channel.close` are facade callables: call them
|
|
1444
|
+
directly (9001 applies to a stored or aliased call); a channel value itself may be stored
|
|
1445
|
+
or passed freely. `send` after `close()` throws
|
|
1446
|
+
`ChannelClosed`, catchable. Stalls fail the run, never time out: `ChannelDeadlock` when
|
|
1447
|
+
receivers wait on channels nothing can send to any more (naming each), `ScriptStalled` when
|
|
1448
|
+
some other promise can never settle.
|
|
1394
1449
|
- The final `return` is the model-facing result; artifacts are the user-facing deliverable.
|
|
1395
1450
|
Never put the same content in both.
|
|
1396
1451
|
- On diagnostics, edit the file the result names and call the tool again with `path`; never
|
|
@@ -1440,8 +1495,8 @@ would describe a workspace that no longer exists, so they run live too. Asks tha
|
|
|
1440
1495
|
answered keep settling from the cache. Editing an ask's text is how you force it to run
|
|
1441
1496
|
again; keep names stable and keep tunable constants out of ask text (§13).
|
|
1442
1497
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1498
|
+
On diagnostics nothing was stopped and nothing was started; fix the file the result names
|
|
1499
|
+
and call again with `path`.
|
|
1445
1500
|
|
|
1446
1501
|
**Confirmation.** A run this session started (through `CreateWorkflow`, a previous
|
|
1447
1502
|
`AmendWorkflow` or the workflows hub) is amended without a confirmation window, even while
|
|
@@ -1454,9 +1509,8 @@ settles. Do not wait for it or poll it with `TaskOutput`.
|
|
|
1454
1509
|
|
|
1455
1510
|
Saves a script with its metadata so it can be run again by name — through `CreateWorkflow`'s
|
|
1456
1511
|
`saved` source, discovered with `ListSavedWorkflows`. Project definitions go in
|
|
1457
|
-
`.dcode/workflows/<name>.dwf.ts`, committed with the repository
|
|
1458
|
-
|
|
1459
|
-
project on this machine.
|
|
1512
|
+
`.dcode/workflows/<name>.dwf.ts`, committed with the repository; global definitions go in
|
|
1513
|
+
`~/.dcode/workflows/<name>.dwf.ts` and are available from every project on this machine.
|
|
1460
1514
|
|
|
1461
1515
|
**When to call it.**
|
|
1462
1516
|
|
|
@@ -1466,15 +1520,13 @@ project on this machine.
|
|
|
1466
1520
|
different inputs — suggest saving it in prose, one sentence naming what you would save and
|
|
1467
1521
|
why, then stop and wait. Call `SaveWorkflow` only after the user agrees, or when the user
|
|
1468
1522
|
asks directly ("save this workflow", "保存这个工作流"). A one-off script tailored to a
|
|
1469
|
-
single question is not worth suggesting
|
|
1470
|
-
project.
|
|
1523
|
+
single question is not worth suggesting.
|
|
1471
1524
|
|
|
1472
1525
|
**Fields.**
|
|
1473
1526
|
|
|
1474
1527
|
- `name`: a file-safe identifier (letters, digits, dot, dash and underscore). Saving over an
|
|
1475
|
-
existing name replaces that workflow
|
|
1476
|
-
|
|
1477
|
-
variant.
|
|
1528
|
+
existing name replaces that workflow, and the confirmation says whether the file is new or
|
|
1529
|
+
an overwrite: reuse a name to update, pick a new one for a variant.
|
|
1478
1530
|
- `description` (required) and `whenToUse`: written for a reader who has not seen this
|
|
1479
1531
|
conversation. `description` shows up wherever the workflow is listed.
|
|
1480
1532
|
- `scope` (required, no default): `project` when the script references this repository's
|
|
@@ -1485,11 +1537,9 @@ project on this machine.
|
|
|
1485
1537
|
file is dropped, because the metadata comes from this call's fields. `script` is the body
|
|
1486
1538
|
only — no metadata block.
|
|
1487
1539
|
- `args`: name exactly the values that would change between runs — a PR number, a
|
|
1488
|
-
directory, a depth
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
`default`. Declared arguments are the workflow's calling convention; every future call is
|
|
1492
|
-
validated against them.
|
|
1540
|
+
directory, a depth. Each declaration gives a `type` (`string`, `number`,
|
|
1541
|
+
`boolean`, or `json` for anything else), and optionally a `description`, `required: true`
|
|
1542
|
+
and a `default`; every future call is validated against them.
|
|
1493
1543
|
|
|
1494
1544
|
The saved file is valid TypeScript: a `/* dcode-workflow` block of YAML metadata, then the
|
|
1495
1545
|
script verbatim. The script is typechecked by the same compiler as `CreateWorkflow`, before
|
|
@@ -1501,20 +1551,43 @@ get.
|
|
|
1501
1551
|
|
|
1502
1552
|
Compiles and runs a small snippet synchronously against the same compiler, sandbox and
|
|
1503
1553
|
world-read execution path a real run uses, and returns the result in the tool call. Nothing
|
|
1504
|
-
persists: no journal rows, no background task, no run. It is the test bench for
|
|
1505
|
-
|
|
1506
|
-
what a glob actually returns (workspace-relative sorted paths, cap rejections), or exercise a
|
|
1507
|
-
gate predicate on real repository state, instead of guessing. It is not for orchestration:
|
|
1508
|
-
there is no `agent()` here.
|
|
1554
|
+
persists: no journal rows, no background task, no run. It is the test bench of §6, for the
|
|
1555
|
+
fixed logic of a script or of a hole's body; it is not for orchestration.
|
|
1509
1556
|
|
|
1510
1557
|
- `code` or `path`, never both: the snippet inline, or a file holding it, read whole with no
|
|
1511
1558
|
metadata handling.
|
|
1512
1559
|
- `timeoutMs`: the wall clock for the whole snippet in milliseconds; default 60000, at most
|
|
1513
1560
|
600000.
|
|
1514
|
-
- The snippet facade is the `args`, `log`, `files`/`git
|
|
1515
|
-
in §16.2; `agent()`, `report()`, `artifact
|
|
1561
|
+
- The snippet facade is the `args`, `log`, `files`/`git`, `world.run`, `channel` and `future`
|
|
1562
|
+
parts of the block in §16.2; `agent()`, `report()`, `artifact.*`, `hole()` and the `phase`
|
|
1563
|
+
marker are the only absentees — they do not exist here and
|
|
1516
1564
|
fail typechecking. The language rules are a script's: plain interfaces, top-level `await`, a
|
|
1517
1565
|
final `return <value>`. The returned value is serialized into the result, so return a
|
|
1518
1566
|
summary, not a dump; over 256KB fails the call. `log(...)` lines come back in order. A
|
|
1519
1567
|
snippet that contains `world.run` asks the user for confirmation before running. On
|
|
1520
1568
|
diagnostics nothing ran: fix the snippet and call again.
|
|
1569
|
+
|
|
1570
|
+
### 16.7 `FillWorkflowHole`
|
|
1571
|
+
|
|
1572
|
+
Writes the body of a hole a run is waiting at (§15). It starts nothing: the run keeps its id,
|
|
1573
|
+
journal and subagents, and the effective script — the run's script with the body spliced in —
|
|
1574
|
+
is what a resume replays, an amend revises and `SaveWorkflow` keeps.
|
|
1575
|
+
|
|
1576
|
+
- `run_id` and `hole_id` (required): from the notification or `GetWorkflowRun`; the hole id
|
|
1577
|
+
is the site id (`hole#21b40fca`), not the name.
|
|
1578
|
+
- `script` or `path`, never both: the body's statements only. An inline `script` is written to
|
|
1579
|
+
a fill file under `.dcode/workflow-drafts/` before it is compiled and the result names it;
|
|
1580
|
+
`path` is usually that file after an `Edit`, and bytes equal to the last rejected attempt
|
|
1581
|
+
are refused as `fill_unchanged`.
|
|
1582
|
+
|
|
1583
|
+
The body is compiled where the hole stands, against the whole script; a diagnostic is anchored
|
|
1584
|
+
to the file it falls in — the fill file inside the body, the run's draft outside it — and on
|
|
1585
|
+
diagnostics nothing is spliced. A body may name only the models the run was launched with; any
|
|
1586
|
+
other model is diagnostic 9011 — to add one, amend the run.
|
|
1587
|
+
`hole_not_waiting` means the run is not in flight or not
|
|
1588
|
+
waiting at that hole (filled, not yet reached, unknown id); resume a stopped run first and the
|
|
1589
|
+
hole asks again. A body may end in a new tail hole instead of returning (§15). On success the
|
|
1590
|
+
response names the phases added and the run's draft, rewritten in place with the effective
|
|
1591
|
+
script. Confirmation follows the amend rule (§16.4): this session's run fills without a
|
|
1592
|
+
window; otherwise the window shows the new stations and the `world.run` commands the body
|
|
1593
|
+
adds.
|