diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index e1fa82e..607d2c0 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -15,7 +15,7 @@ concurrency: cancel-in-progress: true env: - AGENTCTL_COMMIT: "f3181f93afac7546f01923491f77dabdf26b5ace" + AGENTCTL_COMMIT: "736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47" NODE_VERSION: "24.4.1" PNPM_VERSION: "11.9.0" RUST_TOOLCHAIN: "1.88.0" @@ -31,6 +31,8 @@ jobs: - name: Check out Pages source uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + persist-credentials: false path: site - name: Check out canonical agentctl source @@ -38,6 +40,7 @@ jobs: with: repository: opensourceops/agentctl ref: ${{ env.AGENTCTL_COMMIT }} + persist-credentials: false path: agentctl - name: Install pinned Node.js @@ -63,6 +66,20 @@ jobs: AGENTCTL_REPO: ${{ github.workspace }}/agentctl run: pnpm verify:agentctl + - name: Upload validated pull-request artifact + if: github.event_name == 'pull_request' + id: validation_artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agentctl-pages-validation + path: site/_site + if-no-files-found: error + retention-days: 14 + + - name: Record validation artifact digest + if: github.event_name == 'pull_request' + run: echo "agentctl-pages-validation artifact digest ${{ steps.validation_artifact.outputs.artifact-digest }}" >> "$GITHUB_STEP_SUMMARY" + - name: Configure GitHub Pages if: github.event_name != 'pull_request' uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 diff --git a/astro.config.mjs b/astro.config.mjs index 9e14c58..1717fbe 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -59,6 +59,7 @@ export default defineConfig({ { slug: 'overview', label: 'Overview', badge: 'v1alpha1' }, { slug: 'why-agentctl', label: 'Why agentctl' }, { slug: 'concepts/product', label: 'Product definition' }, + { slug: 'concepts/framework-completeness', label: 'Framework completeness' }, { slug: 'getting-started/installation', label: 'Installation' }, { slug: 'getting-started', label: 'Getting started' }, { slug: 'getting-started/first-agent', label: 'First agent workflow' }, @@ -82,6 +83,7 @@ export default defineConfig({ items: [ { slug: 'guides/local-operation', label: 'Local operation' }, { slug: 'durable-execution', label: 'Resume, replay, retry, and fork' }, + { slug: 'guides/selective-repair', label: 'Repair a failed workflow' }, { slug: 'operations/scheduled', label: 'Scheduled execution' }, ], }, @@ -123,6 +125,7 @@ export default defineConfig({ { slug: 'examples/ci-quality-gate', label: 'CI quality gate' }, { slug: 'examples/approval-gated', label: 'Approval-gated action' }, { slug: 'examples/recorded-replay', label: 'Recorded replay' }, + { slug: 'guides/selective-repair', label: 'Selective workflow repair' }, { slug: 'examples/provider-portability', label: 'Provider portability' }, ], }, @@ -143,6 +146,9 @@ export default defineConfig({ { slug: 'reference/compatibility', label: 'Compatibility' }, { slug: 'reference/migration', label: 'Migrate from TypeScript' }, { slug: 'reference/limitations', label: 'Limitations' }, + { slug: 'reference/limitation-burndown', label: 'Limitation burn-down' }, + { slug: 'reference/completeness-verification', label: 'Completeness verification' }, + { slug: 'reference/live-framework-verification', label: 'Live framework verification' }, ], }, { diff --git a/cspell.json b/cspell.json index 9ce23c0..471eb05 100644 --- a/cspell.json +++ b/cspell.json @@ -20,6 +20,11 @@ "effectful", "exfiltration", "inspectable", "ledgered", "lockfiles", "misexecutes", "msvc", "noninteractive", "nonroot", "oneshot", "proptest", "rustdoc", "sandboxing", "schedulable", "Streamable", "subpaths", "TOCTOU", "transactionally", "uncheckpointed", - "unpushed", "xtask", "MSRV", "nojekyll", "accDescr" + "unpushed", "xtask", "MSRV", "nojekyll", "accDescr", "backpressure", "bubblewrap", + "hardlinks", "Microusd", "Millis", "networkless", "pids", "preflighted", "redispatch", + "redispatched", "replayable", "Sigstore", "subworkflows", "Unreviewed", "workstreams", + "zeroizing", "nonterminal", "Kolkata", "libkrun", "gvproxy", "Workstream", + "undispatched", "XPLAT", "roundtrips", "keylessly", "unallowlisted", "embedder", + "reindexing", "zeroization", "BURNDOWN" ] } diff --git a/public/downloads/workflow.schema.json b/public/downloads/workflow.schema.json index de827ef..329459d 100644 --- a/public/downloads/workflow.schema.json +++ b/public/downloads/workflow.schema.json @@ -95,6 +95,20 @@ }, "default": {} }, + "subworkflows": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/SubworkflowDefinition" + }, + "default": {} + }, + "compensation": { + "$ref": "#/$defs/CompensationPolicyDefinition", + "default": { + "onFailure": "manual", + "approval": "policy" + } + }, "tasks": { "type": "array", "items": { @@ -108,7 +122,20 @@ "writableRoots": [], "environmentAllowlist": [], "networkAllowlist": [], + "network": { + "allowedSchemes": [ + "https", + "http" + ], + "allowedPorts": [], + "allowPrivate": false, + "allowProxy": false, + "connectTimeoutSeconds": 10, + "maxResponseBytes": 8388608 + }, "processAllowlist": [], + "secretFileRoots": [], + "secretProcessAllowlist": [], "providers": [], "toolsAllow": [], "toolsDeny": [], @@ -143,11 +170,20 @@ }, "default": [] }, + "packTrust": { + "$ref": "#/$defs/PackTrustDefinition", + "default": { + "unsigned": "warn", + "identities": [], + "allowUnsignedProcess": false + } + }, "runtime": { "$ref": "#/$defs/RuntimeDefinition", "default": { "maxConcurrency": 1, - "defaultTimeoutSeconds": 120 + "defaultTimeoutSeconds": 120, + "budgets": {} } }, "output": { @@ -215,15 +251,74 @@ ] }, "SecretReference": { + "anyOf": [ + { + "type": "object", + "properties": { + "env": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "env" + ] + }, + { + "type": "object", + "properties": { + "file": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "file" + ] + }, + { + "type": "object", + "properties": { + "process": { + "$ref": "#/$defs/SecretProcessReference" + } + }, + "additionalProperties": false, + "required": [ + "process" + ] + } + ] + }, + "SecretProcessReference": { "type": "object", "properties": { - "env": { + "command": { "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "timeoutSeconds": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 5 + }, + "outputLimitBytes": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 16384 } }, "additionalProperties": false, "required": [ - "env" + "command" ] }, "AgentDefinition": { @@ -319,6 +414,10 @@ } ] }, + "stream": { + "type": "boolean", + "default": false + }, "providerOptions": { "type": "object", "additionalProperties": true, @@ -425,6 +524,16 @@ "additionalProperties": true, "default": {} }, + "idempotency": { + "anyOf": [ + { + "$ref": "#/$defs/Idempotency" + }, + { + "type": "null" + } + ] + }, "command": { "type": [ "string", @@ -483,6 +592,34 @@ ], "format": "uint64", "minimum": 0 + }, + "isolation": { + "$ref": "#/$defs/ProcessIsolation" + }, + "container": { + "anyOf": [ + { + "$ref": "#/$defs/ContainerIsolationDefinition" + }, + { + "type": "null" + } + ] + }, + "protocolVersion": { + "type": [ + "string", + "null" + ] + }, + "inputSchema": true, + "outputSchema": true, + "capabilities": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] } }, "additionalProperties": false, @@ -498,14 +635,76 @@ "builtin.read", "builtin.write", "builtin.shell.exec", + "extension.process", "builtin.memory.read", "builtin.memory.write", "builtin.long_term_memory.read", + "builtin.long_term_memory.search", "builtin.long_term_memory.write", + "builtin.long_term_memory.promote", "mcp.call", "a2a.delegate" ] }, + "Idempotency": { + "type": "string", + "enum": [ + "pure", + "idempotent", + "keyed", + "at_most_once", + "unknown" + ] + }, + "ProcessIsolation": { + "type": "string", + "enum": [ + "process", + "container" + ] + }, + "ContainerIsolationDefinition": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "runtime": { + "$ref": "#/$defs/ContainerRuntime", + "default": "auto" + }, + "memoryLimitBytes": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 268435456 + }, + "cpuLimitMillis": { + "type": "integer", + "format": "uint32", + "minimum": 0, + "default": 1000 + }, + "pidsLimit": { + "type": "integer", + "format": "uint32", + "minimum": 0, + "default": 64 + } + }, + "additionalProperties": false, + "required": [ + "image" + ] + }, + "ContainerRuntime": { + "type": "string", + "enum": [ + "auto", + "docker", + "podman" + ] + }, "ToolDefinition": { "type": "object", "properties": { @@ -554,12 +753,6 @@ "approval": { "$ref": "#/$defs/ApprovalRequirement", "default": "policy" - }, - "compensation": { - "type": [ - "string", - "null" - ] } }, "additionalProperties": false, @@ -607,16 +800,6 @@ "remote_agent" ] }, - "Idempotency": { - "type": "string", - "enum": [ - "pure", - "idempotent", - "keyed", - "at_most_once", - "unknown" - ] - }, "ApprovalRequirement": { "type": "string", "enum": [ @@ -625,6 +808,39 @@ "always" ] }, + "SubworkflowDefinition": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "inputs": { + "type": "object", + "additionalProperties": true, + "default": {} + }, + "inputSchema": true, + "outputs": { + "type": "object", + "additionalProperties": true, + "default": {} + }, + "outputSchema": true, + "tasks": { + "type": "array", + "items": { + "$ref": "#/$defs/TaskDefinition" + } + } + }, + "additionalProperties": false, + "required": [ + "version", + "inputSchema", + "outputSchema", + "tasks" + ] + }, "TaskDefinition": { "type": "object", "properties": { @@ -641,6 +857,52 @@ }, "default": [] }, + "foreach": { + "anyOf": [ + { + "$ref": "#/$defs/ForeachDefinition" + }, + { + "type": "null" + } + ] + }, + "matrix": { + "anyOf": [ + { + "$ref": "#/$defs/MatrixDefinition" + }, + { + "type": "null" + } + ] + }, + "route": { + "anyOf": [ + { + "$ref": "#/$defs/RouteDefinition" + }, + { + "type": "null" + } + ] + }, + "loop": { + "anyOf": [ + { + "$ref": "#/$defs/LoopDefinition" + }, + { + "type": "null" + } + ] + }, + "memoryWrites": { + "type": "array", + "items": { + "type": "string" + } + }, "when": { "type": [ "string", @@ -677,7 +939,18 @@ "failure": { "$ref": "#/$defs/FailureBehavior", "default": "stop" - } + }, + "compensate": { + "anyOf": [ + { + "$ref": "#/$defs/CompensationDefinition" + }, + { + "type": "null" + } + ] + }, + "outputSchema": true }, "additionalProperties": false, "required": [ @@ -685,47 +958,238 @@ "uses" ] }, - "FailureBehavior": { - "type": "string", - "enum": [ - "stop", - "continue" - ] - }, - "PolicyDefinition": { + "ForeachDefinition": { "type": "object", "properties": { - "workspaceRoot": { - "type": "string", - "default": "." - }, - "writableRoots": { + "items": { "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "environmentAllowlist": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] + "items": true }, - "networkAllowlist": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] + "as": { + "type": "string", + "default": "item" }, - "processAllowlist": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] + "maxItems": { + "type": "integer", + "format": "uint", + "minimum": 0, + "default": 32 + } + }, + "additionalProperties": false, + "required": [ + "items" + ] + }, + "MatrixDefinition": { + "type": "object", + "properties": { + "axes": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": true + } + }, + "maxItems": { + "type": "integer", + "format": "uint", + "minimum": 0, + "default": 32 + } + }, + "additionalProperties": false, + "required": [ + "axes" + ] + }, + "RouteDefinition": { + "type": "object", + "properties": { + "select": { + "type": "string" + }, + "cases": { + "type": "array", + "items": { + "$ref": "#/$defs/RouteCaseDefinition" + } + }, + "default": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + } + }, + "additionalProperties": false, + "required": [ + "select", + "cases" + ] + }, + "RouteCaseDefinition": { + "type": "object", + "properties": { + "equals": true, + "tasks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "equals", + "tasks" + ] + }, + "LoopDefinition": { + "type": "object", + "properties": { + "maxIterations": { + "type": "integer", + "format": "uint", + "minimum": 0 + }, + "while": { + "type": "string" + }, + "initial": { + "default": null + } + }, + "additionalProperties": false, + "required": [ + "maxIterations", + "while" + ] + }, + "FailureBehavior": { + "type": "string", + "enum": [ + "stop", + "continue" + ] + }, + "CompensationDefinition": { + "type": "object", + "properties": { + "uses": { + "type": "string" + }, + "with": { + "type": "object", + "additionalProperties": true, + "default": {} + }, + "retry": { + "$ref": "#/$defs/RetryDefinition", + "default": { + "maxAttempts": 1, + "backoffMs": 0 + } + }, + "timeoutSeconds": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0, + "default": null + } + }, + "additionalProperties": false, + "required": [ + "uses" + ] + }, + "CompensationPolicyDefinition": { + "type": "object", + "properties": { + "onFailure": { + "$ref": "#/$defs/CompensationTrigger", + "default": "manual" + }, + "approval": { + "$ref": "#/$defs/ApprovalRequirement", + "default": "policy" + } + }, + "additionalProperties": false + }, + "CompensationTrigger": { + "type": "string", + "enum": [ + "manual", + "automatic" + ] + }, + "PolicyDefinition": { + "type": "object", + "properties": { + "workspaceRoot": { + "type": "string", + "default": "." + }, + "writableRoots": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "environmentAllowlist": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "networkAllowlist": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "network": { + "$ref": "#/$defs/NetworkPolicyDefinition", + "default": { + "allowedSchemes": [ + "https", + "http" + ], + "allowedPorts": [], + "allowPrivate": false, + "allowProxy": false, + "connectTimeoutSeconds": 10, + "maxResponseBytes": 8388608 + } + }, + "processAllowlist": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "secretFileRoots": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "secretProcessAllowlist": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] }, "providers": { "type": "array", @@ -759,6 +1223,62 @@ }, "additionalProperties": false }, + "NetworkPolicyDefinition": { + "type": "object", + "properties": { + "allowedSchemes": { + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "https", + "http" + ] + }, + "allowedPorts": { + "type": "array", + "items": { + "type": "integer", + "format": "uint16", + "minimum": 0, + "maximum": 65535 + }, + "default": [] + }, + "allowPrivate": { + "type": "boolean", + "default": false + }, + "allowProxy": { + "type": "boolean", + "default": false + }, + "customCa": { + "anyOf": [ + { + "$ref": "#/$defs/SecretReference" + }, + { + "type": "null" + } + ] + }, + "connectTimeoutSeconds": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 10 + }, + "maxResponseBytes": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 8388608 + } + }, + "additionalProperties": false + }, "ApprovalMode": { "type": "string", "enum": [ @@ -815,6 +1335,36 @@ ], "format": "uint32", "minimum": 0 + }, + "embedding": { + "$ref": "#/$defs/MemoryEmbeddingDefinition", + "default": { + "provider": "local_hash", + "dimensions": 64 + } + } + }, + "additionalProperties": false + }, + "MemoryEmbeddingDefinition": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "default": "local_hash" + }, + "model": { + "type": [ + "string", + "null" + ] + }, + "dimensions": { + "type": "integer", + "format": "uint16", + "minimum": 0, + "maximum": 65535, + "default": 64 } }, "additionalProperties": false @@ -867,6 +1417,18 @@ "minimum": 0, "default": 120 }, + "maxPolls": { + "type": "integer", + "format": "uint", + "minimum": 0, + "default": 100 + }, + "pollIntervalMs": { + "type": "integer", + "format": "uint64", + "minimum": 0, + "default": 100 + }, "protocolVersion": { "type": "string", "default": "1.0" @@ -886,19 +1448,164 @@ "version": { "type": "string" }, + "source": { + "anyOf": [ + { + "$ref": "#/$defs/PackSource" + }, + { + "type": "null" + } + ] + }, + "signature": { + "anyOf": [ + { + "$ref": "#/$defs/PackSignature" + }, + { + "type": "null" + } + ] + }, "path": { - "type": "string" + "type": [ + "string", + "null" + ] }, "integrity": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, "required": [ "name", - "version", - "path", - "integrity" + "version" + ] + }, + "PackSource": { + "anyOf": [ + { + "type": "object", + "properties": { + "path": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "path" + ] + }, + { + "type": "object", + "properties": { + "git": { + "type": "string" + }, + "rev": { + "type": "string" + }, + "manifest": { + "type": "string", + "default": "agentctl.pack.yaml" + } + }, + "additionalProperties": false, + "required": [ + "git", + "rev" + ] + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "integrity": { + "type": "string" + }, + "manifest": { + "type": "string", + "default": "agentctl.pack.yaml" + } + }, + "additionalProperties": false, + "required": [ + "url", + "integrity" + ] + } + ] + }, + "PackSignature": { + "type": "object", + "properties": { + "bundle": { + "type": "string" + }, + "identity": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "bundle", + "identity", + "issuer" + ] + }, + "PackTrustDefinition": { + "type": "object", + "properties": { + "unsigned": { + "$ref": "#/$defs/UnsignedPackPolicy", + "default": "warn" + }, + "identities": { + "type": "array", + "items": { + "$ref": "#/$defs/PackIdentity" + }, + "default": [] + }, + "allowUnsignedProcess": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false + }, + "UnsignedPackPolicy": { + "type": "string", + "enum": [ + "deny", + "warn", + "allow" + ] + }, + "PackIdentity": { + "type": "object", + "properties": { + "identity": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "identity", + "issuer" ] }, "RuntimeDefinition": { @@ -915,10 +1622,197 @@ "format": "uint64", "minimum": 0, "default": 120 + }, + "budgets": { + "$ref": "#/$defs/ResourceBudgetDefinition", + "default": {} + }, + "pricing": { + "anyOf": [ + { + "$ref": "#/$defs/PricingDefinition" + }, + { + "type": "null" + } + ] } }, "additionalProperties": false }, + "ResourceBudgetDefinition": { + "type": "object", + "properties": { + "maxProviderRequests": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxTurns": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxToolCalls": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxInputTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxOutputTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxTotalTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxWallTimeSeconds": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxProcessOutputBytes": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxArtifactBytes": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxTasks": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxExpansionItems": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxLoopIterations": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "maxCostMicrousd": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + } + }, + "additionalProperties": false + }, + "PricingDefinition": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "models": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/ModelPricingDefinition" + } + } + }, + "additionalProperties": false, + "required": [ + "version", + "models" + ] + }, + "ModelPricingDefinition": { + "type": "object", + "properties": { + "inputMicrousdPerMillionTokens": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "outputMicrousdPerMillionTokens": { + "type": "integer", + "format": "uint64", + "minimum": 0 + }, + "reasoningMicrousdPerMillionTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "cacheReadMicrousdPerMillionTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + }, + "cacheWriteMicrousdPerMillionTokens": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0 + } + }, + "additionalProperties": false, + "required": [ + "inputMicrousdPerMillionTokens", + "outputMicrousdPerMillionTokens" + ] + }, "OutputDefinition": { "type": "object", "properties": { diff --git a/public/meta/agentctl-source.json b/public/meta/agentctl-source.json index 2bb63aa..eb3f9d8 100644 --- a/public/meta/agentctl-source.json +++ b/public/meta/agentctl-source.json @@ -2,8 +2,8 @@ "product": "agentctl", "version": "0.2.0", "workflowApi": "agentctl.dev/v1alpha1", - "commit": "f3181f93afac7546f01923491f77dabdf26b5ace", + "commit": "736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47", "dirty": false, "sourceRepository": "https://github.com/opensourceops/agentctl", - "importedFiles": 56 + "importedFiles": 61 } diff --git a/scripts/check-workflow.mjs b/scripts/check-workflow.mjs index 4cd3da7..b346b30 100644 --- a/scripts/check-workflow.mjs +++ b/scripts/check-workflow.mjs @@ -4,18 +4,35 @@ import { fileURLToPath } from 'node:url'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const workflow = await readFile(path.join(root, '.github/workflows/pages.yml'), 'utf8'); +const source = JSON.parse(await readFile(path.join(root, 'src/data/agentctl-source.json'), 'utf8')); const errors = []; const actions = [...workflow.matchAll(/^\s*uses:\s*([^@\s]+)@([^\s#]+)(?:\s+#\s+(.+))?$/gm)]; -if (actions.length !== 6) errors.push(`expected 6 action references, found ${actions.length}`); +if (actions.length !== 7) errors.push(`expected 7 action references, found ${actions.length}`); for (const [, action, revision, comment] of actions) { if (!/^[0-9a-f]{40}$/.test(revision)) errors.push(`${action} is not pinned to a full commit SHA`); if (!/^v\d/.test(comment || '')) errors.push(`${action} has no release comment`); } +const pinnedCommit = workflow.match(/^\s*AGENTCTL_COMMIT:\s*"([0-9a-f]{40})"\s*$/m)?.[1]; +if (!pinnedCommit) { + errors.push('AGENTCTL_COMMIT must be pinned to a full commit SHA'); +} else if (pinnedCommit !== source.commit) { + errors.push(`AGENTCTL_COMMIT ${pinnedCommit} does not match synchronized source ${source.commit}`); +} +if (!workflow.includes('ref: ${{ github.event.pull_request.head.sha || github.sha }}')) { + errors.push('Pages source checkout must select the exact pull-request head or event revision'); +} +if ((workflow.match(/persist-credentials: false/g) || []).length !== 2) { + errors.push('both repository checkouts must disable credential persistence'); +} + for (const required of [ 'repository: opensourceops/agentctl', + "if: github.event_name == 'pull_request'", "if: github.event_name != 'pull_request'", + 'name: agentctl-pages-validation', + 'if-no-files-found: error', 'pages: write', 'id-token: write', 'path: site/_site', diff --git a/scripts/content-manifest.mjs b/scripts/content-manifest.mjs index b917ed4..703cf6b 100644 --- a/scripts/content-manifest.mjs +++ b/scripts/content-manifest.mjs @@ -1,5 +1,6 @@ export const contentManifest = [ ['docs/PRODUCT.md', '_generated/concepts/product.md', 'Product definition', 'What agentctl does, who it serves, and where its boundary ends.'], + ['docs/execution/FRAMEWORK_COMPLETENESS.md', '_generated/concepts/framework-completeness.md', 'Framework completeness', 'The implemented deterministic workflow surface and explicit product boundaries.'], ['docs/DSL.md', '_generated/concepts/workflow-model.md', 'Workflow model', 'Strict YAML, tasks, templates, actions, agents, and validation.'], ['docs/policies.md', '_generated/concepts/policies.md', 'Policies and approvals', 'Keep authority outside the model with explicit grants and durable decisions.'], ['docs/TOOLS.md', '_generated/concepts/tools.md', 'Tools and effects', 'Tool contracts, effect classes, idempotency, and deterministic checks.'], @@ -10,6 +11,7 @@ export const contentManifest = [ ['docs/guides/FIRST_AGENT_WORKFLOW.md', '_generated/getting-started/first-agent.md', 'First agent workflow', 'Run a bounded tool-using agent without a paid API key.'], ['docs/guides/WORKFLOW_AUTHORING.md', '_generated/guides/workflow-authoring.md', 'Author workflows', 'Learn workflow YAML in execution order.'], ['docs/guides/LOCAL_OPERATION.md', '_generated/guides/local-operation.md', 'Local operation', 'Manage paths, state, outputs, interruption, recovery, and retention.'], + ['docs/guides/repair-a-failed-workflow.md', '_generated/guides/selective-repair.md', 'Repair a failed workflow', 'Reuse compatible upstream results and safely execute a corrected suffix.'], ['docs/guides/CI_CD.md', '_generated/guides/ci-cd.md', 'CI/CD integration', 'Use the generic OCI contract in pipelines and Kubernetes.'], ['docs/CONTAINER.md', '_generated/guides/container.md', 'Container guide', 'Run the non-root, read-only OCI image with durable mounts.'], ['docs/OPERATIONS.md', '_generated/operations/scheduled.md', 'Scheduled execution', 'Use cron, systemd, or Kubernetes as the external scheduler.'], @@ -35,8 +37,11 @@ export const contentManifest = [ ['docs/reference/MATRICES.md', '_generated/reference/capabilities.md', 'Capability matrices', 'Provider and tool capabilities with exact evidence levels.'], ['docs/reference/DATABASE.md', '_generated/reference/database.md', 'Database and migrations', 'SQLite records, schema migration, locking, backup, and retention.'], ['docs/reference/TERMINOLOGY.md', '_generated/reference/terminology.md', 'Terminology', 'Use workflow, task, effect, resume, replay, retry, and fork precisely.'], - ['docs/LIMITATIONS.md', '_generated/reference/limitations.md', 'Limitations', 'Current release boundary, deferred work, and non-goals.'], - ['docs/COMPATIBILITY.md', '_generated/reference/compatibility.md', 'Compatibility', 'Preserved, migrated, changed, removed, and deferred contracts.'], + ['docs/LIMITATIONS.md', '_generated/reference/limitations.md', 'Limitations', 'Current supported boundary, operational limits, and non-goals.'], + ['docs/execution/LIMITATION_BURNDOWN.md', '_generated/reference/limitation-burndown.md', 'Limitation burn-down', 'Authoritative disposition of every identified framework limitation.'], + ['docs/execution/COMPLETENESS_VERIFICATION.md', '_generated/reference/completeness-verification.md', 'Completeness verification', 'Deterministic, container, security, and independent review evidence.'], + ['docs/execution/LIVE_FRAMEWORK_VERIFICATION.md', '_generated/reference/live-framework-verification.md', 'Live framework verification', 'Sanitized GPT-5.6 scenario, recovery, replay, usage, and container evidence.'], + ['docs/COMPATIBILITY.md', '_generated/reference/compatibility.md', 'Compatibility', 'Preserved, migrated, changed, removed, and explicit non-goal contracts.'], ['docs/MIGRATING_FROM_TYPESCRIPT.md', '_generated/reference/migration.md', 'Migrate from TypeScript', 'Translate supported legacy workflows to strict v1alpha1 YAML.'], ['docs/ARCHITECTURE.md', '_generated/architecture/index.md', 'Architecture overview', 'Crate boundaries, execution, determinism, concurrency, and packaging.'], ['docs/architecture/DIAGRAMS.md', '_generated/architecture/diagrams.md', 'Architecture diagrams', 'Fourteen verified diagrams for compilation, state, effects, recovery, deployment, and crates.'], diff --git a/src/components/Homepage.astro b/src/components/Homepage.astro index 9baf707..8ecf114 100644 --- a/src/components/Homepage.astro +++ b/src/components/Homepage.astro @@ -108,6 +108,7 @@ const shortCommit = source.commit.slice(0, 8); Scheduled reviewPersist a bounded run invoked by cron or Kubernetes. CI quality gateReturn stable JSON and process status to a pipeline. Approval-gated actionPause a proposed mutation for operator review. + Selective repairReuse compatible upstream results and execute a corrected suffix. Offline replayReconstruct a terminal run without network or credentials. @@ -163,18 +164,19 @@ const shortCommit = source.commit.slice(0, 8);

Current maturity

-

Production-oriented alpha, preparing for hosted RC validation

+

Exact-commit evidence across local and hosted gates

- The workflow API is agentctl.dev/v1alpha1. The deterministic core, fake provider, - local persistence, and credential-free journeys have executable evidence. Native providers and - protocols have mock coverage at documented levels. Hosted multi-platform workflows are configured, - but the current candidate has not completed those remote runs. + The workflow API is agentctl.dev/v1alpha1. Deterministic composition, durable recovery, + local persistence, native Linux arm64 containers, and bounded GPT-5.6 journeys have executable evidence. + The pinned candidate also passed hosted Linux x64, macOS arm64, Windows x64, container, security, + package, SBOM, and release-preparation gates. Other native providers and protocols have mock coverage + at documented levels.

diff --git a/src/content/docs/_generated/architecture/decisions/0001.md b/src/content/docs/_generated/architecture/decisions/0001.md index e6273eb..31e9815 100644 --- a/src/content/docs/_generated/architecture/decisions/0001.md +++ b/src/content/docs/_generated/architecture/decisions/0001.md @@ -8,4 +8,4 @@ Status: accepted, 2026-07-22. The graph, policy, state machine, persistence decisions, and recorded replay remain model-independent. Provider, tool, filesystem, process, MCP, A2A, internal-state mutation, clock, and ID behavior cross injected interfaces and receive durable effect identity when externally observable. This keeps models replaceable and tests credential-free. It requires more records and conservative uncertain states, but avoids hidden calls during replay. Dynamic model-owned orchestration is rejected. -> Canonical source: [`docs/adr/0001-deterministic-core-explicit-effects.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0001-deterministic-core-explicit-effects.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0001-deterministic-core-explicit-effects.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0001-deterministic-core-explicit-effects.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0002.md b/src/content/docs/_generated/architecture/decisions/0002.md index a9f4a4c..fc53244 100644 --- a/src/content/docs/_generated/architecture/decisions/0002.md +++ b/src/content/docs/_generated/architecture/decisions/0002.md @@ -8,4 +8,4 @@ Status: accepted, 2026-07-22. Workflows use `apiVersion`, `kind`, `metadata`, and `spec`. The envelope is adopted because identity/version and evolution need unambiguous locations, not because another system uses it. All typed objects deny unknown fields and a generated JSON Schema is checked in. A narrow legacy translator provides actionable migration. General aliases and silent coercion are rejected because they make security review and durable reproduction ambiguous. -> Canonical source: [`docs/adr/0002-versioned-strict-workflow-envelope.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0002-versioned-strict-workflow-envelope.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0002-versioned-strict-workflow-envelope.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0002-versioned-strict-workflow-envelope.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0003.md b/src/content/docs/_generated/architecture/decisions/0003.md index 41bb64a..998227f 100644 --- a/src/content/docs/_generated/architecture/decisions/0003.md +++ b/src/content/docs/_generated/architecture/decisions/0003.md @@ -8,4 +8,4 @@ Status: accepted, 2026-07-22. One versioned SQLite database is the local correctness store. Transactional task transitions/checkpoints/audits and a request-before-start effect ledger support resume and no-effect replay. Confirmed results are reused; started unconfirmed work becomes uncertain. No exactly-once claim is made. Automatic retry of ambiguous external effects is rejected. Fork is the explicit operation for fresh effects. Distributed history services are outside this release. -> Canonical source: [`docs/adr/0003-sqlite-history-and-conservative-recovery.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0003-sqlite-history-and-conservative-recovery.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0003-sqlite-history-and-conservative-recovery.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0003-sqlite-history-and-conservative-recovery.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0004.md b/src/content/docs/_generated/architecture/decisions/0004.md index 6e682cf..5bd3da9 100644 --- a/src/content/docs/_generated/architecture/decisions/0004.md +++ b/src/content/docs/_generated/architecture/decisions/0004.md @@ -8,4 +8,4 @@ Status: accepted, 2026-07-22. OpenAI Responses, Azure OpenAI Responses, Anthropic Messages, Google Gemini generateContent, and a scripted fake implement one provider-neutral internal interface. Capabilities are negotiated before execution; provider SDK/HTTP shapes never enter durable core state. “OpenAI-compatible” shims are rejected as a support claim because they hide native tool, continuation, reasoning, error, and usage differences. Every provider requires mock protocol coverage; live credentials are optional evidence only. -> Canonical source: [`docs/adr/0004-native-provider-adapters.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0004-native-provider-adapters.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0004-native-provider-adapters.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0004-native-provider-adapters.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0005.md b/src/content/docs/_generated/architecture/decisions/0005.md index 81c501c..1c82840 100644 --- a/src/content/docs/_generated/architecture/decisions/0005.md +++ b/src/content/docs/_generated/architecture/decisions/0005.md @@ -3,9 +3,14 @@ title: "ADR 0005: Narrow v1 scheduling" description: "Keep scheduling sequential until merge and recovery semantics are defined." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/adr/0005-narrow-v1-scheduling-and-extensions.md" --- -Status: accepted, 2026-07-22. +Status: superseded for scheduling and control flow by ADRs 0008 through 0011, +2026-07-24. V1alpha1 schedules a sequential DAG in declaration order and integrates typed actions/tools, local packs, MCP 2025-11-25, and A2A 1.0. `maxConcurrency` greater than one is rejected. -Parallel groups, loops, routing, sub-workflows, teams/handoffs, automatic reconnection/resubmission, executable plugin ABIs, and registries are deferred. Each needs deterministic merge, cancellation, policy, version, and recovery semantics before it can enter the stable contract. -> Canonical source: [`docs/adr/0005-narrow-v1-scheduling-and-extensions.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0005-narrow-v1-scheduling-and-extensions.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +The original decision excluded parallel execution, loops, and routing until +their deterministic semantics existed. ADRs 0008, 0010, and 0011 now define +those contracts. Sub-workflows, teams/handoffs, automatic +reconnection/resubmission, executable plugin ABIs, and registries remain +separate product decisions. +> Canonical source: [`docs/adr/0005-narrow-v1-scheduling-and-extensions.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0005-narrow-v1-scheduling-and-extensions.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0006.md b/src/content/docs/_generated/architecture/decisions/0006.md index f73b009..4f9ab6c 100644 --- a/src/content/docs/_generated/architecture/decisions/0006.md +++ b/src/content/docs/_generated/architecture/decisions/0006.md @@ -11,9 +11,13 @@ Status: accepted Non-interactive execution never prompts or auto-approves. The default approval behavior persists the request, pauses the run, emits run/trace correlation, and exits `3`. An operator resolves the approval and invokes `resume`. `deny_approval` and `fail` are stricter explicit modes. -Machine output is one `agentctl.dev/cli/v1` final envelope. Inputs come from JSON, an input file, or repeated `KEY=VALUE` arguments; provider secrets remain environment references. Separate runs can share a SQLite database, but external schedulers must prevent overlapping effects when the target resource requires serialization. +Machine output is one `agentctl.dev/cli/v1` final envelope. Inputs come from +JSON, an input file, or repeated `KEY=VALUE` arguments; provider secrets remain +typed references rather than values. Separate runs can share a SQLite database, +but external schedulers must prevent overlapping effects when the target +resource requires serialization. ## Consequences Cron, systemd, Kubernetes, and CI can use normal process semantics without hidden terminal waits. The product avoids an eventing/distributed-control-plane surface. A future schedule-run key may improve deduplication, but it cannot replace external overlap controls or effect idempotency. -> Canonical source: [`docs/adr/0006-schedulable-runtime-and-noninteractive-contract.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0006-schedulable-runtime-and-noninteractive-contract.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0006-schedulable-runtime-and-noninteractive-contract.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0006-schedulable-runtime-and-noninteractive-contract.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/decisions/0007.md b/src/content/docs/_generated/architecture/decisions/0007.md index 27844ea..a2a3f58 100644 --- a/src/content/docs/_generated/architecture/decisions/0007.md +++ b/src/content/docs/_generated/architecture/decisions/0007.md @@ -14,4 +14,4 @@ The image entrypoint is `agentctl`. Callers supply ordinary CLI arguments and on ## Consequences No vendor-specific plugin API is required. Platforms without direct entrypoint/argument support can invoke `docker run` from their normal shell step. Distroless reduces runtime surface but deliberately has no shell; debugging uses the public CLI or a separate diagnostic image, not mutation of production images. -> Canonical source: [`docs/adr/0007-generic-oci-step-contract.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0007-generic-oci-step-contract.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/adr/0007-generic-oci-step-contract.md`](https://github.com/opensourceops/agentctl/blob/main/docs/adr/0007-generic-oci-step-contract.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/diagrams.md b/src/content/docs/_generated/architecture/diagrams.md index 89c41eb..fd2ed99 100644 --- a/src/content/docs/_generated/architecture/diagrams.md +++ b/src/content/docs/_generated/architecture/diagrams.md @@ -15,7 +15,7 @@ flowchart LR accDescr: A workflow author uses the CLI, which joins deterministic core contracts to runtime providers, protocols, executors, tracing, and SQLite. User[Workflow author or operator] --> CLI[agentctl CLI] CLI --> Core[Core parser compiler policy state] - CLI --> Runtime[Sequential runtime] + CLI --> Runtime[Bounded deterministic runtime] Runtime --> Store[SQLite store] Runtime --> Providers[Native model providers] Runtime --> Protocols[MCP and A2A clients] @@ -51,9 +51,9 @@ A normal run moves through durable states and ends in one terminal result or a d flowchart TD accTitle: Run lifecycle accDescr: A run creates durable records, executes ready tasks, persists results, and reaches success, approval, failure, or cancellation. - Create[Create run and task records] --> Ready[Find next ready task] - Ready --> Execute[Execute action or bounded agent] - Execute --> Persist[Commit task output checkpoint and audit] + Create[Create run and task records] --> Ready[Select stable ready batch] + Ready --> Execute[Execute independent tasks] + Execute --> Persist[Commit ordered batch checkpoint and audit] Persist --> More{More ready tasks?} More -->|Yes| Ready More -->|No| Success[Succeeded] @@ -61,7 +61,9 @@ flowchart TD Execute --> Failure[Failed or cancelled] ``` -The current scheduler runs one ready task at a time in declaration order. A pending approval is non-terminal and can later resume. +The scheduler selects up to `maxConcurrency` ready tasks in declaration order. +Every task reads a durable isolated snapshot. Results commit atomically in plan +order. A pending approval is non-terminal and can later resume. ## Runtime state machine @@ -146,6 +148,26 @@ flowchart LR Replay reports historical truth. It does not observe current files, rerun verification, or contact a provider. +## Selective repair flow + +Selective repair is a new source-linked run. It is distinct from both effect-free recorded replay and broad fresh fork execution. + +```mermaid +flowchart LR + accTitle: Selective repair flow + accDescr: Repair verifies successful upstream task boundaries, materializes compatible outputs and state, and executes selected roots and descendants from a target workflow. + Source[Terminal source run] --> Plan[Effect-free compatibility plan] + Target[Target workflow] --> Plan + Plan --> Reuse[Materialize compatible upstream tasks] + Plan --> Fresh[Execute roots and descendants] + Reuse --> Boundary[Reconstructed task-boundary state] + Boundary --> Fresh + Fresh --> Repair[New repair run and trace] + Source -. remains immutable .-> Repair +``` + +The detailed failed-run, plan, reuse, invalidation, lineage, and effect-safety diagrams are in [Repair a failed workflow](/agentctl/guides/selective-repair/). + ## Fork or rerun flow Fork makes fresh execution an explicit choice instead of overloading replay. @@ -291,4 +313,4 @@ flowchart TD ``` `agentctl-core` has no dependency on HTTP, SQLite, CLI parsing, or concrete executor types. `xtask` drives the built CLI for generation and acceptance. -> Canonical source: [`docs/architecture/DIAGRAMS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/architecture/DIAGRAMS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/architecture/DIAGRAMS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/architecture/DIAGRAMS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/architecture/index.md b/src/content/docs/_generated/architecture/index.md index e7198a4..9616f35 100644 --- a/src/content/docs/_generated/architecture/index.md +++ b/src/content/docs/_generated/architecture/index.md @@ -14,7 +14,7 @@ CLI ───────┬────────> runtime ─────> c runtime ────────────> observability ─> core contracts ``` -`agentctl-core` owns deterministic domain behavior: strict parsing, migration, compilation, template resolution, effect identities, state machines, policy, and provider/tool interfaces. It knows no HTTP client, database, or CLI type. `agentctl-store` is the SQLite implementation. `agentctl-runtime` schedules one stable ready task at a time and coordinates injected clocks, IDs, executors, providers, protocols, persistence, and traces. Concrete network adapters and rendering stay at the edges. +`agentctl-core` owns deterministic domain behavior: strict parsing, migration, compilation, template resolution, effect identities, state machines, policy, and provider/tool interfaces. It knows no HTTP client, database, or CLI type. `agentctl-store` is the SQLite implementation. `agentctl-runtime` schedules stable bounded ready batches and coordinates injected clocks, IDs, executors, providers, protocols, persistence, and traces. Concrete network adapters and rendering stay at the edges. ## Execution @@ -22,19 +22,60 @@ Parsing produces a versioned `Workflow`; compilation resolves references, valida An effect request is persisted before any filesystem observation/mutation, process, internal-memory update, long-term-memory operation, tool, model, MCP, or A2A call. Its stable identity covers run, task, task attempt, ordinal, operation, and input digest. A confirmed result can be reused on resume. A started but unconfirmed effect is uncertain and stops recovery rather than being repeated. -State transitions, checkpoint creation, working-memory replacement, and audit insertion are transactionally coupled where consistency requires it. Provider continuation, function-call correlation, effects, approvals, and redacted trace events are inspectable through the public CLI. Long-term memory is a separate table and never participates in replay correctness. OpenTelemetry export remains optional and is not the audit log. +State transitions, checkpoint creation, working-memory replacement, artifact references, and audit insertion are transactionally coupled where consistency requires it. A per-run SQLite budget ledger atomically coordinates parallel reservations before effect dispatch and actual-usage reconciliation afterward. Artifact bytes live in an immutable SHA-256 content-addressed store beside SQLite; durable leases and a cross-process lock coordinate ingestion with reachability GC. Provider continuation, function-call correlation, effects, approvals, artifacts, budgets, and redacted trace events are inspectable through the public CLI. Long-term memory is a separate table and never participates in replay correctness. OpenTelemetry export remains optional and is not the audit log. ## Determinism and concurrency -Ready tasks are ordered by YAML declaration order after dependencies. `maxConcurrency` currently must be `1`. Parallel execution, loops, matrix/foreach expansion, routers, sub-workflows, handlers, compensation execution, and event triggers are deferred because deterministic merge and recovery semantics are not yet frozen. The DSL carries optional compensation metadata on a tool contract, but the runtime does not execute compensation. +Ready tasks are ordered by YAML declaration order after dependencies. +`maxConcurrency` defaults to one and is bounded at 64. A parallel batch reads +per-task durable memory snapshots, executes independently, then commits +successful outputs, disjoint memory deltas, failures, artifact references, +audit events, and the checkpoint in compiled order in one transaction. +Unordered overlapping `memoryWrites` fail compilation. Effects and provider +sessions remain task-local. See ADR 0008 and +[Deterministic parallel tasks](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PARALLEL_TASKS.md). + +Static foreach lists and matrix axes compile into ordinary namespaced child +tasks followed by a pure aggregate. Their IDs, bindings, attempts, outputs, +and recovery lineage use the same durable task model as authored nodes. Typed +routers are pure tasks whose enumerated destination guards compile into the +graph; condition and route decisions are durable and replayable. Bounded loops +compile into sequential namespaced iteration tasks and a pure aggregate, so +iteration attempts, effects, guard decisions, retry, repair, and replay use the +ordinary durable task model. Reusable sub-workflows compile into a typed input +boundary, namespaced ordinary tasks, and a typed output aggregate. Their policy +and providers come from the invoking workflow, while deterministic memory keys +are invocation-prefixed. Explicit compensation plans eligible applied effects +in reverse graph order and executes ordinary actions in a separate +source-linked run. Confirmed inverse effects append immutable reconciliation +records to the source. Structured handoffs are typed deterministic tasks +between bounded agent tasks, so role collaboration retains ordinary task-local +provider sessions, effects, audit, retry, repair, and replay. Streaming +providers pass typed fragments through an awaited runtime sink that bounds and +persists each task-attempt event before consuming more transport data. Final +result validation remains unchanged. Handlers and event triggers remain +outside the runtime surface. Clock and identifier generation are injected. Provider responses, tools, and external actions are injected interfaces. Cryptographic digests canonicalize identity; output maps use stable ordering where the public contract requires it. ## Platform and packaging -The workspace uses Rust edition 2024, pins Rust 1.88 as the MSRV, forbids unsafe code, and denies clippy warnings. HTTP uses rustls and disables redirects. Subprocesses use direct argv, a cleared environment, explicit allowlists, validated timeout/output limits, concurrent bounded pipe draining, cancellation, and kill/reap cleanup. SQLite is bundled for predictable installation and creates private files on Unix. SIGINT and SIGTERM converge on durable cancellation. +The workspace uses Rust edition 2024, pins Rust 1.88 as the MSRV, forbids +unsafe code, and denies clippy warnings. HTTP uses rustls, ignores environment +proxies by default, disables redirects and Unix sockets, checks every resolved +address, and pins accepted direct DNS answers. Optional custom roots come only +from protected certificate-only PEM references. Host subprocesses use direct +argv, a cleared environment, explicit allowlists, validated timeout/output +limits, concurrent bounded pipe draining, cancellation, and kill/reap cleanup; +this `process` mode is not a sandbox. Explicit `container` actions use a local +digest-pinned Docker/Podman image with no pull/network, a read-only +root/workspace, a non-root identity, dropped capabilities, resource limits, +and fail-closed backend/image preflight. SQLite is bundled for predictable +installation and creates private files on Unix. SIGINT and SIGTERM converge on +durable cancellation. See [Process isolation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PROCESS_ISOLATION.md) and +ADR 0020. Run budget coordination is described by ADR 0021. -The OCI build is multi-stage: only the optimized Rust binary enters a maintained distroless runtime with CA roots and a non-root identity. `/config` is workflow configuration, `/workspace` is the read-only working tree, `/state` holds SQLite, and `/artifacts` receives declared outputs. State must be mounted again for inspect/resume/replay. The root filesystem may be read-only. See [Container contract](/agentctl/guides/container/) and ADR 0007. +The OCI build is multi-stage: only the optimized Rust binary enters a maintained distroless runtime with CA roots and a non-root identity. `/config` is workflow configuration, `/workspace` is the read-only working tree, `/state` holds SQLite and the content-addressed artifact store, and `/artifacts` receives declared workflow outputs. State must be mounted again for inspect/resume/replay/repair and artifact export. The root filesystem may be read-only. See [Container contract](/agentctl/guides/container/) and ADR 0007. See the [architecture diagrams](/agentctl/architecture/diagrams/), [ADRs](https://github.com/opensourceops/agentctl/blob/main/docs/adr/), and [Durable execution](/agentctl/durable-execution/) for failure semantics. -> Canonical source: [`docs/ARCHITECTURE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/ARCHITECTURE.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/ARCHITECTURE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/ARCHITECTURE.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/framework-completeness.md b/src/content/docs/_generated/concepts/framework-completeness.md new file mode 100644 index 0000000..9f45f61 --- /dev/null +++ b/src/content/docs/_generated/concepts/framework-completeness.md @@ -0,0 +1,146 @@ +--- +title: "Framework completeness" +description: "The implemented deterministic workflow surface and explicit product boundaries." +editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/execution/FRAMEWORK_COMPLETENESS.md" +--- +## Product contract + +`agentctl` is a deterministic and declarative runtime for durable agentic +workflows. The compiler, graph, state machine, effect ledger, policy, and +versioned persistence remain authoritative. Models execute bounded typed tasks; +they do not own orchestration. + +The complete supported surface contains: + +- strict versioned YAML, typed inputs/outputs, constrained templates, typed + conditions, and deterministic routing; +- sequential or bounded parallel DAG execution with stable commit order and + explicit working-memory conflict rules; +- bounded foreach/matrix expansion, bounded loops, and namespaced + sub-workflows; +- deterministic actions, bounded provider tasks, typed tools, structured + handoffs, explicit compensation, and durable streaming events; +- local SQLite history, authenticated encryption for selected sensitive fields, + content-addressed artifacts, checkpoints, audit, traces, and usage budgets; +- resume, operator reconciliation, terminal retry, selective repair, recorded + replay, and explicit effectful fork; +- native provider adapters behind a provider-neutral interface; +- resilient MCP and A2A clients that never duplicate uncertain mutation; +- local/Git/immutable-archive packs with deterministic locking and optional + established signature verification; +- reviewed packs, MCP, and a bounded process protocol as the extension model; +- exact, text, vector, and hybrid optional long-term-memory retrieval with + explicit promotion; +- environment, mounted-file, and policy-gated process secret references whose + values are never persisted; +- explicit network and process policies, honest isolation modes, and generic + non-root/read-only container execution; +- human, final JSON, JSONL progress, inspection, export, migration, and + administration commands; +- local, externally scheduled, CI, container, and embedded Rust operation. + +## Determinism rules + +1. Compilation fixes task identity, dependencies, expansion limits, schemas, + policies, budgets, and commit order. +2. Parallel tasks read an immutable boundary snapshot. Their durable commits + occur in compiled order. +3. Working-memory writes are declared. Conflicts fail before effect dispatch + unless a versioned deterministic merge is explicit. +4. Dynamic children and loop iterations receive stable IDs and hard bounds. +5. Every external observation or mutation has a persisted identity before + dispatch. +6. Uncertain mutating work is never silently repeated. +7. Provider sessions are task-local. Typed output, durable state, artifacts, + and explicit handoff payloads are the only cross-task dataflow. +8. Recorded replay dispatches no provider, tool, process, network, filesystem, + protocol, memory, or artifact-ingestion effect. + +## Persistence boundaries + +SQLite stores versioned metadata and encrypted sensitive fields. Artifact bytes +live in an immutable local content-addressed store rooted beside the database. +The database references blobs by digest and owns reachability and retention. +External artifact backends may implement the same interface later, but none is +required for the complete local product. + +The database and artifact root are backed up together. A repair or retry run +materializes its own metadata references so source-row garbage collection does +not break it. Blob garbage collection removes only unreferenced content outside +the configured retention window. + +## Recovery operations + +- `resume` continues a nonterminal run and reuses confirmed effects. +- `reconcile` records operator-confirmed external reality without mutating the + source effect. +- `retry` creates a new source-linked run for an identical workflow and reruns + failed or explicitly selected boundaries. +- `repair` creates a new source-linked run for a changed compatible workflow. +- `replay` reconstructs a terminal run and recorded stream without fresh + effects. +- `fork` creates a broad new execution with intentionally fresh effects. +- `compensate` performs explicitly declared best-effort reverse actions and + never claims transactional rollback. + +## Extension contract + +There is no in-process native plugin ABI. Extensions use one of: + +- reviewed declarative packs; +- MCP for remote tools; +- a versioned bounded process protocol for local executors. + +Each executable extension declares schemas, capabilities, effects, limits, and +policy requirements. Process and MCP execution remain isolated effect +boundaries. + +## Network contract + +Required provider and protocol URLs are preflighted before run persistence. +Policy fixes the HTTP(S) schemes, exact or wildcard hosts, effective ports, +private-network authority, proxy authority, optional custom CA reference, +DNS/connect bound, and response-byte ceiling. Direct destinations resolve +once, every IPv4 and IPv6 answer is authorized, and the accepted answer is +pinned into the client. Redirects and Unix sockets are unsupported. + +Private addresses and environment proxies fail by default. Explicit proxy +authority delegates routing and resolution to that trusted proxy. These +controls are defense in depth; they do not replace container, VM, identity, or +platform egress isolation for hostile workflows. + +## Process isolation contract + +Process actions declare `process` or `container` isolation. Existing actions +default to `process`, which means bounded direct execution with the agentctl +host identity and is not a sandbox. The compiled plan lists every process +action, selected mode, consuming tasks, and container resources. + +`container` requires a locally available content-addressed image and Docker or +Podman. It never pulls or silently falls back. The fixed invocation is +networkless, read-only, non-root, capability-dropped, `no-new-privileges`, and +memory/CPU/PID/output/time bounded. The authorized working directory is mounted +read-only. No Linux namespace/bubblewrap, macOS sandbox-profile, or Windows +restricted-token/job-object backend is claimed. + +## Explicit non-goals + +- hosted SaaS, public control plane, or public pack registry; +- chat application, free-form multi-agent conversation, or hidden model-owned + routing; +- Kubernetes operator, runner fleet, public cloud scheduler, calendars, or + event triggers; +- distributed scheduling, distributed leases, multi-host execution, or + distributed storage; +- IDE or visual workflow editor; +- general configuration management; +- unbounded loops, unbounded model-controlled expansion, or arbitrary + expression code; +- an unsafe in-process native plugin ABI; +- a claim that policy allowlists are an OS sandbox; +- a claim of exactly-once external mutation or transactional compensation. + +External schedulers own triggers and overlap policy. Containers, VMs, platform +identities, and egress controls remain the strongest isolation boundary for +hostile workloads. +> Canonical source: [`docs/execution/FRAMEWORK_COMPLETENESS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/execution/FRAMEWORK_COMPLETENESS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/memory.md b/src/content/docs/_generated/concepts/memory.md index 729317a..9621459 100644 --- a/src/content/docs/_generated/concepts/memory.md +++ b/src/content/docs/_generated/concepts/memory.md @@ -6,9 +6,81 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/memory.md" Four mechanisms remain intentionally separate: - Run state is authoritative lifecycle data: inputs, task states, attempts, outputs, cancellations, effects, approvals, and checkpoints. -- Working memory is a JSON object owned by one run. Writes are explicit keyed internal-state effects and the updated object commits with the task transition and checkpoint. Sequential scheduling is its merge rule. -- Long-term memory is namespaced SQLite data across runs with optional expiry. Reads/writes are explicit actions; `memory get/put` and `gc` provide administration. Replay never rolls it back or treats it as history. +- Working memory is a JSON object owned by one run. Writes are explicit keyed internal-state effects. Parallel tasks read durable isolated snapshots; disjoint deltas commit in compiled order with task transitions and the checkpoint. Unordered conflicting write sets fail compilation. +- Long-term memory is typed, namespaced data across runs with optional expiry, exact lookup, metadata filters, and text, vector, or hybrid retrieval. SQLite is built in and a provider-neutral adapter trait supports external stores. - Provider prompt cache is an optional performance optimization. Cache keys/options and usage counts are provider metadata, never correctness or memory. -Long-term retrieval is exact namespace/key lookup in this release. Vector search and automatic promotion are not implemented. A workflow promotes a value explicitly by reading long-term memory and then writing working memory. Retention is applied by expiration/GC, not by replay. -> Canonical source: [`docs/memory.md`](https://github.com/opensourceops/agentctl/blob/main/docs/memory.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +## Long-term memory configuration + +```yaml +spec: + memory: + working: + recalled: [] + longTerm: + provider: sqlite + namespace: support + retentionDays: 30 + embedding: + provider: local_hash + dimensions: 64 +``` + +`provider` selects the memory store. The packaged CLI provides `sqlite`. +`embedding.provider` selects `local_hash` or a named provider. The local hash +provider is a deterministic lexical vector baseline suitable for offline tests, +not a neural semantic model. A named OpenAI provider can use +`model: text-embedding-3-small`; it follows the provider's credential, endpoint, +and header configuration. OpenAI dimensions require a +`text-embedding-3` model that supports the requested size. + +Entries use format version 1 and contain either typed text or JSON plus +searchable text and exact-match metadata: + +```yaml +content: { type: text, text: "customer prefers concise release notes" } +metadata: { team: docs, priority: 2 } +``` + +JSON entries may instead use `content: { type: json, value: ..., text: ... }`. +Legacy JSON values are read as versioned entries with derived searchable text. + +## Workflow actions + +- `builtin.long_term_memory.read` reads one namespace/key record. +- `builtin.long_term_memory.search` accepts `query`, `mode` (`text`, `vector`, + or `hybrid`), `limit`, optional `namespace`, and exact metadata `filters`. +- `builtin.long_term_memory.write` accepts `key`, optional `namespace`, + `content` or `entry`, metadata, and optional `retentionDays`. +- `builtin.long_term_memory.promote` explicitly copies its `value` into a + declared working-memory `key`. + +Search returns a stable ordered result set with typed records and integer +millionth scores. Text scoring is deterministic token overlap. Vector scoring +uses cosine similarity. Hybrid mode combines both scores. Equal scores are +ordered by key. Expired records are excluded. + +Retrieval and writes are durable effects. Recorded replay reuses the recorded +result and performs no memory or embedding call. Selective repair re-executes a +selected retrieval boundary, so it can observe entries added after the source +run. Promotion is explicit and recorded; there is no automatic or hidden model +memory. + +## Administration and bounds + +```text +agentctl memory --db .agentctl/runtime.db get NAMESPACE KEY +agentctl memory --db .agentctl/runtime.db put NAMESPACE KEY JSON_VALUE --text TEXT --metadata JSON --retention-days 30 +agentctl memory --db .agentctl/runtime.db search NAMESPACE QUERY --mode hybrid --limit 10 --filter team='"docs"' +agentctl memory --db .agentctl/runtime.db reindex NAMESPACE +``` + +The CLI administration path writes and rebuilds 64-dimensional `local_hash` +vectors. Workflow execution is the path for configured OpenAI or external +embedding providers. + +Entries are capped at 1 MiB, queries at 64 KiB, results at 100, embedding +dimensions from 8 through 4096, and a local search scan at 10,000 active +candidates. Corrupt or mismatched vector dimensions fail closed. Retention is +applied during reads/search and by garbage collection, not by replay. +> Canonical source: [`docs/memory.md`](https://github.com/opensourceops/agentctl/blob/main/docs/memory.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/packs.md b/src/content/docs/_generated/concepts/packs.md index f485152..706e794 100644 --- a/src/content/docs/_generated/concepts/packs.md +++ b/src/content/docs/_generated/concepts/packs.md @@ -3,9 +3,122 @@ title: "Reusable packs" description: "Use versioned local content with integrity verification." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/PACKS.md" --- -A pack is reviewed reusable YAML content, not executable plugin code. Its manifest API is `agentctl.dev/pack/v1alpha1` and declares a fully qualified dotted name, semantic version, agentctl semver constraint, actions, agents, tool contracts, capabilities, provider requirements, and optional policy defaults. +A pack is reviewed reusable workflow content. It is not an in-process native +plugin. The manifest API is `agentctl.dev/pack/v1alpha1` and uses a fully +qualified dotted name, semantic version, agentctl compatibility constraint, +optional dependencies, and exported actions, agents, tools, and sub-workflows. -`agentctl packs inspect` strictly parses the manifest, validates the API version, name, versions, and compatibility with the running binary. `agentctl packs verify` compares a `sha256:` integrity digest for a local manifest or archive. Workflow pack references carry name, version, local path, and integrity. The CLI verifies a referenced manifest, keeps it beneath the workflow directory, and loads actions, agents, and tools as `.` before compilation. +## Sources and resolution -Dependency resolution, transitive lockfile generation, Git fetching, reusable sub-workflows, policy-default merging, a hosted registry, native dynamic libraries, and pack processes are not implemented. A checked-in pack reference is therefore an integrity/provenance contract for local content, not a package manager. Manifest policy defaults are inspectable metadata and never weaken the invoking workflow’s policy. -> Canonical source: [`docs/PACKS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PACKS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Workflow roots and transitive dependencies use an exact source: + +```yaml +packs: + - name: example.utility + version: "^1.0" + source: + path: packs/example.pack.yaml +``` + +Supported sources are: + +- a contained local `path`; +- a Git `https` URL with a full 40-character `rev` and contained `manifest`; +- an immutable `https` tar-gzip archive URL with SHA-256 `integrity` and a + contained `manifest`. + +Loopback HTTP and contained `file:` Git URLs exist only for deterministic local +fixtures. URLs with credentials, query parameters, or fragments are rejected. +Git branches and tags are not accepted as revisions. Archive redirects, +symlinks, hardlinks, special files, path escapes, more than 1,024 entries, +compressed content over 16 MiB, and expanded content over 64 MiB are rejected. + +Each dependency names its source and semantic constraint: + +```yaml +dependencies: + example.base: + version: "^2.1" + source: + git: https://github.com/example/base-pack.git + rev: 0123456789abcdef0123456789abcdef01234567 + manifest: agentctl.pack.yaml +``` + +Resolution is deterministic because every requirement identifies one immutable +candidate. Conflicting versions or sources, duplicate identities, missing +dependencies, and cycles fail with validation exit `2`. There is no hosted +registry and no implicit search order. + +## Lockfile workflow + +Generate and commit `agentctl.pack.lock` beside the workflow: + +```console +agentctl packs lock workflow.yaml +agentctl packs verify-lock workflow.yaml --locked +agentctl packs update workflow.yaml +agentctl packs update workflow.yaml --pack example.utility +``` + +The lock API is `agentctl.dev/pack-lock/v1`. It records agentctl compatibility, +pack identity and concrete version, exact source, manifest digest, dependency +edges, signature metadata, and trust result. Entries are sorted by pack name. +An update resolves the complete graph; `--pack` validates and identifies the +requested root while preserving graph-wide consistency. + +Execution uses the lock whenever it exists. `--locked` requires it and rejects +workflow, source, graph, digest, compatibility, signature, trust, or unreachable +entry drift. `--offline` permits local paths and requires Git/archive cache +hits. Legacy exact `path` plus `integrity` references remain readable without a +lock and emit a migration warning. + +## Integrity and trust + +SHA-256 binds the lock to exact bytes. It proves sameness, not publisher +identity. Optional keyless publisher verification uses the standard Sigstore +bundle format and the embedded Sigstore public-good trust root: + +```yaml +packTrust: + unsigned: deny + identities: + - identity: https://github.com/example/repository/.github/workflows/release.yml@refs/tags/v1.2.0 + issuer: https://token.actions.githubusercontent.com +packs: + - name: example.utility + version: "=1.2.0" + source: + path: packs/example.pack.yaml + signature: + bundle: packs/example.pack.sigstore.json + identity: https://github.com/example/repository/.github/workflows/release.yml@refs/tags/v1.2.0 + issuer: https://token.actions.githubusercontent.com +``` + +Verification checks the artifact signature, certificate chain, identity, +issuer, transparency-log proof, signed timestamp, and locked bundle digest. +The bundle is sufficient for offline cryptographic verification, subject to the +freshness of the trust root embedded in the installed agentctl version. See the +[Sigstore bundle model](https://docs.sigstore.dev/about/bundle/) and +[Cosign blob verification](https://docs.sigstore.dev/cosign/verifying/verify/). + +`packTrust.unsigned` is `deny`, `warn`, or `allow`, with `warn` as the default. +Unsigned process-capable packs are always blocked unless +`allowUnsignedProcess: true` is also explicit. That exception is a review +acknowledgement, not proof of publisher identity or process isolation. + +Manifest policy defaults remain inspectable metadata and never weaken the +invoking workflow policy. Exported definitions are qualified as +`.` before compilation. + +## Verification evidence + +Unit fixtures cover semantic constraints, deterministic ordering, conflicts, +cycles, path containment, tamper, locked drift, pinned Git cache reuse, +offline misses, bounded archives, archive links, valid and invalid Sigstore +bundles, identity policy, unsigned process denial, and dependency reachability. +Packaged acceptance scenario 42 verifies the checked-in transitive example, +locks an extension pack, proves that its process cannot start before explicit +trust authorization, executes it once, and replays without another invocation. +> Canonical source: [`docs/PACKS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PACKS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/policies.md b/src/content/docs/_generated/concepts/policies.md index 444fdbe..7189cd8 100644 --- a/src/content/docs/_generated/concepts/policies.md +++ b/src/content/docs/_generated/concepts/policies.md @@ -3,13 +3,44 @@ title: "Policies and approvals" description: "Keep authority outside the model with explicit grants and durable decisions." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/policies.md" --- -Policy is evaluated by the runtime, never by a model. A policy defines a canonical workspace root, writable roots, allowed environment names, network host patterns, process basenames, providers, tool allow/deny lists, approval mode, and non-interactive behavior. +Policy is evaluated by the runtime, never by a model. A policy defines a +canonical workspace root, writable roots, allowed environment names, secret +file roots, ordinary and secret-helper process basenames, network host +patterns, providers, tool allow/deny lists, approval mode, and non-interactive +behavior. -Read paths must canonicalize under the workspace. Write paths canonicalize the nearest existing parent and must remain under a writable root. Parent traversal and symlink escape fail. Network rules match an exact hostname or `*.suffix` subdomains; suffix lookalikes and the wildcard apex do not match. HTTP redirects are disabled. Process allowlisting checks the executable basename and then launches direct argv with a cleared environment. +Read paths must canonicalize under the workspace. Write paths canonicalize the +nearest existing parent and must remain under a writable root. Secret files +must be existing regular files canonically contained by `secretFileRoots`. +Parent traversal and symlink escape fail. Network rules match an exact hostname +or `*.suffix` subdomains; suffix lookalikes and the wildcard apex do not match. +Before a required provider, MCP, or A2A adapter is created, agentctl validates +the scheme and effective port, resolves the destination once, checks every +returned IPv4 and IPv6 address, and pins the accepted answer into the HTTP +client. Private, loopback, link-local, shared, documentation, benchmark, +unspecified, multicast, and reserved addresses fail unless `allowPrivate` is +explicitly enabled. HTTP redirects and Unix-socket transports are disabled. +Environment proxy discovery is disabled unless `allowProxy` is explicit. +TLS uses rustls and the platform roots; an optional protected `customCa` +reference may add a certificate-only PEM bundle. DNS/connect time and response +bytes are bounded. See [Network policy](https://github.com/opensourceops/agentctl/blob/main/docs/guides/NETWORK_POLICY.md). + +Process allowlisting checks the executable basename. Process actions then use +an explicit isolation mode. The default `process` mode launches direct host +arguments with a cleared environment and is not a sandbox. `container` +requires a local digest-pinned image and available Docker or Podman backend; +it never falls back to the host, pulls an image, or enables network access. +The compiled plan exposes the selected mode and resource limits. Secret +helpers use their separate `secretProcessAllowlist` and stricter 60-second, +64-KiB maximums as host processes. See [Process +isolation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PROCESS_ISOLATION.md) and [Secret +references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). Tool visibility, tool/capability authorization, resource checks, effect risk, and approval are distinct decisions. `never`, `mutations`, `high_risk`, and `always` are available approval modes. A tool may say `never`, `policy`, or `always`. The default non-interactive behavior is a durable pause and exit code `3`; explicit `deny_approval` and `fail` modes fail closed. Non-interactive execution never prompts or auto-approves. An approval stores the run/trace/task/agent, tool, capability, risk, redacted input, expected effect, reason, and resolution actor/reason. The associated task waits durably. Use `approvals list`, `approve`, or `reject`, then `resume`. Resolution and effect status are auditable. -Provider, MCP, A2A, filesystem, process, and environment allowlists are necessary controls, not a containment boundary. Run untrusted executors inside an external OS/container sandbox. -> Canonical source: [`docs/policies.md`](https://github.com/opensourceops/agentctl/blob/main/docs/policies.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Provider, MCP, A2A, filesystem, process, and environment allowlists are +necessary controls, not a containment boundary. Use `isolation: container` or +an externally managed container/VM boundary for untrusted executors. +> Canonical source: [`docs/policies.md`](https://github.com/opensourceops/agentctl/blob/main/docs/policies.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/product.md b/src/content/docs/_generated/concepts/product.md index 341105b..febe67e 100644 --- a/src/content/docs/_generated/concepts/product.md +++ b/src/content/docs/_generated/concepts/product.md @@ -9,7 +9,7 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/PRODUCT.md" Primary users are application and platform engineers authoring reviewed automation, security-conscious teams introducing model calls into existing operations, CI maintainers needing credential-free validation, and Rust applications embedding the runtime. Their jobs are to validate before acting, understand an exact plan, constrain effects, recover from interruption, prove what happened, and reuse reviewed content. -Core use cases are local repository automation, approval-gated changes, structured model enrichment, provider-portable agent tasks, MCP tool calls, A2A delegation, cron-invoked runs, and generic containerized CI steps. `agentctl` is a schedulable runtime, not a scheduler: cron, systemd, Kubernetes, and CI own triggers and overlap policy. Hosted orchestration, a visual builder, chat, distributed scheduling, a public registry, arbitrary configuration management, secret storage, and unbounded autonomy are non-goals. +Core use cases are local repository automation, approval-gated changes, structured model enrichment, provider-portable agent tasks, selective repair from a failed task boundary, MCP tool calls, A2A delegation, cron-invoked runs, and generic containerized CI steps. `agentctl` is a schedulable runtime, not a scheduler: cron, systemd, Kubernetes, and CI own triggers and overlap policy. Hosted orchestration, a visual builder, chat, distributed scheduling, a public registry, arbitrary configuration management, secret storage, and unbounded autonomy are non-goals. ## Journeys @@ -17,6 +17,7 @@ Core use cases are local repository automation, approval-gated changes, structur - Scheduled: invoke the CLI without a TTY, use explicit database/workspace/artifact paths and an overall timeout, receive exit `3` for a durable pending approval, and resume through an operator-controlled invocation. - CI: mount config/workspace/state/artifacts into the generic OCI image, inject secrets only as environment variables, pass inputs by `--inputs-file` or repeated `--input`, and consume one versioned final JSON envelope on stdout. - Embedded: construct core workflow and plan values, inject a store, providers, tools, clock, IDs, and tracing, then invoke the runtime with a cancellation token. +- Repair: keep the failed terminal source immutable, compile a corrected target, plan one or more roots, reuse compatible successful boundaries, and execute only the roots and their affected descendants. Provider portability means the internal message, tool, continuation, usage, and capability contracts do not expose provider SDK types. It does not mean every provider has identical features. Compilation rejects a requested feature absent from the chosen provider. @@ -36,5 +37,5 @@ Version 0.2 is a production-oriented alpha with executable evidence for the stat This is not a chat-agent or multi-agent conversation framework: workflows, not conversations, own control flow. It is not CI/CD: it can run inside CI but does not manage runners or deployment environments. It borrows idempotence and check/diff vocabulary from Ansible without becoming configuration management. It borrows plan/effect separation from Terraform without owning infrastructure state. It is not a hosted orchestrator or general scripting language: one local process, SQLite, constrained templates, typed actions, and explicit remote effects are intentional boundaries. -The differentiator is the combination of deterministic compilation, honest predictability, durable effect identity, recorded no-effect replay, native provider portability, and policy decisions made outside the model. -> Canonical source: [`docs/PRODUCT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PRODUCT.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +The differentiator is the combination of deterministic compilation, honest predictability, durable effect identity, recorded no-effect replay, compatibility-checked task-boundary repair, native provider portability, and policy decisions made outside the model. +> Canonical source: [`docs/PRODUCT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PRODUCT.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/tools.md b/src/content/docs/_generated/concepts/tools.md index 21d299e..4b155bf 100644 --- a/src/content/docs/_generated/concepts/tools.md +++ b/src/content/docs/_generated/concepts/tools.md @@ -3,13 +3,20 @@ title: "Tools and effects" description: "Tool contracts, effect classes, idempotency, and deterministic checks." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/TOOLS.md" --- -A tool contract has a stable ID, description, input and output JSON Schema, capability, risk, effect class, idempotency, retry-safety flag, timeout, secret and network requirements, approval mode, and optional compensation metadata. Inputs are validated before an executor is called; outputs are validated before entering messages or task state. Executor errors remain errors. +A tool contract has a stable ID, description, input and output JSON Schema, capability, risk, effect class, idempotency, retry-safety flag, timeout, secret and network requirements, and approval mode. Inputs are validated before an executor is called; outputs are validated before entering messages or task state. Executor errors remain errors. Effect classes are `pure`, `internal_state`, `observe`, `workspace_mutate`, `external_mutate`, `process_execution`, `network`, `model`, and `remote_agent`. Idempotency is `pure`, `idempotent`, `keyed`, `at_most_once`, or `unknown`. These values drive durable recovery and policy; model-provided MCP annotations never override them. Built-in model-callable tools are workspace read, workspace write, and echo. Their declared kind must match compiler-enforced capability/effect/idempotency semantics; the packaged CLI registers each declared built-in executor. Function-call IDs, input/output digests, status, and effect correlation are stored per run. -Built-in actions are assign, assert, file read/write, direct process execution, run working-memory read/write, SQLite long-term-memory read/write, MCP call, and A2A delegation. File writes use a temporary file plus rename and return before/after/diff. Shell execution uses a direct executable and argv, never an implicit shell, clears inherited environment, applies allowlisted variables, and is not an OS sandbox. +Built-in actions are assign, assert, file read/write, direct process execution, +run working-memory read/write, typed long-term-memory read/search/write and +explicit promotion, MCP call, and A2A delegation. Long-term retrieval supports +deterministic text, vector, and hybrid modes with metadata filters; replay uses +the recorded result. File writes use a temporary file plus rename and return +before/after/diff. Shell execution uses a direct executable and argv, never an +implicit shell, clears inherited environment, applies allowlisted variables, +and is not an OS sandbox. Check mode executes pure/internal simulation and observation needed for dataflow but never filesystem, process, remote, or model mutation. Results say fully predictable, partially predictable, or requires execution; unknown external work is never reported as predicted. -> Canonical source: [`docs/TOOLS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/TOOLS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/TOOLS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/TOOLS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/concepts/workflow-model.md b/src/content/docs/_generated/concepts/workflow-model.md index 2963493..0abf213 100644 --- a/src/content/docs/_generated/concepts/workflow-model.md +++ b/src/content/docs/_generated/concepts/workflow-model.md @@ -5,17 +5,89 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/DSL.md" --- The current document version is `agentctl.dev/v1alpha1`, with `kind: Workflow`. The generated, authoritative JSON Schema is [`schemas/workflow.schema.json`](/agentctl/downloads/workflow.schema.json). YAML documents are limited to 1 MiB and reject unknown fields. -`metadata` contains the name, description, and labels. `spec` contains typed inputs/outputs; providers; bounded agents; actions; tool contracts; ordered tasks; policy; memory; MCP servers; A2A peers; packs; runtime; and output settings. A task `uses` either `action:` or `agent:`, declares `needs`, an optional `when`, local `vars`, typed `with` input, retry, timeout, and failure behavior. +`metadata` contains the name, description, and labels. `spec` contains typed inputs/outputs; providers; bounded agents; actions; tool contracts; reusable sub-workflows; compensation policy; ordered tasks; policy; memory; MCP servers; A2A peers; packs; runtime; and output settings. A task `uses` `action:`, `agent:`, `workflow:`, or the pure `router` construct. Tasks declare `needs`, optional bounded `foreach`, `matrix`, or `loop` expansion, optional working-memory `memoryWrites`, an optional `when`, local `vars`, typed `with` input, optional `outputSchema`, retry, timeout, failure behavior, and an optional effectful `compensate` action. Templates use only `${{ inputs.path }}`, `${{ vars.path }}`, `${{ memory.path }}`, and `${{ tasks.task-id.output.path }}`. Conditions additionally allow `not` and equality against a JSON literal or string. Exact templates preserve their JSON type; interpolation into text accepts only scalars. Missing and explicit `null` are different. There is no code execution, function call, indexing, arithmetic, or implicit task dependency. -Providers, action environments, and protocol headers use `{ env: NAME }` secret references. Secret names are validated and values never become the workflow document. +`when` decisions retain the expression, boolean result, and a digest of the +evaluated context in durable task/audit state. A `router` selects one exact +typed template, compares it with type-sensitive enumerated cases, and records +the selected value and explicit destinations. Unselected destinations are +durably skipped. See [Conditions and routers](https://github.com/opensourceops/agentctl/blob/main/docs/guides/CONDITIONS_AND_ROUTERS.md). -The compiler validates missing references, duplicate tasks, cycles, task-aware templates, tool references, provider capabilities, agent limits, and sequential runtime settings before execution. Ready tasks follow declaration order. `maxConcurrency` must be `1` in this version. +Task output is JSON. Built-in actions own an object contract, agents can declare provider-enforced `structuredOutput`, and a task can override the complete contract with `outputSchema`. The compiler validates schemas; the runtime validates completed and selectively reused values. + +Providers, action environments, and protocol headers use secret references: +`{ env: NAME }`, `{ file: PATH }`, or a bounded `{ process: ... }` reference. +File references require `policy.secretFileRoots`; process references require +`policy.secretProcessAllowlist`. Existing environment references remain +compatible. Resolved values never become the workflow document, effect value, +trace, or inspection output. See [Secret references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). + +`policy.workspaceRoot` is the default boundary for relative file paths. Each `writableRoots` entry may be workspace-relative or an explicit absolute mount such as `/artifacts`. Ordinary reads remain workspace-confined. After a successful authorized mutation, the runtime may read that exact output through its writable-root boundary to ingest the bounded regular file into durable CAS; this does not grant tasks general read access to the external root. + +`policy.networkAllowlist` grants exact hosts or `*.suffix` subdomains. +`policy.network` constrains `allowedSchemes`, `allowedPorts`, +`allowPrivate`, `allowProxy`, `customCa`, `connectTimeoutSeconds`, and +`maxResponseBytes`. Private addresses and proxies default to denied. Required +provider and protocol endpoints are resolved, checked, and pinned before run +state is created. See [Network policy](https://github.com/opensourceops/agentctl/blob/main/docs/guides/NETWORK_POLICY.md). + +The compiler validates missing references, duplicate tasks, cycles, task-aware templates, tool references, provider capabilities, agent limits, concurrency bounds, and working-memory conflicts before execution. `maxConcurrency` accepts `1` through `64` and defaults to `1`. Independent ready tasks are selected in compiled order, execute against durable isolated memory snapshots, and commit atomically in compiled order. Literal working-memory keys are inferred; templated keys require `memoryWrites`. See [Deterministic parallel tasks](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PARALLEL_TASKS.md). + +Static `foreach` lists and matrix axes expand at compile time into stable child +tasks plus a parent aggregate. `maxItems` defaults to 32, expansion cannot +exceed 256 children, and model output cannot drive it. Retry and repair can +select the visible child IDs. See [Matrix and foreach tasks](https://github.com/opensourceops/agentctl/blob/main/docs/guides/MATRIX_AND_FOREACH.md). + +Bounded `loop` tasks require `maxIterations` from 1 through 64 and one exact +typed `while` guard. They compile into stable sequential iteration tasks. +`vars.loopIndex` is the zero-based position and `vars.loopPrevious` is the +initial value or preceding iteration output. A still-true guard after the +maximum fails closed. Retry and repair select iteration IDs. See [Bounded +loops](https://github.com/opensourceops/agentctl/blob/main/docs/guides/BOUNDED_LOOPS.md). + +Reusable `subworkflows` declare a semantic version, input/output JSON Schemas, +default input values, an output map, and local tasks. An invocation compiles to +a typed input boundary, `INVOCATION--LOCAL_TASK` children, and a typed output +aggregate. Pack manifests export the same contract under `workflows`. See +[Reusable sub-workflows](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SUB_WORKFLOWS.md). + +Compensable tasks declare one named effectful action under `compensate`. +Compensation is manual unless `spec.compensation.onFailure` is `automatic`. +Planning uses confirmed source effects, runs inverse actions in reverse graph +order, and appends linked `compensated` reconciliation records. See +[Compensate applied effects](https://github.com/opensourceops/agentctl/blob/main/docs/guides/COMPENSATION.md). + +Structured role collaboration uses ordinary agent tasks, typed deterministic +handoff tasks, routers, and reusable sub-workflows. `uses: team:` is +rejected because hidden conversation state would bypass the compiled graph. +See [Structured role handoffs](https://github.com/opensourceops/agentctl/blob/main/docs/guides/STRUCTURED_HANDOFFS.md). + +An agent may set `stream: true` when its provider advertises streaming. Stream +fragments are bounded, redacted, persisted under task-attempt sequence numbers, +and kept separate from final task output validation. See [Durable provider +streaming](https://github.com/opensourceops/agentctl/blob/main/docs/guides/DURABLE_STREAMING.md). + +`builtin.shell.exec` and `extension.process` expose `isolation: process` by +default. This is bounded host execution, not a sandbox. `isolation: container` +requires a local digest-pinned image plus Docker or Podman and runs with a +read-only root/workspace, no network, a non-root identity, dropped +capabilities, and explicit memory/CPU/PID limits. The requested engine and +image fail closed without host fallback. See [Process +isolation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PROCESS_ISOLATION.md). + +`runtime.budgets` sets optional run-wide request, turn, tool, token, wall-time, +process-output, artifact, task, expansion, loop, and monetary ceilings. Static +graph counts fail compilation. Dynamic units are reserved atomically before +fresh effect dispatch and reconciled from actual usage. Monetary limits use +integer micro-US-dollars and require versioned `runtime.pricing` entries keyed +by `provider/model`. See [Resource and cost +budgets](https://github.com/opensourceops/agentctl/blob/main/docs/guides/RESOURCE_BUDGETS.md). `builtin.shell.exec` captures stdout and stderr concurrently. Its optional `stdoutLimitBytes`, `stderrLimitBytes`, and `combinedOutputLimitBytes` fields default to 1 MiB, 1 MiB, and 2 MiB respectively. Each configured value must be between 1 byte and 16 MiB. `timeoutSeconds` must be between 1 and 86,400. Exceeding an output bound terminates and reaps the process and records a structured failed effect; timeout or cancellation remains an uncertain effect because external changes may already have occurred. These fields are validated identically for workflow and pack actions. The parser translates a limited unversioned `playbook:` document and emits a migration warning. Use `agentctl migrate old.yaml --write new.yaml`. Legacy pack-backed, MCP, A2A, provider-specific, and broad module configurations need manual migration; see [Migrating from TypeScript](/agentctl/reference/migration/). -Not implemented in v1alpha1: `foreach`, matrix expansion, parallel groups, routers, loops, sub-workflows, `finally`, handlers, event triggers, or compensation execution. They remain excluded until their deterministic state, merge, and recovery semantics are specified. -> Canonical source: [`docs/DSL.md`](https://github.com/opensourceops/agentctl/blob/main/docs/DSL.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Not implemented in v1alpha1: `finally`, handlers, or event triggers. Parallelism is expressed by independent graph tasks rather than a separate parallel-group construct. +> Canonical source: [`docs/DSL.md`](https://github.com/opensourceops/agentctl/blob/main/docs/DSL.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/add-action.md b/src/content/docs/_generated/contributing/add-action.md index 2e08dba..5a27276 100644 --- a/src/content/docs/_generated/contributing/add-action.md +++ b/src/content/docs/_generated/contributing/add-action.md @@ -42,4 +42,4 @@ cargo xtask generate cargo xtask docs-verify cargo xtask verify ``` -> Canonical source: [`docs/development/ADD_ACTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_ACTION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/development/ADD_ACTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_ACTION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/add-migration.md b/src/content/docs/_generated/contributing/add-migration.md index 87e2987..8438db8 100644 --- a/src/content/docs/_generated/contributing/add-migration.md +++ b/src/content/docs/_generated/contributing/add-migration.md @@ -24,4 +24,4 @@ Create the previous schema in a temporary database, insert representative durabl ## 5. Document operator impact Update the database reference, compatibility policy, release notes or status evidence, and backup guidance. Explain whether downgrade remains possible. Run the complete store tests and `cargo xtask verify`. -> Canonical source: [`docs/development/ADD_MIGRATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_MIGRATION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/development/ADD_MIGRATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_MIGRATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/add-provider.md b/src/content/docs/_generated/contributing/add-provider.md index 36d7579..03ab4a5 100644 --- a/src/content/docs/_generated/contributing/add-provider.md +++ b/src/content/docs/_generated/contributing/add-provider.md @@ -11,7 +11,10 @@ Declare support for text, structured output, tools, reasoning, continuation, cac ## Authentication and network boundary -Use a workflow environment reference. Resolve credentials only at the adapter boundary, never from a CLI key flag. Enforce the reviewed endpoint host, disable redirects, use rustls, and define whether an endpoint override is permitted. +Use the core secret-reference contract and runtime resolver. Resolve credentials +only at the adapter boundary, never from a CLI key flag. Enforce the reviewed +endpoint host, disable redirects, use rustls, and define whether an endpoint +override is permitted. ## Native request mapping @@ -35,5 +38,8 @@ Add local mock-protocol tests for request mapping, authentication, headers, redi ## Documentation claims -Update the provider guide and matrix with the exact level: implemented, mock-protocol tested, retained live evidence, or deferred. Add an example that passes `check` without resolving a secret. Run `cargo xtask generate`, `cargo xtask docs-verify`, and `cargo xtask verify`. -> Canonical source: [`docs/development/ADD_PROVIDER.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_PROVIDER.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Update the provider guide and matrix with the exact level: implemented, +mock-protocol tested, retained live evidence, or outside the current supported +surface. Add an example that passes `check` without resolving a secret. Run +`cargo xtask generate`, `cargo xtask docs-verify`, and `cargo xtask verify`. +> Canonical source: [`docs/development/ADD_PROVIDER.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/ADD_PROVIDER.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/developer-guide.md b/src/content/docs/_generated/contributing/developer-guide.md index cb942c8..b89e380 100644 --- a/src/content/docs/_generated/contributing/developer-guide.md +++ b/src/content/docs/_generated/contributing/developer-guide.md @@ -11,7 +11,7 @@ The production implementation is a Rust workspace. The remaining top-level TypeS | --- | --- | | `agentctl-core` | strict DSL, migration, compiler, templates, state, effects, policy, provider and tool contracts | | `agentctl-store` | versioned SQLite persistence, migrations, checkpoints, approvals, audit, trace, sessions, tool calls, memory | -| `agentctl-runtime` | sequential scheduler, actions, bounded agent loop, resume, replay, fork, cancellation | +| `agentctl-runtime` | bounded deterministic scheduler, actions, bounded agent loop, resume, replay, fork, cancellation | | `agentctl-providers` | native OpenAI, Azure OpenAI, Anthropic, Google, and fake adapters | | `agentctl-protocols` | MCP and A2A clients | | `agentctl-observability` | typed events, test sink, and OpenTelemetry bridge | @@ -64,4 +64,4 @@ Provider adapters implement the neutral model contract and publish typed capabil Run `cargo xtask generate` whenever CLI help or the DSL changes. Run `cargo xtask docs-verify` for public content and examples. Update the Pages site's content manifest when adding a new canonical public page. Release decisions depend on hosted evidence for the exact candidate commit; local success alone does not approve an RC. Related guides: [Add an action](/agentctl/contributing/add-action/), [Add a provider](/agentctl/contributing/add-provider/), [Add a store migration](/agentctl/contributing/add-migration/), [Write documentation](/agentctl/contributing/documentation/), [Testing](/agentctl/contributing/testing/), and [Release process](/agentctl/contributing/release/). -> Canonical source: [`docs/development/REPOSITORY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/REPOSITORY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/development/REPOSITORY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/REPOSITORY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/documentation.md b/src/content/docs/_generated/contributing/documentation.md index a13f6f0..ada1a0e 100644 --- a/src/content/docs/_generated/contributing/documentation.md +++ b/src/content/docs/_generated/contributing/documentation.md @@ -18,7 +18,9 @@ Place public journeys in `examples/docs/` with a README entry, provider classifi - Use sentence-case headings, active voice, short paragraphs, and descriptive links. - State the working directory, writes, credentials, and network effect for commands. - Use exact commands and complete valid YAML. -- Distinguish implemented, deterministic, mock-tested, live evidence, hosted configuration, hosted execution, and deferred work. +- Distinguish implemented, deterministic, mock-tested, live evidence, hosted + configuration, hosted execution, and functionality outside the supported + surface. - Never use an em dash in public copy. - Avoid hype, generic AI claims, and unsupported maturity language. - Explain every Mermaid diagram before and after it. @@ -42,4 +44,4 @@ The site command imports canonical content, records the source commit, validates ## Review Review technical claims against source, generated help, schema, tests, and evidence. Check keyboard navigation, heading order, link purpose, alt text, diagram explanations, mobile code blocks, and direct deep links. Do not claim accessibility certification from automated tooling alone. -> Canonical source: [`docs/development/DOCUMENTATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/DOCUMENTATION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/development/DOCUMENTATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/development/DOCUMENTATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/index.md b/src/content/docs/_generated/contributing/index.md index 91199f2..a49ea54 100644 --- a/src/content/docs/_generated/contributing/index.md +++ b/src/content/docs/_generated/contributing/index.md @@ -80,4 +80,4 @@ Reviewers focus on correctness, deterministic behavior, explicit effects, safe f ## Release process Maintainers follow [Release process](/agentctl/contributing/release/). Candidate promotion requires the exact remote commit to pass required hosted checks and artifact verification. Contributors must not create tags, publish packages, or describe a local build as released. -> Canonical source: [`docs/CONTRIBUTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/CONTRIBUTING.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/CONTRIBUTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/CONTRIBUTING.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/release.md b/src/content/docs/_generated/contributing/release.md index badcec2..b553e78 100644 --- a/src/content/docs/_generated/contributing/release.md +++ b/src/content/docs/_generated/contributing/release.md @@ -16,9 +16,15 @@ Push the review branch and open a pull request only after the local gates below - `container-security / container` - `supply-chain-security / security` -The three platform jobs run `cargo xtask verify`, `cargo xtask acceptance`, and `cargo xtask package`. The other jobs enforce the Linux container contract, HIGH/CRITICAL image vulnerability policy, production and image CycloneDX SBOMs, complete-history and checked-out-tree secret scans, dependency policy, immutable action pins, and workflow lint. +The three platform jobs run `cargo xtask verify`, `cargo xtask acceptance`, +`cargo xtask completeness`, and `cargo xtask package`. The other jobs enforce +the Linux container contract, HIGH/CRITICAL image vulnerability policy, +production and image CycloneDX SBOMs, complete-history and checked-out-tree +secret scans, dependency policy, immutable action pins, and workflow lint. -The repository owner must enable GitHub Actions and required checks after the workflows reach the remote. This repository-local change does not modify remote settings or claim a hosted run. +The repository owner must enable required checks on the protected release +branch. Repository-local changes and green pull-request jobs do not modify or +prove that remote governance setting. ## Local preflight @@ -29,6 +35,8 @@ env -u OPENAI_API_KEY -u AZURE_OPENAI_API_KEY -u ANTHROPIC_API_KEY \ -u GOOGLE_API_KEY -u GEMINI_API_KEY cargo xtask verify env -u OPENAI_API_KEY -u AZURE_OPENAI_API_KEY -u ANTHROPIC_API_KEY \ -u GOOGLE_API_KEY -u GEMINI_API_KEY cargo xtask acceptance +env -u OPENAI_API_KEY -u AZURE_OPENAI_API_KEY -u ANTHROPIC_API_KEY \ + -u GOOGLE_API_KEY -u GEMINI_API_KEY cargo xtask completeness cargo xtask package ``` @@ -64,9 +72,11 @@ For the candidate workflow run: - Secret-scan finding: stop, revoke any real credential, remove it from the complete history using the repository's incident procedure, then rerun both history and tree scans. - Dependency or image finding: review the advisory and remediate or document an explicit time-bounded exception before release. The default HIGH/CRITICAL image gate ignores only unfixed findings. - SBOM failure or missing artifact: treat as a release failure. SBOM generation is not best-effort. -- Container CA failure: configure only `AGENTCTL_BUILD_CA_PEM` as a protected repository/organization secret. Do not use insecure Cargo, Git, curl, or container flags. +- Container CA failure on `main` or a manually dispatched run: configure only `AGENTCTL_BUILD_CA_PEM` as a protected repository/organization secret. Pull-request runs intentionally cannot receive it. Do not use insecure Cargo, Git, curl, or container flags. ## Release decision -The local recommendation is **Ready for hosted RC validation**. Promote to an RC only after the exact remote commit has all required hosted checks and artifacts. Stable `v1.0` remains outside this `v1alpha1` gate. -> Canonical source: [`docs/RELEASE_PROCESS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/RELEASE_PROCESS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Promote an exact commit to a framework candidate only after it has all required +hosted checks and artifacts. Stable `v1.0` remains outside this `v1alpha1` +gate. +> Canonical source: [`docs/RELEASE_PROCESS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/RELEASE_PROCESS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/contributing/testing.md b/src/content/docs/_generated/contributing/testing.md index b83273f..d75f009 100644 --- a/src/content/docs/_generated/contributing/testing.md +++ b/src/content/docs/_generated/contributing/testing.md @@ -15,13 +15,16 @@ User-journey layers are separate: cargo xtask acceptance cargo xtask acceptance-container cargo xtask acceptance-live-openai # explicit credentialed gate only +cargo xtask resource-budget-live-openai # one-request credentialed gate only +cargo xtask examples-verify +cargo xtask examples-verify-live-openai # explicit credentialed gate only cargo xtask package cargo xtask secret-scan ``` It checks rustfmt; clippy with all targets/features and warnings denied; locked build; unit, integration, compatibility, provider, protocol, persistence, runtime, and security tests; rustdoc; generated schema/CLI consistency; all workflow validation and deterministic examples; negative capability/policy/no-mutation cases; dependency sources/licenses/advisories; repository secret patterns and immutable workflow action pins; `cargo install`; and the Rust-only production boundary. -Unit tests cover parser diagnostics, strictness, compiler order/cycles/capabilities, templates, tool schemas, policy traversal/network/redaction, state transitions, effect recovery, store migration/corruption/checkpoints, runtime dataflow/check/diff/approval/cancellation/replay/fork, provider mappings, protocols, and traces. `proptest` exercises arbitrary templates and typed preservation. Language-neutral fixtures in `fixtures/compat` preserve the TypeScript oracle’s external graph/dataflow contract. +Unit tests cover parser diagnostics, strictness, compiler order/cycles/capabilities, templates, tool schemas, policy traversal/network/redaction, state transitions, effect recovery, store migration/corruption/checkpoints, runtime dataflow/check/diff/approval/cancellation/replay/repair/fork, provider mappings, protocols, and traces. Repair regressions cover two-agent reuse with a panic-on-repeat provider, downstream and branch closure, repeated roots, changed definitions/prompts, output/state/artifact corruption, migration and rollback, effect uncertainty/reconciliation, approval gating, source garbage collection, and effect-free replay. `proptest` exercises arbitrary templates and typed preservation. Language-neutral fixtures in `fixtures/compat` preserve the TypeScript oracle’s external graph/dataflow contract. `fuzz/` contains `cargo-fuzz` targets for workflow YAML/templates, provider responses, MCP/A2A payload shapes, persisted state, and tool schemas/inputs. They use no network or credentials. Example: @@ -30,7 +33,21 @@ cargo install cargo-fuzz cargo fuzz run workflow_yaml -- -max_total_time=60 ``` -The local hosted-CI configuration runs the canonical suite, credential-free acceptance, and packaging on Rust 1.88 for Linux x64, macOS arm64, and Windows x64. Separate automatic jobs cover the Linux x64 container, current vulnerability scan, two CycloneDX SBOM artifacts, complete-history/tree secret scans, dependency policy, and workflow lint. The workflows are locally linted but have not been pushed or dispatched, so this is configured evidence rather than validated hosted-platform support. Provider/protocol conformance uses local mock HTTP servers. Normal examples are deterministic; MCP/A2A runtime behavior is covered by mocks rather than requiring a background service. - -The only full live gate is the separately invoked OpenAI acceptance described in [Providers](/agentctl/providers/). It performs two bounded Responses API requests locally and two in the OCI image for one tool-call/continuation journey each, then performs keyless replays. Never run it for debugging loops, fuzzing, load, or normal CI. -> Canonical source: [`docs/TESTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/TESTING.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Hosted CI runs the canonical suite, credential-free acceptance, and packaging +on Rust 1.88 for Linux x64, macOS arm64, and Windows x64. Separate automatic +jobs cover the Linux x64 container, current vulnerability scan, two CycloneDX +SBOM artifacts, complete-history/tree secret scans, dependency policy, and +workflow lint. Exact-head pull-request and release-preparation runs provide +validated hosted-platform evidence. Provider/protocol conformance uses local +mock HTTP servers. Normal examples are deterministic; MCP/A2A runtime behavior +is covered by mocks rather than requiring a background service. + +Live gates are separately invoked and described in [Providers](/agentctl/providers/). +The original acceptance performs one tool-call/continuation journey locally +and in the image. `resource-budget-live-openai` performs exactly one provider +dispatch, then proves that the next requested effect is denied. +`examples-verify-live-openai` inventories and runs every OpenAI-backed example, +including the failed two-agent source, selective repair, and keyless replay, +with a 40-request and conservative USD 10 guard. Never run these commands for +debugging loops, fuzzing, load, or normal CI. +> Canonical source: [`docs/TESTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/TESTING.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/durable-execution/index.md b/src/content/docs/_generated/durable-execution/index.md index a32041f..b251aec 100644 --- a/src/content/docs/_generated/durable-execution/index.md +++ b/src/content/docs/_generated/durable-execution/index.md @@ -5,20 +5,76 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/DURABLE_EXECU --- SQLite is the local history and correctness boundary. Run, task, effect, approval, checkpoint, audit, provider-session, tool-call, and long-term-memory records are schema-versioned. Future database, runtime, plan, effect, or checkpoint versions fail explicitly instead of being ignored. +Each run also owns a durable resource ledger. Known provider, tool, process, +and artifact units are atomically reserved before fresh dispatch, then replaced +with actual usage. Parallel tasks share the same SQLite coordinator. The +wall-time deadline is derived from run creation, so pause and resume cannot +reset it. Recorded replay and reused retry or repair boundaries dispatch +nothing and consume no fresh effect units. See [Resource and cost +budgets](https://github.com/opensourceops/agentctl/blob/main/docs/guides/RESOURCE_BUDGETS.md). + ## Operations - Resume continues the same run from durable task state. Confirmed effects are reused. A requested-but-not-started effect may execute; a started-but-unconfirmed effect fails as uncertain. - Recorded replay creates a replay record from terminal stored outputs and calls no provider, tool, network, process, or filesystem executor. +- Terminal retry creates a new source-linked run for an identical workflow, materializes compatible successful boundaries, and executes failed or explicitly selected roots plus their descendants with fresh attempts. +- Selective repair creates a new source-linked run, materializes compatible successful task outputs and committed state deltas, then executes selected roots and descendants with fresh effects from a target workflow. +- Compensation creates a source-linked sequential run for explicitly declared inverse actions. Confirmed inverse effects append `compensated` reconciliations to immutable source effects; partial failures remain independently retryable. - Fork creates a new run linked to the old run and intentionally permits fresh effects. -- Retry creates a new task attempt only within the task’s explicit bound. An unsafe unresolved effect is not retried. +- A task's `retry` policy creates another attempt inside the same run only within its explicit bound. An unsafe unresolved effect is not retried. An effect ID is SHA-256 over run ID, task ID, task attempt, ordinal, operation, and input digest. Each record carries its format version, idempotency key, effect class, risk, status, request/result or error, timestamps, trace correlation, and confirmation flag. The request commits before the executor starts. This supports deterministic reuse of completed results but does not prove exactly-once behavior in an external system. -Pure operations need no external guarantee. Idempotent and keyed effects may be safely retried only when their implementation contract says so. Model calls and unknown remote mutations are treated at-most-once after start: a crash in the acknowledgement window creates an uncertain effect requiring operator reconciliation or an explicit fork. This is deliberately more conservative than silent at-least-once replay. +Pure operations need no external guarantee. Idempotent and keyed effects may be safely retried only when their implementation contract says so. Model calls and unknown remote mutations are treated at-most-once after start: a crash in the acknowledgement window creates an uncertain effect requiring operator reconciliation. Reconciliation appends an immutable `applied`, `not_applied`, or `compensated` conclusion with evidence; it does not rewrite the source effect. This is deliberately more conservative than silent at-least-once replay. + +Working-memory replacement, the task transition, checkpoint, and audit event commit in one SQLite transaction. Tool-effect and tool-call terminal status also commit together, so inspection cannot observe one as completed while the other remains started. On resume, a confirmed memory-write effect is applied to the reconstructed working-memory value during the succeeding transition. Long-term reads and retrievals are recorded observation effects; writes are recorded external mutations; explicit promotion is an internal-state effect. Replay reuses recorded retrieval output without calling the memory or embedding provider. Repair re-executes a selected retrieval boundary and can observe newer entries. Long-term memory is not rolled back by replay. + +Successful workspace mutations are ingested into the local content-addressed artifact store before task completion. Ingestion uses an atomic temporary file, SHA-256 identity, immutable deduplicated blobs, a cross-process lock, and a durable one-hour lease. Successful task completion then commits the artifact references with the definition fingerprint, resolved-input digest, output-contract fingerprint, output digest, immutable state delta and digest, audit event, and checkpoint, and releases the ingestion lease in the same SQLite transaction. Repair initialization starts from target initial memory and applies only reused successful task deltas in topological order. It never copies a terminal source's final memory snapshot. + +Retry and repair planning are effect-free. A source task is reusable only when its metadata version, definition, dependencies, resolved inputs, output contract/value, state delta, content-addressed artifacts, and effect certainty are compatible. Retry additionally requires the exact stored workflow digest; changed definitions require repair. The new run stores the reused result, artifact references, and provenance in its own rows, so later source-row or workspace deletion does not break it. Missing or corrupt CAS bytes block reuse before a run is created. + +Cancellation is both an injected token and a durable run flag. CLI SIGINT and SIGTERM cancel in-flight async calls and return exit `130`; `agentctl cancel` records a request for another process to observe. An overall CLI deadline can be set with `--timeout-seconds`, in addition to task/tool/provider/protocol bounds. A provider, tool, process, MCP, or A2A timeout/cancellation/transport loss after dispatch marks the effect `uncertain`; resume refuses to guess and requires reconciliation. An applied reconciliation supplies a validated recorded result. A not-applied or compensated reconciliation resumes with a fresh task and effect attempt. + +A repaired agent task starts a fresh provider session. Source +`previous_response_id`, stateless continuation items, incomplete turns, pending +tool calls, and reasoning state are not copied. Validated task output and +reconstructed memory are the only cross-task/cross-run dataflow. + +Clock and ID generation are injected; test providers/tools/protocol handlers +are injected. Ready tasks execute in bounded stable batches. Each reads a +persisted immutable memory snapshot, while task output, disjoint memory deltas, +artifacts, failures, audit events, and the checkpoint commit atomically in +compiled order. + +Static foreach and matrix declarations compile before a run is created. Every +expanded child is a normal durable task with its own attempts, effects, +fingerprint, output, retry/repair identity, and replay record. The parent is a +pure aggregate task that records child IDs, states, outputs, and errors in +stable expansion order. + +Condition transitions retain the expression, boolean result, and a canonical +digest of the evaluated inputs, variables, memory, and dependency outputs. +Pure router tasks retain their typed selected value and enumerated destination +IDs. Skipped branch records are copied directly by recorded replay and never +pass through a running state. + +Bounded loops compile into a fixed sequential chain of ordinary tasks plus a +pure aggregate. Each iteration retains its guard decision, output, effects, +artifacts, attempts, and recovery identity. A false guard skips the remaining +chain. A guard that remains true after the declared maximum fails closed. -Working-memory replacement, the task transition, checkpoint, and audit event commit in one SQLite transaction. Tool-effect and tool-call terminal status also commit together, so inspection cannot observe one as completed while the other remains started. On resume, a confirmed memory-write effect is applied to the reconstructed working-memory value during the succeeding transition. Long-term memory is an external effect and is not rolled back by replay. +Sub-workflows also compile before run creation. Typed input and output boundary +tasks surround namespaced child tasks, so child attempts, effects, artifacts, +approvals, retry/repair lineage, cancellation, and replay stay in the ordinary +run graph. -Cancellation is both an injected token and a durable run flag. CLI SIGINT and SIGTERM cancel in-flight async calls and return exit `130`; `agentctl cancel` records a request for another process to observe. An overall CLI deadline can be set with `--timeout-seconds`, in addition to task/tool/provider/protocol bounds. A provider, tool, process, MCP, or A2A timeout/cancellation/transport loss after dispatch marks the effect `uncertain`; resume refuses to guess and requires reconciliation or an explicit fork. +Compensation planning is effect-free. Only confirmed successful mutations or +effects reconciled as applied are eligible. Started and uncertain effects +require operator reconciliation. The generated compensation run uses reverse +compiled order, ordinary effect identities, policy, approvals, retries, +checkpoints, audit, and traces. A repeated plan excludes source effects already +reconciled as compensated. This is best-effort inverse execution, not +transactional rollback. -Clock and ID generation are injected; test providers/tools/protocol handlers are injected. The current scheduler is sequential, so output and memory commit order is task declaration order. -> Canonical source: [`docs/DURABLE_EXECUTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/DURABLE_EXECUTION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +The artifact root is `artifacts/` beside the database. `agentctl artifacts` lists references and blobs, verifies hashes, exports bytes atomically, and performs reachability-based collection. GC excludes referenced blobs and active ingestion leases, recovers interrupted quarantine operations on startup, and cleans stale untracked blobs and partial temporary files. +> Canonical source: [`docs/DURABLE_EXECUTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/DURABLE_EXECUTION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/approval-gated.md b/src/content/docs/_generated/examples/approval-gated.md index c61d9e4..2450bed 100644 --- a/src/content/docs/_generated/examples/approval-gated.md +++ b/src/content/docs/_generated/examples/approval-gated.md @@ -58,4 +58,4 @@ The approval includes redacted input, tool or action, capability, risk, expected ## Current limitation The CLI stores operator-provided identity text but does not provide a hosted identity or role system. The invoking platform must authenticate and authorize the operator. -> Canonical source: [`docs/use-cases/APPROVAL_GATED_ACTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/APPROVAL_GATED_ACTION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/APPROVAL_GATED_ACTION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/APPROVAL_GATED_ACTION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/ci-quality-gate.md b/src/content/docs/_generated/examples/ci-quality-gate.md index c16f9ba..4eddc87 100644 --- a/src/content/docs/_generated/examples/ci-quality-gate.md +++ b/src/content/docs/_generated/examples/ci-quality-gate.md @@ -57,9 +57,11 @@ The default exits `0` with verdict `pass`. Run with `--input checksPassed=false` ## State and security -Use ordinary typed inputs for non-secret gate evidence. Inject provider secrets only by environment reference. Archive the database on failure only when its potentially confidential content is protected. +Use ordinary typed inputs for non-secret gate evidence. Inject provider secrets +only through typed environment or mounted-file references. Archive the database +on failure only when its potentially confidential content is protected. ## Current limitation This workflow does not run tests itself. A surrounding pipeline can supply results, or a reviewed `builtin.shell.exec` action can run a specifically allowed executable. -> Canonical source: [`docs/use-cases/CI_QUALITY_GATE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/CI_QUALITY_GATE.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/CI_QUALITY_GATE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/CI_QUALITY_GATE.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/provider-portability.md b/src/content/docs/_generated/examples/provider-portability.md index 3f4d0ae..cfe24be 100644 --- a/src/content/docs/_generated/examples/provider-portability.md +++ b/src/content/docs/_generated/examples/provider-portability.md @@ -112,4 +112,4 @@ Both workflows share the provider-neutral agent shape. Each provider still needs ## Current limitation Provider portability does not mean identical behavior or equal maturity. Fake is deterministic, OpenAI has retained bounded live evidence, and Azure OpenAI, Anthropic, and Google are mock-protocol tested only in this release. -> Canonical source: [`docs/use-cases/PROVIDER_PORTABILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/PROVIDER_PORTABILITY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/PROVIDER_PORTABILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/PROVIDER_PORTABILITY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/recorded-replay.md b/src/content/docs/_generated/examples/recorded-replay.md index eeda88f..21dcbf7 100644 --- a/src/content/docs/_generated/examples/recorded-replay.md +++ b/src/content/docs/_generated/examples/recorded-replay.md @@ -60,4 +60,4 @@ Replay needs only the database, but the stored record may contain confidential i ## Current limitation Replay is not a new validation, retry, or exactly-once guarantee. It rejects non-terminal source runs. Use resume for safe continuation and fork only when fresh effects are intentional. -> Canonical source: [`docs/use-cases/RECORDED_REPLAY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/RECORDED_REPLAY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/RECORDED_REPLAY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/RECORDED_REPLAY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/release-readiness.md b/src/content/docs/_generated/examples/release-readiness.md index f537b7d..608bf05 100644 --- a/src/content/docs/_generated/examples/release-readiness.md +++ b/src/content/docs/_generated/examples/release-readiness.md @@ -81,4 +81,4 @@ The database records which gate failed and whether the analysis task started. A ## Current limitation The example uses the fake provider. It demonstrates graph and policy behavior, not a live model quality claim or a release approval system. -> Canonical source: [`docs/use-cases/RELEASE_READINESS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/RELEASE_READINESS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/RELEASE_READINESS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/RELEASE_READINESS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/repository-audit.md b/src/content/docs/_generated/examples/repository-audit.md index 7f04649..d4cb81e 100644 --- a/src/content/docs/_generated/examples/repository-audit.md +++ b/src/content/docs/_generated/examples/repository-audit.md @@ -121,4 +121,4 @@ The database records the provider session, strict tool call, read effect, assert ## Current limitation The checked journey proves orchestration and tool boundaries, not the quality of a live model's repository analysis. Production workflows need task-specific verification stronger than a fixed marker. -> Canonical source: [`docs/use-cases/REPOSITORY_AUDIT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/REPOSITORY_AUDIT.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/REPOSITORY_AUDIT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/REPOSITORY_AUDIT.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/examples/scheduled-review.md b/src/content/docs/_generated/examples/scheduled-review.md index 83dc3e6..a605d26 100644 --- a/src/content/docs/_generated/examples/scheduled-review.md +++ b/src/content/docs/_generated/examples/scheduled-review.md @@ -71,4 +71,4 @@ Persist the database and artifact directory with restrictive permissions. Config ## Current limitation `agentctl` is a schedulable runtime, not a scheduling service. It does not provide clocks, calendars, distributed leases, or log rotation. -> Canonical source: [`docs/use-cases/SCHEDULED_REVIEW.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/SCHEDULED_REVIEW.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/use-cases/SCHEDULED_REVIEW.md`](https://github.com/opensourceops/agentctl/blob/main/docs/use-cases/SCHEDULED_REVIEW.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/getting-started/first-agent.md b/src/content/docs/_generated/getting-started/first-agent.md index 053e3b7..b3969bd 100644 --- a/src/content/docs/_generated/getting-started/first-agent.md +++ b/src/content/docs/_generated/getting-started/first-agent.md @@ -84,4 +84,4 @@ The live command makes a paid network request to `api.openai.com` and writes pro ## Next step Read [Workflow authoring](/agentctl/guides/workflow-authoring/) to replace the scripted journey with your own reviewed workflow. -> Canonical source: [`docs/guides/FIRST_AGENT_WORKFLOW.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/FIRST_AGENT_WORKFLOW.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/FIRST_AGENT_WORKFLOW.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/FIRST_AGENT_WORKFLOW.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/getting-started/index.md b/src/content/docs/_generated/getting-started/index.md index a5f77c2..baf436c 100644 --- a/src/content/docs/_generated/getting-started/index.md +++ b/src/content/docs/_generated/getting-started/index.md @@ -87,4 +87,4 @@ If a command fails, read [Troubleshooting](/agentctl/troubleshooting/). ## Next step Run [your first bounded agent workflow](/agentctl/getting-started/first-agent/) without a paid API key. -> Canonical source: [`docs/guides/GETTING_STARTED.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/GETTING_STARTED.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/GETTING_STARTED.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/GETTING_STARTED.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/getting-started/installation.md b/src/content/docs/_generated/getting-started/installation.md index d980a31..7b99658 100644 --- a/src/content/docs/_generated/getting-started/installation.md +++ b/src/content/docs/_generated/getting-started/installation.md @@ -78,4 +78,4 @@ The workflow API is `agentctl.dev/v1alpha1`. Pin the CLI or image version, read ## Next step Continue with [Getting started](/agentctl/getting-started/). -> Canonical source: [`docs/guides/INSTALLATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/INSTALLATION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/INSTALLATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/INSTALLATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/guides/ci-cd.md b/src/content/docs/_generated/guides/ci-cd.md index cedbc56..88786e8 100644 --- a/src/content/docs/_generated/guides/ci-cd.md +++ b/src/content/docs/_generated/guides/ci-cd.md @@ -13,7 +13,7 @@ Every platform uses the same paths: | --- | --- | --- | | `/config` | read-only | reviewed workflow, inputs, and packs | | `/workspace` | normally read-only | checked-out source and fixtures | -| `/state` | writable and retained | SQLite database, resume, replay, approvals | +| `/state` | writable and retained | SQLite database, resume, replay, repair, approvals | | `/artifacts` | writable and collected | declared reports and outputs | Use `--output json --color never`. A successful workflow exits `0`. Validation exits `2`; policy or a pending approval exits `3`; run failure exits `4`; persistence exits `5`; provider or protocol failure exits `6`; cancellation exits `130`. @@ -45,12 +45,27 @@ Their current evidence level is documentation or syntax review unless stated oth ## Inputs and structured output -Mount an ordinary JSON file under `/config` and pass `--inputs-file /config/inputs.json`, or use repeated non-secret `--input KEY=VALUE`. Provider credentials must be environment references. Capture stdout as one `agentctl.dev/cli/v1` JSON envelope and archive declared files from `/artifacts`. +Mount an ordinary JSON file under `/config` and pass `--inputs-file +/config/inputs.json`, or use repeated non-secret `--input KEY=VALUE`. Provider +credentials must be typed environment or mounted-file references. Capture +stdout as one `agentctl.dev/cli/v1` JSON envelope and archive declared files +from `/artifacts`. ## Approvals in pipelines A non-interactive approval does not wait for stdin. It persists a request, exits `3`, and requires the same `/state` data in a later operator-controlled job. That job lists and resolves the approval, then calls `resume`. If your pipeline cannot retain protected state between jobs, configure policy to deny or fail instead of using approvals. +## Selective repair in pipelines + +Keep the failed terminal `/state` and durable workspace, publish a reviewed corrected workflow, and run an effect-free planning step first: + +```text +agentctl repair /config/repaired.yaml SOURCE_RUN_ID --from failed_task --plan \ + --workspace /workspace --db /state/runtime.db --output json --color never +``` + +Permit the execution step only when the plan exits `0` and the machine output's source run, target digest, roots, fresh effects, and approvals match the review. Exit `3` can also mean a blocked repair plan, so distinguish `kind: RepairPlan` from a pending run approval. Retain the new repair run ID as independent audit evidence. + ## Retention and recovery Collect `/state` even on failure when recovery or audit matters. It can contain confidential prompts and outputs, so apply protected artifact access and a short, documented retention period. Keep `/artifacts` according to the report's classification. @@ -63,8 +78,8 @@ Do not set a pipeline retry policy that blindly repeats exit `5`, `6`, or `130`. - Run as non-root with a read-only root filesystem. - Drop capabilities and deny unneeded egress. - Mount the workspace read-only unless a reviewed write is required. -- Inject secrets by environment reference and never echo them. +- Inject secrets by environment reference or read-only mounted file and never echo them. - Treat remote content and model output as untrusted. - Retain state for approval or recovery, then delete it under policy. - Set the external platform's overlap and timeout controls. -> Canonical source: [`docs/guides/CI_CD.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/CI_CD.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/CI_CD.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/CI_CD.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/guides/container.md b/src/content/docs/_generated/guides/container.md index 6cd8e7c..8bb6e0e 100644 --- a/src/content/docs/_generated/guides/container.md +++ b/src/content/docs/_generated/guides/container.md @@ -5,6 +5,15 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/CONTAINER.md" --- The repository `Containerfile` builds the Rust CLI in a pinned Rust 1.88 builder and copies only the optimized binary into a maintained distroless Debian runtime. The runtime has CA roots, version/source/license OCI labels, runs as `nonroot`, has a deterministic `agentctl` entrypoint, and contains no Node.js runtime, TypeScript source, credentials, workflows, or fixtures. +This whole-workflow OCI step is distinct from action-level process isolation. +An action with `isolation: container` asks the host agentctl process to invoke +a locally available digest-pinned image through Docker or Podman. That action +receives a read-only working-directory mount, no network, a read-only root, +non-root UID/GID 65532, dropped capabilities, `no-new-privileges`, a bounded +temporary filesystem, and explicit memory/CPU/PID/output/time limits. The +engine and exact image are preflighted and never fall back to host execution. +See [Process isolation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PROCESS_ISOLATION.md). + ## Optional build-network CA The default build uses the builder's public CA roots. Networks that intercept TLS may supply a reviewed public CA certificate or bundle through a build secret: @@ -14,22 +23,51 @@ docker build --secret id=agentctl_ca,src=/protected/path/build-ca.pem \ --tag agentctl:local --file Containerfile . ``` -For the repository acceptance wrapper, set `AGENTCTL_BUILD_CA_FILE=/protected/path/build-ca.pem` before `cargo xtask acceptance-container`. Hosted CI accepts the protected secret `AGENTCTL_BUILD_CA_PEM`, materializes it only in the runner's temporary directory, and removes it after the build. +For the repository acceptance wrapper, set `AGENTCTL_BUILD_CA_FILE=/protected/path/build-ca.pem` before `cargo xtask acceptance-container`. Hosted `main` and manually dispatched runs accept the protected secret `AGENTCTL_BUILD_CA_PEM`, materialize it only in the runner's temporary directory, and remove it after the build. Pull-request runs never receive that secret. The `Containerfile` combines the secret with public roots on a tmpfs mount for the single Cargo build step. The CA value is not a build argument, image environment value, build-context file, layer, history value, runtime file, or artifact. Never use `--insecure`, `CARGO_HTTP_CHECK_REVOKE=false`, a TLS-verification disable flag, or a committed certificate. +Runtime TLS interception is separate from build TLS. Mount a reviewed +certificate-only PEM bundle read-only, authorize its parent under +`secretFileRoots`, and reference it through `policy.network.customCa`: + +```yaml +spec: + policy: + secretFileRoots: [/run/agentctl-ca] + networkAllowlist: [api.internal.example] + network: + allowedSchemes: [https] + allowedPorts: [443] + customCa: { file: /run/agentctl-ca/runtime-ca.pem } +``` + +The adapter adds the bundle to rustls in memory. The bundle is not copied into +SQLite, effects, traces, or artifact storage. Invalid, empty, private-key, or +mixed-object PEM input fails before dispatch. See [Network +policy](https://github.com/opensourceops/agentctl/blob/main/docs/guides/NETWORK_POLICY.md). + ## Mounts and inputs | Path | Contract | | --- | --- | | `/config` | read-only reviewed workflow and pack configuration | | `/workspace` | usually read-only source/fixture workspace | -| `/state` | writable SQLite database and durable recovery state | -| `/artifacts` | writable declared workflow artifacts | - -Pass workflow values with repeated `--input KEY=VALUE`, `--inputs-file`, or `--inputs` JSON. Prefer files for large or sensitive non-provider inputs. Provider credentials are environment references only; never put a key in CLI arguments, YAML, an image layer, or an ordinary input value. Before a bind-mount run, provision `/state` and `/artifacts` host directories so UID/GID 65532 can write them and the runner's artifact collector can read them. Durable state may contain prompts and outputs; protect it like a sensitive build artifact. - -The image emits exactly one versioned JSON result on stdout with `--output json`; failures emit one versioned JSON error on stderr. The document includes exit status semantics, run/trace IDs, final state, and declared outputs. Progress is not mixed into stdout. Persist `/state` for later `inspect`, approval resolution, `resume`, or `replay`. +| `/state` | writable SQLite database, CAS blobs, and durable recovery state | +| `/artifacts` | writable declared workflow output/export surface | + +Pass workflow values with repeated `--input KEY=VALUE`, `--inputs-file`, or +`--inputs` JSON. Prefer files for large or sensitive non-provider inputs. +Provider credentials may reference a forwarded environment name or a read-only +mounted file under an explicit `secretFileRoots` policy. Never put a key in CLI +arguments, YAML, an image layer, or an ordinary input value. Before a bind-mount +run, provision `/state` and `/artifacts` host directories so UID/GID 65532 can +write them. Successful bounded workflow files are copied into +`/state/artifacts/sha256`; `/artifacts` remains the convenient CI collection +surface. Durable state may contain prompts, outputs, and artifact bytes; +protect it like a sensitive build artifact. + +The image emits exactly one versioned JSON result on stdout with `--output json`; failures emit one versioned JSON error on stderr. The document includes exit status semantics, run/trace IDs, final state, and declared outputs. Progress is not mixed into stdout. Persist `/state` for later `inspect`, approval resolution, `resume`, `replay`, or `repair`. ## Verified Docker/Podman invocation @@ -49,6 +87,40 @@ docker run --rm --read-only --user 65532:65532 \ The value form `--env OPENAI_API_KEY` forwards an already protected host variable without placing its value in the command. The credential-free container acceptance uses the same command with the fake provider and without that environment variable. +For a container-native secret file, configure +`credential: { file: /run/secrets/openai }` and +`secretFileRoots: [/run/secrets]`, then replace the environment forwarding with +a read-only mount: + +```console +docker run --rm --read-only --user 65532:65532 \ + --tmpfs /tmp:rw,noexec,nosuid,size=16m \ + --mount type=bind,src="$PWD/config",dst=/config,readonly \ + --mount type=bind,src="$PWD/workspace",dst=/workspace,readonly \ + --mount type=bind,src="$PWD/state",dst=/state \ + --mount type=bind,src="$PWD/openai.key",dst=/run/secrets/openai,readonly \ + ghcr.io/OWNER/agentctl:0.2.0 \ + run /config/workflow.yaml --workspace /workspace --db /state/runtime.db \ + --output json --color never +``` + +The file is read at bounded credential preflight and its value is never copied +to the state mount. See [Secret references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). + +For selective repair, mount the corrected workflow under `/config` and keep the source database plus its `/state/artifacts` CAS under `/state`. The original workspace output can be absent after successful ingestion. Plan without forwarding provider credentials: + +```console +docker run --rm --read-only --user 65532:65532 --network none \ + --mount type=bind,src="$PWD/config",dst=/config,readonly \ + --mount type=bind,src="$PWD/workspace",dst=/workspace,readonly \ + --mount type=bind,src="$PWD/state",dst=/state \ + ghcr.io/OWNER/agentctl:0.2.0 \ + repair /config/repaired.yaml SOURCE_RUN_ID --from failed_task --plan \ + --workspace /workspace --db /state/runtime.db --output json --color never +``` + +The execution invocation may forward only credentials required by tasks in the fresh closure. Reused tasks do not access them. The container acceptance suite executes a credential-free repair under the same non-root, read-only-root, and mounted-state contract. + ## Pipeline examples All examples use the same image/entrypoint contract. Replace the image owner/tag and arrange the four host paths using the platform's storage mechanism. Exit `3` means approval is durably pending: retain the state directory as a protected artifact or persistent volume, resolve the approval in an operator-controlled job, and resume against that same state. Discarding the state directory makes resume impossible. @@ -190,7 +262,13 @@ The surrounding Harness stage must publish `/harness/.agentctl-state` and `/harn ### Kubernetes Job or CronJob -Use ConfigMaps for reviewed configuration, a PVC for `/state` when recovery across Pods matters, a PVC or artifact uploader for `/artifacts`, and a Secret environment reference for credentials. The container security context should set `runAsNonRoot`, UID/GID 65532, no privilege escalation, dropped capabilities, and a read-only root filesystem. A CronJob should normally set `concurrencyPolicy: Forbid`; see [Operations](/agentctl/operations/scheduled/). +Use ConfigMaps for reviewed configuration, a PVC for `/state` when recovery +across Pods matters, a PVC or artifact uploader for `/artifacts`, and either a +Secret environment reference or a projected read-only Secret volume for +credentials. The container security context should set `runAsNonRoot`, UID/GID +65532, no privilege escalation, dropped capabilities, and a read-only root +filesystem. A CronJob should normally set `concurrencyPolicy: Forbid`; see +[Operations](/agentctl/operations/scheduled/). ```yaml apiVersion: batch/v1 @@ -265,5 +343,21 @@ For a one-time invocation, use the same Pod template in a `batch/v1` `Job` and o ## Validation level -The current native-arm image was built through the optional secret-mounted CA path and executed with Podman as non-root with a read-only root. The suite exercised a mock tool workflow, artifact and durable inspection, missing-secret and invalid-workflow exit propagation, SIGTERM, and recorded replay under `--network none`. Checksum-verified Trivy 0.72.0 found zero fixed HIGH/CRITICAL findings and generated valid CycloneDX JSON. The exact retained GPT-5.6 live database had previously replayed with no credential and no network, identical output and artifact digest, zero fresh effects/tool calls/provider sessions, and explicit source-effect audit links. GitHub, GitLab, Jenkins, Harness, and Kubernetes examples remain documentation-reviewed only; the automatic Ubuntu Linux x64 build, scan, and SBOM job is locally linted but has not been dispatched. -> Canonical source: [`docs/CONTAINER.md`](https://github.com/opensourceops/agentctl/blob/main/docs/CONTAINER.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +On 2026-07-27, the current native-arm image built and passed the complete +credential-free Podman gate as non-root with a read-only root. The suite +exercised a real digest-pinned action container, a mock tool workflow, artifact +export and durable inspection, parallel ordered commit, selective repair, +missing-secret and invalid-workflow exits, SIGTERM, and recorded replay under +`--network none`. Trivy 0.72.0 with a freshly updated database found zero fixed +HIGH/CRITICAL findings and generated valid CycloneDX JSON with 11 components. +Image configuration and history scans found no credential or authorization +markers. + +The exact retained GPT-5.6 live database had previously replayed with no +credential and no network, identical output and artifact digest, zero fresh +effects/tool calls/provider sessions, and explicit source-effect audit links. +GitLab, Jenkins, Harness, and Kubernetes examples remain +documentation-reviewed only. The automatic Ubuntu Linux x64 build, scan, and +SBOM job passed on the exact pull-request head and retained its image SBOM +artifact and digest. +> Canonical source: [`docs/CONTAINER.md`](https://github.com/opensourceops/agentctl/blob/main/docs/CONTAINER.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/guides/local-operation.md b/src/content/docs/_generated/guides/local-operation.md index b5bfde3..da0e1bf 100644 --- a/src/content/docs/_generated/guides/local-operation.md +++ b/src/content/docs/_generated/guides/local-operation.md @@ -3,7 +3,7 @@ title: "Local operation" description: "Manage paths, state, outputs, interruption, recovery, and retention." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/guides/LOCAL_OPERATION.md" --- -Use explicit paths and retain the database whenever you may need inspection, approval, resume, replay, or audit evidence. +Use explicit paths and retain the database whenever you may need inspection, approval, resume, replay, repair, or audit evidence. ## Default and custom paths @@ -22,7 +22,9 @@ This writes the SQLite database and any declared artifacts. Network calls occur Human output is for terminals. `--output json --color never` emits one versioned final document on stdout; an error uses the same envelope shape on stderr. Exit codes distinguish success, validation, policy or approval, run failure, persistence, remote failure, and cancellation. -JSONL progress output is not supported in this release. Use durable audit and trace records for event-level inspection. +`--output jsonl` emits durable provider stream events followed by the final +outcome. Human stream progress uses stderr. Use `--output json` when an +automation requires exactly one final document. ## Interrupt safely @@ -37,14 +39,15 @@ agentctl approvals list RUN_ID --db /var/lib/agentctl/runtime.db --output json - Use the run ID and trace ID when correlating logs. Treat database output as sensitive because prompts, file content, tool output, and remote artifacts may be present even when secret values were redacted. -## Resume, replay, retry, and fork +## Resume, replay, retry, repair, and fork - Resume continues the same non-terminal run and reuses confirmed effects. - Retry is bounded within a task and never guesses about an ambiguous effect. - Recorded replay creates a new record from terminal stored results and calls no executor. +- Repair creates a new source-linked run, reuses only compatible successful tasks before selected roots, and executes every root and descendant from a supplied target workflow. - Fork creates a new child run and permits fresh effects. -Do not use these terms interchangeably. Read [Durable execution](/agentctl/durable-execution/) before recovering a workflow that may have changed an external system. +Do not use these terms interchangeably. Read [Durable execution](/agentctl/durable-execution/) before recovering a workflow that may have changed an external system. For a corrected terminal workflow, follow [Repair a failed workflow](/agentctl/guides/selective-repair/). ## Resolve an approval @@ -70,4 +73,4 @@ agentctl gc --db .agentctl/runtime.db --older-than-days 30 --output json --color ``` Garbage collection deletes eligible terminal history and expired long-term memory. Back up before deletion when the history is audit evidence. -> Canonical source: [`docs/guides/LOCAL_OPERATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/LOCAL_OPERATION.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/LOCAL_OPERATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/LOCAL_OPERATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/guides/selective-repair.md b/src/content/docs/_generated/guides/selective-repair.md new file mode 100644 index 0000000..2f21837 --- /dev/null +++ b/src/content/docs/_generated/guides/selective-repair.md @@ -0,0 +1,200 @@ +--- +title: "Repair a failed workflow" +description: "Reuse compatible upstream results and safely execute a corrected suffix." +editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/guides/repair-a-failed-workflow.md" +--- +Suppose `analyze` and `publish` are agent tasks. `analyze` succeeded and stored validated JSON. `publish` called its read-only tool but failed because its turn limit was too small. You corrected only `publish`. + +Do not resume the failed terminal run. Resume continues the same non-terminal run with the same compiled definition. Do not replay it to execute the fix. Recorded replay copies terminal recorded results and emits no fresh effects. Use repair to create a linked run that reuses compatible `analyze` data and executes `publish` plus its descendants from the corrected workflow. + +The runnable example is in [`examples/selective-repair-openai/`](https://github.com/opensourceops/agentctl/blob/main/examples/selective-repair-openai/README.md). + +## 1. Understand the failed source + +```mermaid +flowchart LR + A["analyze
succeeded
structured output stored"] --> B["publish
failed after tool call"] + B -. blocked .-> C["verify
not run"] + C -. blocked .-> D["artifact
not written"] +``` + +Inspect the failed run: + +```bash +agentctl inspect SOURCE_RUN_ID \ + --db .agentctl/runtime.db \ + --output json \ + --color never +``` + +Confirm that the source is terminal, `analyze` is `succeeded`, `publish` is `failed`, and any partial effects are understood. + +## 2. Fix task 2 and plan + +Increase the turn limit or correct the task instructions, prompt file, tool configuration, implementation, timeout, or output contract in the target workflow. Then plan without calling a provider or tool: + +```bash +agentctl repair repaired.workflow.yaml SOURCE_RUN_ID \ + --from publish \ + --plan \ + --db .agentctl/runtime.db \ + --output json \ + --color never +``` + +```mermaid +flowchart TD + S["Terminal source run"] --> C["Compile source and target graphs"] + C --> R["Roots: publish"] + R --> D["Closure: publish, verify, artifact"] + C --> U["Candidate reuse: analyze"] + U --> K{"All compatibility checks pass?"} + K -->|yes| P["Plan: analyze reused"] + K -->|no| X["Block before run creation"] + D --> E["Plan: closure executes freshly"] +``` + +The plan reports source and target workflow digests, roots, reused and rerun tasks, new/removed/changed tasks, blocked checks, estimated provider tasks, fresh effects, and possible approvals. A compatible plan exits `0`. A blocked plan is still valid JSON and exits `3`. + +For independent failed branches, repeat the root: + +```bash +agentctl repair workflow.yaml SOURCE_RUN_ID \ + --from analyze_a \ + --from analyze_b \ + --plan +``` + +A source task that already succeeded can be a fresh root only with `--restart-successful`. + +## 3. How upstream reuse works + +```mermaid +flowchart LR + SO["Source analyze result"] --> V["Verify metadata v1"] + V --> F["Definition and prompt fingerprint"] + F --> I["Resolved input and dependency digest"] + I --> O["Output contract and output digest"] + O --> M["State delta digest"] + M --> A["Artifact path, size, SHA-256"] + A --> N["Materialize succeeded/reused task
attempt 0, source provenance"] +``` + +The runtime starts from target initial memory, visits reusable tasks in deterministic topological order, materializes their outputs, and applies only their committed successful state deltas. It does not copy the source run's final memory snapshot. Failed task-local state and invalidated downstream state are excluded. + +Agent tasks that feed downstream tasks need an explicit structured output contract through agent `structuredOutput` or task `outputSchema`. Built-in actions use their runtime-owned JSON output contract when a more specific schema is not needed. Outputs are validated at completion and again before reuse. + +## 4. Downstream invalidation + +```mermaid +flowchart TD + P["prepare"] --> A["analyze_a"] + P --> B["analyze_b
repair root"] + A --> C["combine"] + B --> C + classDef reused fill:#e8f5e9,stroke:#2e7d32 + classDef fresh fill:#fff3e0,stroke:#ef6c00 + class P,A reused + class B,C fresh +``` + +Every root and transitive descendant executes. Tasks outside that union are candidates for reuse, not automatically reusable. A new descendant executes. A new unrelated task blocks and asks for another or earlier root. A removed unreferenced task is reported but does not block. + +## 5. Execute and inspect + +```bash +agentctl repair repaired.workflow.yaml SOURCE_RUN_ID \ + --from publish \ + --reason "raise publish turn limit after read-only call" \ + --db .agentctl/runtime.db \ + --output json \ + --color never +``` + +```mermaid +flowchart LR + S["Source run
failed, immutable"] -->|sourceRunId| R["Repair run
new run and trace IDs"] + S1["source analyze attempt 1"] -->|provenance| R1["repair analyze
succeeded / reused / attempt 0"] + R1 --> R2["repair publish
succeeded / executed"] + R2 --> R3["repair descendants
executed"] +``` + +The result includes the new repair run ID, source run ID, trace ID, reused tasks, executed tasks, final state, and workflow outputs. `inspect` exposes run lineage and each task's disposition, source attempt, fingerprints, output/state/artifact digests, and reuse decision. Reused tasks create no provider session, tool call, process, network call, or effect row in the repair run. + +The repair run materializes reused task output and state metadata in its own rows. Deleting the source database rows later does not break repair inspection or recorded replay. Artifact bytes must remain in the configured durable workspace and are verified before reuse. + +## 6. Understand fresh-effect safety + +```mermaid +flowchart TD + E["Prior effect in repair closure"] --> C{"Effect class"} + C -->|model, observe, pure| F["Fresh execution permitted"] + C -->|mutation or remote action| S{"Recorded outcome"} + S -->|confirmed idempotent| F + S -->|failed before dispatch| F + S -->|started or uncertain| B["Block repair"] + S -->|confirmed non-idempotent| B + B --> I["Inspect effect and reconcile external reality"] + I --> N{"Confirmed not applied?"} + N -->|yes| R["Reconcile as not-applied, then re-plan"] + N -->|no or unknown| H["Choose a safe business remediation
or broader fresh execution"] +``` + +List effects for the failed boundary, then inspect the selected effect: + +```bash +agentctl effects --db .agentctl/runtime.db list SOURCE_RUN_ID --task publish +agentctl effects --db .agentctl/runtime.db inspect EFFECT_ID +``` + +If an effect is `started` or `uncertain` and an operator has verified that it did not happen: + +```bash +agentctl effects --db .agentctl/runtime.db reconcile EFFECT_ID \ + --status not-applied \ + --reason "remote system confirms no record" \ + --actor operator-name +``` + +Use `--status applied --result-file result.json` when the effect happened and resume needs its externally confirmed result. Use `--status compensated --compensation-effect EFFECT_ID` only after a distinct compensation effect is confirmed. There is no generic force option and no exactly-once claim. An applied non-idempotent effect stays blocked from duplicate fresh execution until it has a valid compensation record. Normal policy, approval, timeout, retry, and cancellation behavior applies to every fresh task. See [Effect reconciliation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/EFFECT_RECONCILIATION.md). + +A repaired agent begins a new provider session. It receives target instructions +and tools plus validated upstream output and reconstructed memory. It never +receives the failed source task's `previous_response_id`, stateless +continuation items, incomplete turn, pending call, or reasoning state. Within +the new repaired task, normal multi-turn continuation still applies. + +## 7. Replay the repaired result offline + +After a successful repair: + +```bash +env -u OPENAI_API_KEY agentctl replay REPAIR_RUN_ID \ + --db .agentctl/runtime.db \ + --output json \ + --color never +``` + +Recorded replay has a new replay run ID but the same semantic outputs. It dispatches zero fresh effects and does not rewrite artifacts. + +## Troubleshooting blocked plans + +| Block | Meaning | Next action | +| --- | --- | --- | +| `repair_root_missing` | The root is absent from the target graph. | Correct the task ID or workflow. | +| `successful_root_requires_acknowledgement` | The selected root succeeded. | Add `--restart-successful` only when fresh execution is intended. | +| `definition_fingerprint_mismatch` | A task changed outside the rerun closure. | Choose that task as an earlier/additional root. | +| `dependency_set_mismatch` | A reusable task has different upstream dependencies. | Select the changed consumer as another repair root. | +| `resolved_input_digest_mismatch` | Inputs, dependency output, or boundary memory changed. | Choose the first affected task as a root. | +| `missing_output_contract` | A reused agent feeds downstream work without typed output. | Add structured output and create a fresh source result. | +| `output_contract_mismatch` | The target expects a different contract. | Rerun from the producer. | +| `output_digest_mismatch` | Persisted output was modified or corrupted. | Do not reuse it; rerun from the producer. | +| `state_delta_missing` or `state_delta_invalid` | Successful boundary-state metadata is absent or corrupt. | Select the task as an earlier root; do not edit the database. | +| `artifact_integrity` | A content-addressed artifact is missing or corrupt. The block reports its logical path, expected digest, and expected size. | Restore the database and sibling CAS from a consistent backup, or select its producer as an earlier repair root. | +| `unresolved_reused_effect` | A nominally successful reusable task retains a started or uncertain effect. | Reconcile external reality before reuse. | +| `legacy_task_metadata` | The source predates repair metadata v1. | Run `agentctl runs analyze` and `runs upgrade`, then use the reported safe root. | +| `new_task_outside_repair_closure` | A new unrelated task has no result. | Add it as a root or choose an earlier common boundary. | +| `unreconciled_effect` | Fresh execution may duplicate a mutation. | Inspect and reconcile external reality first. | + +Use [`agentctl retry`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/TERMINAL_RETRY.md) instead when the workflow definition is unchanged and the intent is to rerun failed or explicitly selected boundaries of a terminal source. Use repair for a corrected definition and fork for a broader intentionally fresh execution. +> Canonical source: [`docs/guides/repair-a-failed-workflow.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/repair-a-failed-workflow.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/guides/workflow-authoring.md b/src/content/docs/_generated/guides/workflow-authoring.md index 6e09f1b..0ff2c2f 100644 --- a/src/content/docs/_generated/guides/workflow-authoring.md +++ b/src/content/docs/_generated/guides/workflow-authoring.md @@ -88,6 +88,8 @@ agents: The model does not own the graph, policy, or persistence. +When an agent result feeds another task, declare `structuredOutput` as a JSON Schema. It becomes the task's durable output contract and lets selective repair verify and reuse the result. A task-level `outputSchema` is available when the complete task contract must differ from the agent or action default. + ## 7. Define tool contracts A model sees only tools listed on its agent. Each tool requires strict input and output schema, capability, risk, effect class, idempotency, retry safety, timeout, and approval requirement. Runtime policy makes the final authorization decision. @@ -111,7 +113,7 @@ Start with the minimum grant. Add a host, writable root, executable, or secret n ## 10. Plan for state and recovery -Choose an explicit database path for scheduled or CI runs. A confirmed effect can be reused during resume. An effect that started without a confirmed result becomes uncertain and stops automatic recovery. Recorded replay calls no executor. Fork intentionally permits fresh effects. +Choose an explicit database path for scheduled or CI runs. A confirmed effect can be reused during resume. An effect that started without a confirmed result becomes uncertain and stops automatic recovery. Recorded replay calls no executor. Repair can reuse compatible successful task boundaries and execute a corrected suffix. Fork intentionally permits a broader fresh execution. ## Validate your workflow @@ -124,4 +126,4 @@ agentctl run workflow.yaml --check --diff --db .agentctl/preview.db ``` The preview may write run history to its database, but it does not perform filesystem, process, remote, or model mutation. Read [Workflow DSL](/agentctl/concepts/workflow-model/) and the [YAML reference](/agentctl/reference/yaml/) for the complete contract. -> Canonical source: [`docs/guides/WORKFLOW_AUTHORING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/WORKFLOW_AUTHORING.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/WORKFLOW_AUTHORING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/WORKFLOW_AUTHORING.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/observability/index.md b/src/content/docs/_generated/observability/index.md index eddc8da..de233f5 100644 --- a/src/content/docs/_generated/observability/index.md +++ b/src/content/docs/_generated/observability/index.md @@ -13,7 +13,11 @@ Human output is the default for interactive use. For automation, use one version agentctl run workflow.yaml --db .agentctl/runtime.db --output json --color never ``` -Success writes an `agentctl.dev/cli/v1` envelope to stdout. Failure writes the same envelope shape to stderr and returns a typed exit code. Run-scoped results include run and trace IDs. JSONL progress streaming is not implemented in this release; do not parse human output or assume that each line is an event. +Success writes an `agentctl.dev/cli/v1` envelope to stdout. Failure writes the +same envelope shape to stderr and returns a typed exit code. Run-scoped results +include run and trace IDs. `--output jsonl` emits versioned durable +`StreamEvent` envelopes followed by the final outcome. Human provider progress +uses stderr. `--output json` remains one final document. ## Durable inspection @@ -24,7 +28,7 @@ agentctl inspect RUN_ID --db .agentctl/runtime.db --output json --color never agentctl db stats --db .agentctl/runtime.db --output json --color never ``` -Inspection includes task attempts, checkpoints, effect state, approvals, provider and protocol records, ordered audit events, and trace correlation. Use `agentctl approvals list RUN_ID` when the run exited pending approval. Preserve the database and its WAL files together when the history is operational evidence. +Inspection includes task attempts, disposition, repair source/roots, per-task reuse provenance and compatibility evidence, fingerprints/digests, checkpoints, effect state, approvals, the run budget snapshot, bounded provider stream events, provider and protocol records, ordered audit events, and trace correlation. A reused task emits a durable `task.reused` trace event and `repair.task_reused` audit event but no fresh effect, provider-session, tool-call, or budget usage. Use `agentctl approvals list RUN_ID` when the run exited pending approval. Preserve the database and its WAL files together when the history is operational evidence. ## Runtime events @@ -36,7 +40,11 @@ OpenTelemetry export is an embedding concern in this release; the standalone CLI ## Metrics and interpretation -Usage maps input, output, reasoning, cache-read, and cache-write tokens where providers expose them. Duration, attempts, provider errors, retries, approval waits, tool counts, and action change status are available from trace and audit events. Price calculation is not fabricated when no reliable price metadata exists. +Usage maps provider requests, turns, tool calls, input, output, reasoning, +cache-read, cache-write, process output, artifact bytes, wall time, and +monetary cost where the necessary data exists. Price calculation is not +fabricated when neither reliable provider metadata nor explicit versioned +custom pricing exists. When diagnosing a failure, correlate the final envelope's run and trace IDs with the persisted task, attempt, effect, and provider records. A model response is not proof that an external effect completed; use the effect record and its confirmation state. @@ -44,7 +52,12 @@ When diagnosing a failure, correlate the final envelope's run and trace IDs with Sensitive field names and registered secret values are redacted before trace attributes leave the runtime. Provider response content is not printed by the live smoke. Operators must still treat trace backends and the local database as sensitive because prompts, file content, tool output, and remote artifacts may contain confidential non-secret data. -Keep provider credentials in environment references, never workflow inputs or command arguments. Apply access control and retention to the database, collected artifacts, CI logs, and trace backend. Before sharing diagnostics, remove credentials, prompt content, file content, remote payloads, and identifying metadata; a run ID alone is sufficient for local correlation. +Keep provider credentials in typed environment, mounted-file, or policy-gated +process references, never workflow inputs or command arguments. Apply access +control and retention to the database, collected artifacts, CI logs, and trace +backend. Before sharing diagnostics, remove credentials, prompt content, file +content, remote payloads, and identifying metadata; a run ID alone is +sufficient for local correlation. See [CLI output and exit codes](/agentctl/reference/output/), [local operation](/agentctl/guides/local-operation/), and [runtime database and migrations](/agentctl/reference/database/) for the complete operating contract. -> Canonical source: [`docs/OBSERVABILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/OBSERVABILITY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/OBSERVABILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/OBSERVABILITY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/operations/scheduled.md b/src/content/docs/_generated/operations/scheduled.md index 184b38a..2755ed9 100644 --- a/src/content/docs/_generated/operations/scheduled.md +++ b/src/content/docs/_generated/operations/scheduled.md @@ -63,8 +63,12 @@ A oneshot service has one active invocation at a time. Use distinct databases on 2. Run `agentctl inspect RUN_ID --db PATH --output json`. 3. Resolve a pending approval, then `resume`; never use `fork` as an implicit retry. 4. Use `replay` for a no-effect reconstruction of a terminal run. -5. Use `fork` for a new run that may execute fresh effects. -6. For an uncertain effect, reconcile the remote system first. The runtime intentionally refuses unsafe resume. +5. Use `repair TARGET SOURCE --from TASK --plan` before executing a corrected terminal workflow from a task boundary. +6. Use `fork` for a broader new run that may execute fresh effects. +7. For an uncertain effect, reconcile the remote system first. The runtime intentionally refuses unsafe resume or repair. +8. Verify retained bytes with `agentctl artifacts --db PATH verify --all`; export a digest with `agentctl artifacts --db PATH export DIGEST DESTINATION`. -Use `agentctl gc --db PATH --older-than-days N` for expired memory and old terminal histories after the organization's retention/backup requirements are satisfied. SQLite WAL files belong with the database during backup. A future schedule-run key may improve deduplication; today the external scheduler owns overlap prevention. -> Canonical source: [`docs/OPERATIONS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/OPERATIONS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Repair planning exits `3` when compatibility or effect safety blocks reuse. Read `blockedReuse`, choose an earlier/additional root, restore a verified artifact, or reconcile an effect. Do not bypass the plan with a fresh fork unless repeating all effects is an intentional operator decision. + +Use `agentctl gc --db PATH --older-than-days N` for expired memory and old terminal histories. Then use `agentctl artifacts --db PATH gc --older-than-days N --dry-run` to preview unreferenced blobs before running it without `--dry-run`. SQLite WAL files and the sibling artifact root belong together during backup. A future schedule-run key may improve deduplication; today the external scheduler owns overlap prevention. +> Canonical source: [`docs/OPERATIONS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/OPERATIONS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/providers/a2a.md b/src/content/docs/_generated/providers/a2a.md index ebe8180..8441e21 100644 --- a/src/content/docs/_generated/providers/a2a.md +++ b/src/content/docs/_generated/providers/a2a.md @@ -3,9 +3,32 @@ title: "A2A" description: "Delegate bounded work to pinned A2A peers." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/A2A.md" --- -The client pins [A2A `1.0`](https://a2a-protocol.org/latest/specification/) and discovers an Agent Card. It selects a JSON-RPC interface advertising version `1.0`, then supports `SendMessage`, bounded `GetTask` polling, `CancelTask`, SSE task updates, terminal success/failure/cancel states, messages, structured parts, and artifacts. +The client pins [A2A `1.0`](https://a2a-protocol.org/latest/specification/) and discovers an Agent Card. It selects a same-origin JSON-RPC interface advertising version `1.0`, then supports `SendMessage`, bounded `GetTask` polling, `SubscribeToTask` SSE updates, `CancelTask`, terminal states, messages, structured parts, and artifacts. -Card and RPC authentication headers are environment secret references. The card URL is subject to network policy, redirects are disabled, and the selected JSON-RPC interface must have the same scheme, host, and effective port as that reviewed card URL. Cards, skills, messages, parts, and artifacts are untrusted data. An A2A delegation is a `remote_agent` effect and may require approval. +Card and RPC authentication headers are secret references resolved at dispatch and refreshed once after `401`. The card URL is subject to network policy, redirects are disabled, and the selected interface must have the same scheme, host, and effective port as that reviewed card URL. Cards, skills, messages, parts, and artifacts are untrusted data. An A2A delegation is an `at_most_once` `remote_agent` effect and may require approval. -Polling is bounded; request and overall operation timeouts and cancellation are enforced. The client does not claim delivery exactly once or transparently resubmit after an ambiguous response. Mock peers cover discovery, SendMessage/GetTask, artifacts, streaming parsing, cancellation mapping, protocol mismatch, failure, and timeout at the declared maturity. -> Canonical source: [`docs/A2A.md`](https://github.com/opensourceops/agentctl/blob/main/docs/A2A.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Configure observation bounds explicitly when the defaults are unsuitable: + +```yaml +a2aPeers: + worker: + cardUrl: https://agents.example.test/card.json + protocolVersion: "1.0" + timeoutSeconds: 10 + maxPolls: 100 + pollIntervalMs: 100 +``` + +The runtime persists the call identity and remote task ID before polling. A lost polling or streaming connection can refresh the same-origin Agent Card once and resume observation of that task. It never sends another `SendMessage`. If the submission response itself was ambiguous and no task ID was received, automatic continuation is refused. + +Continue a known uncertain task with: + +```text +agentctl effects --db .agentctl/runtime.db continue-remote EFFECT_ID \ + --actor operator --reason "resume persisted task" --approved +``` + +The command observes the existing remote task, ingests completed inline or same-origin URL artifacts into the local CAS, and records an applied effect reconciliation. A following failed-only retry materializes that completed boundary and executes only its descendants. Repair, retry, and replay retain source-linked protocol evidence without submitting the task again. + +Each artifact part must contain exactly one of `text`, `raw`, `data`, or `url`. Retrieval is bounded to 16 MiB per part and same-origin URL policy. Mock peers cover known-task continuation, ambiguous-send refusal, task polling, artifacts, streaming fallback, cancellation, protocol mismatch, origin enforcement, timeout, and zero-resubmission retry. +> Canonical source: [`docs/A2A.md`](https://github.com/opensourceops/agentctl/blob/main/docs/A2A.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/providers/index.md b/src/content/docs/_generated/providers/index.md index dfaedaf..e6b5b33 100644 --- a/src/content/docs/_generated/providers/index.md +++ b/src/content/docs/_generated/providers/index.md @@ -7,13 +7,27 @@ The core defines provider-neutral messages, text/reasoning/tool content, strict | Kind | Native API | Implemented behavior | Credential default | | --- | --- | --- | --- | -| `fake` | in-process scripted provider | deterministic echo/script, tool path, usage | none | -| `openai` | Responses API | GPT-5.6; strict function tools and structured output; multiple call IDs; `previous_response_id`; reasoning effort/mode/context; response storage; prompt-cache mode/TTL; input/output/reasoning/cache metrics | `OPENAI_API_KEY` | -| `azure_openai` | Azure `/openai/v1/responses?api-version=v1` | OpenAI mapping with Azure `api-key`; explicit endpoint required | `AZURE_OPENAI_API_KEY` | +| `fake` | in-process scripted provider | deterministic echo/script, tool path, usage, typed streaming | none | +| `openai` | Responses API | GPT-5.6; strict function tools and structured output; multiple call IDs; stored and stateless continuation; reasoning effort/mode/context; prompt-cache mode/TTL; input/output/reasoning/cache metrics; typed SSE streaming | `OPENAI_API_KEY` | +| `azure_openai` | Azure `/openai/v1/responses?api-version=v1` | OpenAI mapping and SSE with Azure `api-key`; explicit endpoint required | `AZURE_OPENAI_API_KEY` | | `anthropic` | Messages API | native content/tool/thinking blocks, structured output instruction, usage and stop mapping | `ANTHROPIC_API_KEY` | | `google` | Gemini `generateContent` | native contents/function declarations/calls/results, thought-signature continuation, response schema, token usage | `GEMINI_API_KEY` | -Endpoints must pass the workflow network allowlist. Redirects are disabled. Credentials and configured headers are resolved from environment references only when building an adapter; standard authentication headers override custom headers. Successful/error response JSON keys and values plus provider request IDs are scrubbed of configured secrets before parsing or persistence. Calls honor timeout and cancellation. +Endpoints must pass the workflow scheme, host, effective-port, and resolved-IP +policy. Every DNS answer must be allowed, and direct clients pin the accepted +answer to prevent resolution drift. Private addresses and environment proxies +are denied by default. Redirects and Unix-socket transports are disabled. +Response bytes and DNS/connect time are bounded, composed with the provider +task timeout and the adapter's lower hard limit. See [Network +policy](https://github.com/opensourceops/agentctl/blob/main/docs/guides/NETWORK_POLICY.md). +Credentials and configured headers accept environment, mounted-file, or +policy-gated process references. Provider credentials in the fresh execution +closure are preflighted before a new run record or effect; custom headers +resolve while building a required adapter. +Standard authentication headers override custom headers. Successful/error +response JSON keys and values plus provider request IDs are scrubbed of +configured secrets before parsing or persistence. Calls honor timeout and +cancellation. See [Secret references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). `agentctl providers inspect ` reports declared capabilities without calling a service. OpenAI has the broadest mock request/response/tool/usage/error coverage. Azure OpenAI, Anthropic, and Google have native mapping and focused mock-protocol coverage at the maturity shown below; normal tests have no credentials. Live provider workflow examples end in `-live.yaml` and are opt-in. @@ -25,9 +39,50 @@ Endpoints must pass the workflow network allowlist. Redirects are disabled. Cred | Anthropic | native text/tool/usage mapping mock-tested; not live-tested | | Google | native text/function/usage mapping mock-tested; not live-tested | -`agentctl providers smoke-openai --live --model gpt-5.6` remains a provider-only diagnostic; it is not runtime acceptance. The repository-owned live gate is `cargo xtask acceptance-live-openai`. It runs a YAML workflow through compilation, SQLite, a real strict function call, built-in tool policy/schema validation, `previous_response_id` continuation, deterministic assertion/artifact creation, public inspection, and replay with the credential removed. It repeats the journey inside the production OCI image and never runs in normal CI. Anthropic, Google, and Azure are implemented and mock-tested but are not live-tested in this release. +`agentctl providers smoke-openai --live --model gpt-5.6` remains a provider-only diagnostic; it is not runtime acceptance. The repository-owned live gate is `cargo xtask acceptance-live-openai`. It runs a YAML workflow through compilation, SQLite, a real strict function call, built-in tool policy/schema validation, stateless encrypted-reasoning continuation, deterministic assertion/artifact creation, public inspection, and replay with the credential removed. It repeats the journey inside the production OCI image and never runs in normal CI. Anthropic, Google, and Azure are implemented and mock-tested but are not live-tested in this release. -OpenAI provider options are an allowlisted map (`store`, `reasoningContext`, `promptCacheMode`, `promptCacheTtl`, `parallelToolCalls`, and `safetyIdentifier`). Unknown options or invalid values fail compilation. Tool-using OpenAI and Azure OpenAI agents may not set `store: false`: stateless continuation would require replaying returned response/reasoning/function items, which this release does not implement. One-turn agents without tools may disable storage. Programmatic tool calling and model streaming are explicitly unsupported in the workflow runtime and fail rather than being ignored. Parallel function calls are parsed and correlated, but executors run them serially in response order because v1 scheduling is sequential. +`cargo xtask examples-verify-live-openai` is the broader opt-in gate. It runs every public OpenAI workflow plus the canonical two-agent repair. A repaired task starts a new Responses session. The failed source task's response ID, stateless continuation items, pending tool call, and reasoning state are not copied. Validated task output is the cross-run dataflow boundary. -Cost is not inferred when a provider returns no reliable cost metadata. A workflow requesting `maxCostUsd` therefore fails capability negotiation; input/output token limits are enforced from native usage. Retry is limited to explicit task bounds and definitive retryable HTTP responses. Timeout, cancellation, or a transport loss after dispatch is considered ambiguous and is not automatically reissued. -> Canonical source: [`docs/PROVIDERS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PROVIDERS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +`cargo xtask resource-budget-live-openai` is the narrow resource-control gate. It +allows one real `gpt-5.6` dispatch, durably denies the second requested model +effect, and verifies the provider-request ledger through public inspection. + +OpenAI provider options are an allowlisted map (`store`, `reasoningContext`, `promptCacheMode`, `promptCacheTtl`, `parallelToolCalls`, and `safetyIdentifier`). Unknown options or invalid values fail compilation. Tool-using OpenAI and Azure OpenAI agents may set `store: false`; the adapter requests encrypted reasoning content and replays the complete ordered response-item and function-output history. `stream: true` selects typed Responses SSE for fake, OpenAI, and Azure OpenAI agents. Anthropic and Google streaming fail capability negotiation. Programmatic tool calling remains unsupported and fails rather than being ignored. Parallel function calls are parsed and correlated, but one agent task executes them serially in response order. Independent workflow tasks can use bounded parallel scheduling. + +## Stateful and stateless continuation + +With the default `store: true`, OpenAI continuation uses `previous_response_id`. +The next request sends only the latest function outputs and relies on the +provider-stored response. + +With `store: false`, agentctl does not send `previous_response_id`. It +automatically requests `reasoning.encrypted_content`, normalizes each returned +reasoning, message, and function-call item into the provider-neutral +continuation, and replays those items in their original order with correlated +function outputs, following the official [stateless encrypted-reasoning +contract](https://developers.openai.com/api/reference/resources/responses/methods/create). +A returned reasoning item without encrypted content fails closed instead of +silently losing model context. + +Both modes persist continuation under provider-session format version 1. +Stateless request input is capped at 8 MiB before dispatch. Provider responses +remain subject to the configured response-byte limit and the 4 MiB adapter hard +limit. Continuation and model-effect payloads use the selected-field +state-encryption boundary when state encryption is enabled. Repair starts a +fresh provider session, while pause/resume restores the task-local continuation +and recorded replay performs no provider dispatch. + +Cost is not inferred when a provider returns no reliable cost metadata. +Agent `maxCostUsd` and run `maxCostMicrousd` can use explicit versioned custom +pricing keyed by `provider/model`; otherwise a requested monetary limit fails +capability negotiation. Token-only run budgets remain enforceable from native +usage without pricing. Retry is limited to explicit task bounds and definitive +retryable HTTP responses. Timeout, cancellation, or a transport loss after +dispatch is considered ambiguous and is not automatically reissued. See +[Resource and cost budgets](https://github.com/opensourceops/agentctl/blob/main/docs/guides/RESOURCE_BUDGETS.md). + +Streaming persists each accepted fragment before reading more transport data. +Records are bounded and redacted, while the terminal response still follows +the normal validation path. See [Durable provider +streaming](https://github.com/opensourceops/agentctl/blob/main/docs/guides/DURABLE_STREAMING.md). +> Canonical source: [`docs/PROVIDERS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/PROVIDERS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/providers/mcp.md b/src/content/docs/_generated/providers/mcp.md index 29ae45e..9aa3001 100644 --- a/src/content/docs/_generated/providers/mcp.md +++ b/src/content/docs/_generated/providers/mcp.md @@ -3,9 +3,22 @@ title: "MCP" description: "Use pinned MCP Streamable HTTP tools under explicit policy." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/MCP.md" --- -The client pins the stable MCP protocol version `2025-11-25` from the [official specification](https://modelcontextprotocol.io/specification/2025-11-25). It uses Streamable HTTP JSON-RPC and implements initialization/version negotiation, initialized notification, session IDs, protocol headers, tool listing, input/output schemas, tool calls, structured content, error mapping, SSE response parsing, timeout, best-effort cancellation notification, and explicit session-expiry failure. +The client pins the stable MCP protocol version `2025-11-25` from the [official specification](https://modelcontextprotocol.io/specification/2025-11-25). It uses Streamable HTTP JSON-RPC and implements initialization/version negotiation, initialized notification, session IDs, protocol headers, tool listing, input/output schemas, tool calls, structured content, bounded SSE response parsing, timeout, and best-effort cancellation notification. -Authentication headers are environment secret references. The endpoint must pass network policy. Redirects are disabled and an `Origin` header is sent. Remote descriptions, schemas, content, and annotations are untrusted; annotations are exposed only as metadata and never authorize an effect. +Authentication headers are secret references resolved at dispatch. A `401` refreshes those references once for initialization, notification, listing, or call. The endpoint must pass network policy. Redirects are disabled and an `Origin` header is sent. Remote descriptions, schemas, content, and annotations are untrusted; annotations are exposed only as metadata and never authorize an effect. -The client initializes lazily and does not automatically reconnect after session expiry because repeating a remote operation could be unsafe. The caller must reconcile and resume or fork. Streaming transport is parsed, but tool results are delivered to the runtime only when complete. Deterministic local mock-server tests cover negotiation, sessions, listing/call, structured results, version mismatch, and timeout. -> Canonical source: [`docs/MCP.md`](https://github.com/opensourceops/agentctl/blob/main/docs/MCP.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Set `idempotency` on an `mcp.call` action when its server contract justifies it: + +```yaml +actions: + lookup: + kind: mcp.call + idempotency: idempotent +``` + +`pure`, `idempotent`, and `keyed` calls may reconnect once after session expiry, timeout, transport loss, or a malformed response. A keyed call also sends the stable effect identity as `params._meta["agentctl.dev/idempotency-key"]`; the declaration is valid only when the reviewed server contract honors that key. Reconnection creates a new session, refreshes `tools/list`, and compares the selected tool's schema digest before redispatch. A changed or missing schema fails without a second call. `at_most_once` and `unknown` calls are never redispatched after an ambiguous response. + +SQLite schema 13 records session generation, immutable call identity, idempotency, status, selected remote, and encrypted-capable protocol state. `agentctl inspect RUN_ID` exposes `protocolSessions`, `protocolCalls`, and bounded protocol stream events. Recorded replay copies source-linked protocol evidence but performs no network effect. + +Streaming progress is persisted with backpressure before the next frame is consumed. A final tool result enters workflow state only after complete JSON-RPC validation. Deterministic mock-server coverage includes server restart, one-reconnect bounds, stable and changed schemas, authentication refresh, unsafe-call refusal, SSE parsing, cancellation, timeout, inspection, and replay. +> Canonical source: [`docs/MCP.md`](https://github.com/opensourceops/agentctl/blob/main/docs/MCP.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/capabilities.md b/src/content/docs/_generated/reference/capabilities.md index fb954cf..52d1679 100644 --- a/src/content/docs/_generated/reference/capabilities.md +++ b/src/content/docs/_generated/reference/capabilities.md @@ -40,4 +40,4 @@ The compiler verifies that a built-in tool declaration matches its executor sema | `a2a.delegate` | remote agent | recorded result, no fresh delegation in replay | See [Providers](/agentctl/providers/), [Tools](/agentctl/concepts/tools/), and [Durable execution](/agentctl/durable-execution/). -> Canonical source: [`docs/reference/MATRICES.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/MATRICES.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/reference/MATRICES.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/MATRICES.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/cli.md b/src/content/docs/_generated/reference/cli.md index 2a63271..5bc0d67 100644 --- a/src/content/docs/_generated/reference/cli.md +++ b/src/content/docs/_generated/reference/cli.md @@ -19,14 +19,20 @@ Commands: resume Continue an interrupted or approval-paused run replay Reconstruct a terminal run only from recorded state and results fork Create a new run from a prior workflow with fresh effects + repair Create a new run that reuses compatible upstream results and executes a repaired suffix + retry Retry failed or selected boundaries of an identical terminal workflow + compensate Execute explicitly declared best-effort compensation for a terminal run + runs Analyze or upgrade retained legacy run records for selective reuse cancel Durably request cancellation inspect Inspect durable run, task, and audit state + effects Inspect or narrowly reconcile uncertain effects approvals List or resolve durable approval requests providers Inspect provider capabilities or run the opt-in OpenAI smoke auth Check configured secret references without revealing values schema Print or write the generated workflow JSON Schema migrate Translate an unversioned TypeScript-era workflow into v1alpha1 packs Inspect and verify a local reusable pack + artifacts Inspect, verify, export, or collect durable artifacts db Inspect the runtime database memory Read or write namespaced long-term memory gc Garbage-collect expired memory and old terminal runs @@ -35,9 +41,11 @@ Commands: update Explain safe update options without modifying the installation Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help -V, --version Print version ``` @@ -53,9 +61,11 @@ Arguments: Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -70,9 +80,11 @@ Arguments: Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -87,19 +99,36 @@ Arguments: Options: - --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] - --color [default: auto] [possible values: auto, always, never] + --db + [default: .agentctl/runtime.db] + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] --inputs + --inputs-file + --verbose + --input + + --offline + Forbid pack network access and require cached Git/archive sources + --locked + Require agentctl.pack.lock and reject all source or graph drift --workspace + --timeout-seconds + --check + --diff + --interactive - -h, --help Print help + + -h, --help + Print help ``` ## `agentctl resume` @@ -113,15 +142,28 @@ Arguments: Options: - --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] - --color [default: auto] [possible values: auto, always, never] + --db + [default: .agentctl/runtime.db] + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] --diff + --interactive + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources --workspace + + --locked + Require agentctl.pack.lock and reject all source or graph drift --timeout-seconds - -h, --help Print help + + -h, --help + Print help ``` ## `agentctl replay` @@ -136,9 +178,11 @@ Arguments: Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -153,15 +197,217 @@ Arguments: Options: - --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] - --color [default: auto] [possible values: auto, always, never] + --db + [default: .agentctl/runtime.db] + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] + --interactive + + --diff + + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources + --workspace + + --locked + Require agentctl.pack.lock and reject all source or graph drift + --timeout-seconds + + -h, --help + Print help +``` + +## `agentctl repair` + +```text +Create a new run that reuses compatible upstream results and executes a repaired suffix + +Usage: agentctl repair [OPTIONS] --from + +Arguments: + + + +Options: + --from + + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] + --plan + + --restart-successful + + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources + --reason + + --db + [default: .agentctl/runtime.db] + --locked + Require agentctl.pack.lock and reject all source or graph drift + --interactive + + --diff + + --workspace + + --timeout-seconds + + -h, --help + Print help +``` + +## `agentctl retry` + +```text +Retry failed or selected boundaries of an identical terminal workflow + +Usage: agentctl retry [OPTIONS] + +Arguments: + + + +Options: + --failed + + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] + --from + + --plan + + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources + --restart-successful + + --locked + Require agentctl.pack.lock and reject all source or graph drift + --reason + + --db + [default: .agentctl/runtime.db] --interactive + --diff + + --workspace + + --timeout-seconds + + -h, --help + Print help +``` + +## `agentctl compensate` + +```text +Execute explicitly declared best-effort compensation for a terminal run + +Usage: agentctl compensate [OPTIONS] + +Arguments: + + +Options: + --output + [default: human] [possible values: human, json, jsonl] + --task + + --color + [default: auto] [possible values: auto, always, never] + --plan + + --db + [default: .agentctl/runtime.db] --verbose + + --interactive + + --offline + Forbid pack network access and require cached Git/archive sources + --diff + + --locked + Require agentctl.pack.lock and reject all source or graph drift --workspace + --timeout-seconds - -h, --help Print help + + -h, --help + Print help +``` + +## `agentctl runs` + +```text +Analyze or upgrade retained legacy run records for selective reuse + +Usage: agentctl runs [OPTIONS] + +Commands: + analyze Prove reusable legacy metadata without changing the source run + upgrade Transactionally persist every legacy field that can be proven + +Options: + --db [default: .agentctl/runtime.db] + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl runs analyze` + +```text +Prove reusable legacy metadata without changing the source run + +Usage: agentctl runs analyze [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl runs upgrade` + +```text +Transactionally persist every legacy field that can be proven + +Usage: agentctl runs upgrade [OPTIONS] + +Arguments: + + +Options: + --dry-run + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help ``` ## `agentctl cancel` @@ -176,9 +422,11 @@ Arguments: Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -194,12 +442,111 @@ Arguments: Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl effects` + +```text +Inspect or narrowly reconcile uncertain effects + +Usage: agentctl effects [OPTIONS] + +Commands: + list + inspect + continue-remote Resume observation of a persisted remote task without resubmitting it + reconcile + +Options: + --db [default: .agentctl/runtime.db] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` +## `agentctl effects list` + +```text +Usage: agentctl effects list [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --task + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl effects inspect` + +```text +Usage: agentctl effects inspect [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl effects reconcile` + +```text +Usage: agentctl effects reconcile [OPTIONS] --status --reason + +Arguments: + + +Options: + --output + [default: human] [possible values: human, json, jsonl] + --status + [possible values: applied, not-applied, compensated] + --actor + [default: cli-user] + --color + [default: auto] [possible values: auto, always, never] + --reason + + --verbose + + --evidence-file + + --offline + Forbid pack network access and require cached Git/archive sources + --locked + Require agentctl.pack.lock and reject all source or graph drift + --result-file + + --result-schema-file + + --compensation-effect + + --approved + + -h, --help + Print help +``` + ## `agentctl approvals` ```text @@ -214,9 +561,11 @@ Commands: Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -229,9 +578,11 @@ Arguments: Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -245,10 +596,12 @@ Arguments: Options: --actor [default: cli-user] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --reason --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -262,10 +615,12 @@ Arguments: Options: --actor [default: cli-user] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --reason --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -281,9 +636,11 @@ Commands: smoke-openai Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -296,9 +653,11 @@ Arguments: Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -309,10 +668,12 @@ Usage: agentctl providers smoke-openai [OPTIONS] --live Options: --live Required acknowledgement that this performs one bounded live request - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --model [default: gpt-5.6] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -327,9 +688,11 @@ Commands: check Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -341,10 +704,12 @@ Print or write the generated workflow JSON Schema Usage: agentctl schema [OPTIONS] Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --write --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -359,10 +724,12 @@ Arguments: Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --write --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -376,14 +743,230 @@ Usage: agentctl packs [OPTIONS] Commands: inspect verify + lock Resolve the complete graph and write agentctl.pack.lock + update Refresh the locked graph from immutable sources + verify-lock Verify a lockfile, source digests, signatures, and trust policy + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl packs inspect` + +```text +Usage: agentctl packs inspect [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl packs verify` + +```text +Usage: agentctl packs verify [OPTIONS] --integrity + +Arguments: + + +Options: + --integrity + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl packs lock` + +```text +Resolve the complete graph and write agentctl.pack.lock + +Usage: agentctl packs lock [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl packs update` + +```text +Refresh the locked graph from immutable sources + +Usage: agentctl packs update [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --pack + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl packs verify-lock` + +```text +Verify a lockfile, source digests, signatures, and trust policy + +Usage: agentctl packs verify-lock [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl artifacts` + +```text +Inspect, verify, export, or collect durable artifacts + +Usage: agentctl artifacts [OPTIONS] + +Commands: + list + inspect + verify + export + gc Options: - --output [default: human] [possible values: human, json] + --db [default: .agentctl/runtime.db] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` +## `agentctl artifacts list` + +```text +Usage: agentctl artifacts list [OPTIONS] + +Options: + --output [default: human] [possible values: human, json, jsonl] + --run + --color [default: auto] [possible values: auto, always, never] + --task + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl artifacts inspect` + +```text +Usage: agentctl artifacts inspect [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl artifacts verify` + +```text +Usage: agentctl artifacts verify [OPTIONS] [DIGEST] + +Arguments: + [DIGEST] + +Options: + --all + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl artifacts export` + +```text +Usage: agentctl artifacts export [OPTIONS] + +Arguments: + + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --overwrite + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl artifacts gc` + +```text +Usage: agentctl artifacts gc [OPTIONS] + +Options: + --older-than-days + [default: 30] + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] + --dry-run + + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources + --locked + Require agentctl.pack.lock and reject all source or graph drift + -h, --help + Print help +``` + ## `agentctl db` ```text @@ -394,15 +977,91 @@ Usage: agentctl db [OPTIONS] Commands: stats migrate + encryption Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` +## `agentctl db encryption` + +```text +Usage: agentctl db encryption [OPTIONS] + +Commands: + inventory Inventory protected fields without exposing their values + enable Transactionally encrypt every identified sensitive field + rotate Transactionally decrypt and re-encrypt every protected field with a new key + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl db encryption inventory` + +```text +Inventory protected fields without exposing their values + +Usage: agentctl db encryption inventory [OPTIONS] + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl db encryption enable` + +```text +Transactionally encrypt every identified sensitive field + +Usage: agentctl db encryption enable [OPTIONS] --key-id --key-env + +Options: + --key-id + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --key-env Environment variable containing a base64-encoded 32-byte key + --dry-run + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl db encryption rotate` + +```text +Transactionally decrypt and re-encrypt every protected field with a new key + +Usage: agentctl db encryption rotate [OPTIONS] --key-id --key-env + +Options: + --key-id + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --key-env Environment variable containing a base64-encoded 32-byte key + --dry-run + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + ## `agentctl memory` ```text @@ -413,12 +1072,103 @@ Usage: agentctl memory [OPTIONS] Commands: get put + search + reindex Options: --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl memory get` + +```text +Usage: agentctl memory get [OPTIONS] + +Arguments: + + + +Options: + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl memory put` + +```text +Usage: agentctl memory put [OPTIONS] + +Arguments: + + + + +Options: + --output + [default: human] [possible values: human, json, jsonl] + --text + + --color + [default: auto] [possible values: auto, always, never] + --metadata + + --retention-days + + --verbose + + --offline + Forbid pack network access and require cached Git/archive sources + --locked + Require agentctl.pack.lock and reject all source or graph drift + -h, --help + Print help +``` + +## `agentctl memory search` + +```text +Usage: agentctl memory search [OPTIONS] + +Arguments: + + + +Options: + --mode [default: text] [possible values: text, vector, hybrid] + --output [default: human] [possible values: human, json, jsonl] + --color [default: auto] [possible values: auto, always, never] + --limit [default: 10] + --filter + --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift + -h, --help Print help +``` + +## `agentctl memory reindex` + +```text +Usage: agentctl memory reindex [OPTIONS] + +Arguments: + + +Options: + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -430,12 +1180,22 @@ Garbage-collect expired memory and old terminal runs Usage: agentctl gc [OPTIONS] Options: - --db [default: .agentctl/runtime.db] - --output [default: human] [possible values: human, json] - --color [default: auto] [possible values: auto, always, never] - --older-than-days [default: 30] + --db + [default: .agentctl/runtime.db] + --output + [default: human] [possible values: human, json, jsonl] + --color + [default: auto] [possible values: auto, always, never] + --older-than-days + [default: 30] --verbose - -h, --help Print help + + --offline + Forbid pack network access and require cached Git/archive sources + --locked + Require agentctl.pack.lock and reject all source or graph drift + -h, --help + Print help ``` ## `agentctl completion` @@ -449,9 +1209,11 @@ Arguments: [possible values: bash, elvish, fish, powershell, zsh] Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -463,9 +1225,11 @@ Print the exact build version Usage: agentctl version [OPTIONS] Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` @@ -477,9 +1241,11 @@ Explain safe update options without modifying the installation Usage: agentctl update [OPTIONS] Options: - --output [default: human] [possible values: human, json] + --output [default: human] [possible values: human, json, jsonl] --color [default: auto] [possible values: auto, always, never] --verbose + --offline Forbid pack network access and require cached Git/archive sources + --locked Require agentctl.pack.lock and reject all source or graph drift -h, --help Print help ``` -> Canonical source: [`docs/generated/CLI.md`](https://github.com/opensourceops/agentctl/blob/main/docs/generated/CLI.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/generated/CLI.md`](https://github.com/opensourceops/agentctl/blob/main/docs/generated/CLI.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/compatibility.md b/src/content/docs/_generated/reference/compatibility.md index d4da82b..f052952 100644 --- a/src/content/docs/_generated/reference/compatibility.md +++ b/src/content/docs/_generated/reference/compatibility.md @@ -1,27 +1,59 @@ --- title: "Compatibility" -description: "Preserved, migrated, changed, removed, and deferred contracts." +description: "Preserved, migrated, changed, removed, and explicit non-goal contracts." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/COMPATIBILITY.md" --- ## Preserved -Declaration-order scheduling among ready tasks, `needs` dataflow, exact typed templates, deterministic assign/assert/file/memory use cases, bounded agent/tool turns, approval concepts, SQLite local persistence, and the useful top-level command names remain. The language-neutral fixture records the legacy assign workflow’s translated model, graph order, and task reference. +Declaration-order scheduling among ready tasks, `needs` dataflow, exact typed templates, deterministic assign/assert/file/memory use cases, bounded agent/tool turns, approval concepts, SQLite local persistence, and the useful top-level command names remain. The language-neutral fixture records the legacy assign workflow’s translated model, graph order, and task reference. Omitted `foreach`, `matrix`, and `loop` fields preserve the unchanged single-task graph; compiled expansion metadata is additive. ## Migrated -Unversioned `playbook:` YAML can be translated by `agentctl migrate`; `modules` become `actions`, `module:x` becomes `action:x`, heuristic agents map to the fake provider, and core memory/policy fields are normalized. Rust JSON output is a stable `agentctl.dev/cli/v1` envelope rather than the prototype JSONL/YAML mixture. The production executable and runtime are Rust. +Unversioned `playbook:` YAML can be translated by `agentctl migrate`; `modules` become `actions`, `module:x` becomes `action:x`, heuristic agents map to the fake provider, and core memory/policy fields are normalized. Rust JSON output is a stable `agentctl.dev/cli/v1` envelope rather than the prototype JSONL/YAML mixture. The additive JSONL mode uses the same versioned envelopes for bounded progress and a final result. The production executable and runtime are Rust. ## Intentionally changed `replay` now means no-effect recorded reconstruction. The prototype operation that created a new effectful run is `fork`. Unknown YAML fields, missing references, cycles, unsupported provider capabilities, invalid tool output, path escapes, unsafe processes/networks, and incompatible durable state now fail explicitly. Direct `--api-key` flags are removed; secret references are required. OpenAI uses current Responses concepts, and Anthropic/Google are native adapters rather than names on an OpenAI-compatible route. -## Deprecated and removed +Schema 5 adds selective-repair metadata without changing resume, replay, retry, or fork semantics. New runs persist task fingerprints, output contracts/digests, state deltas, artifacts, and disposition. Older runs migrate and remain inspectable, but tasks completed without metadata version 1 cannot be silently reused by repair. -Unversioned YAML is compatibility-only and warns. The TypeScript package exposes no `bin` or `main` and is archived. Placeholder memory adapters, provider environment-name-only “support,” YAML output, legacy profiles, automatic endpoint overrides, old prompt-cache fields, and optimistic replay semantics are removed from production. +Schema 14 preserves legacy long-term-memory values by wrapping them as typed +format-version-1 JSON entries with derived searchable text. Exact namespace/key +reads remain compatible. Text, vector, hybrid search, metadata, embedding +identity, and explicit promotion are additive. -Legacy workflows depending on packs, broad built-in tool profiles, remote MCP/A2A shape, MongoDB memory, provider-specific endpoint fields, or embedded credentials require manual conversion. The translator intentionally refuses to guess security-sensitive intent. +## Deprecated and removed -## Deferred product decisions +Unversioned YAML is compatibility-only and warns. The TypeScript package exposes no `bin` or `main` and is archived. Placeholder memory adapters, provider environment-name-only “support,” YAML output, legacy profiles, automatic endpoint overrides, old prompt-cache fields, and optimistic replay semantics are removed from production. -Parallel execution, foreach/matrix, loops, routers, sub-workflows, teams/handoffs, compensation execution, a public pack registry/resolver, vector memory, automatic MCP reconnection, general A2A resubmission, and streamed model output are not compatibility promises for v1alpha1. -> Canonical source: [`docs/COMPATIBILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/COMPATIBILITY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Tool-level `compensation` metadata was never executable and is rejected. Declare +an effectful inverse action on each source task with `compensate`; see +[Compensation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/COMPENSATION.md). + +Free-form `team:` orchestration is rejected. Convert each role to an explicit +agent task and each payload transfer to a typed handoff task; see +[Structured role handoffs](https://github.com/opensourceops/agentctl/blob/main/docs/guides/STRUCTURED_HANDOFFS.md). + +Legacy exact local pack references remain readable and warn until +`agentctl packs lock` writes `agentctl.pack.lock`. Convert `path` and +`integrity` fields to a typed `source`, select `packTrust.unsigned`, and review +`allowUnsignedProcess` before enabling any process-capable pack. Native dynamic +libraries are not supported; migrate local executors to `extension.process` or +remote tools to MCP. + +Legacy workflows depending on broad built-in tool profiles, remote MCP/A2A +shape, MongoDB memory, provider-specific endpoint fields, or embedded +credentials require manual conversion. The translator intentionally refuses to +guess security-sensitive intent. + +## Separate product decisions + +A public pack registry, in-process plugin ABI, and general A2A resubmission are +not compatibility promises for v1alpha1. Pack lock v1, the bounded process +protocol v1, and source/trust policy are additive. MCP reconnect is bounded by +explicit idempotency and schema stability. A2A continuation observes only a +persisted task ID. Bounded loops, namespaced sub-workflows, explicit +source-linked compensation, graph-native structured handoffs, durable +streaming, and protocol continuation records are additive; hidden or +model-controlled orchestration is intentionally unsupported. +> Canonical source: [`docs/COMPATIBILITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/COMPATIBILITY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/completeness-verification.md b/src/content/docs/_generated/reference/completeness-verification.md new file mode 100644 index 0000000..ea8ca0c --- /dev/null +++ b/src/content/docs/_generated/reference/completeness-verification.md @@ -0,0 +1,228 @@ +--- +title: "Completeness verification" +description: "Deterministic, container, security, and independent review evidence." +editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/execution/COMPLETENESS_VERIFICATION.md" +--- +This record accumulates sanitized evidence for the framework-completeness +program. It contains no credentials, raw provider responses, prompt +transcripts, runtime databases, private certificates, or artifact bytes. + +## Baseline + +Branch point: `af9b4ae`, including independently reviewed selective workflow +repair. + +Date: 2026-07-23, Asia/Kolkata. + +| Gate | Baseline result | +| --- | --- | +| `cargo xtask verify` | passed all 12 stages | +| `cargo xtask acceptance` | passed 28 scenarios | +| `cargo xtask examples-verify` | passed | +| `cargo xtask docs-verify` | passed all 6 stages | +| `cargo xtask package` | passed for macOS arm64 | +| `cargo xtask secret-scan` | passed | +| `env -u OPENAI_API_KEY cargo xtask acceptance-container` | reached the OCI CLI, then failed because `/artifacts/report.txt` escaped the authorized workspace root | + +The installed container runtime is Podman 5.8.2 with a libkrun machine. In this +execution environment, Podman's VM and forwarding processes survive only while +the starting terminal remains open. Keeping that terminal active made the +engine reachable without deleting a machine, changing TLS, or weakening +configuration. + +No OpenAI request was made during baseline verification. + +## Semantic-memory checkpoint + +Date: 2026-07-27, Asia/Kolkata. + +| Gate | Result | +| --- | --- | +| `cargo xtask verify` | passed all 12 stages; 14 CLI, 55 core, 21 provider, 80 runtime, 31 store, and 15 protocol tests passed | +| `cargo xtask acceptance` | passed all 43 credential-free packaged CLI scenarios | +| `cargo xtask docs-verify` | passed all 6 stages | +| `cargo xtask examples-verify` | passed | +| `cargo xtask package` | passed for macOS arm64 | +| `cargo xtask secret-scan` | passed | + +All deterministic commands ran with `OPENAI_API_KEY` removed. The optional +OpenAI embedding adapter used only WireMock contract tests, so this checkpoint +made zero OpenAI API requests. + +## Process-isolation checkpoint + +Date: 2026-07-27, Asia/Kolkata. + +| Gate | Result | +| --- | --- | +| `cargo check --workspace --all-targets` | passed without warnings | +| `cargo test -p agentctl-core --lib` | passed all 63 tests | +| `cargo test -p agentctl-store --lib` | passed all 35 tests | +| `cargo test -p agentctl-runtime --lib` | passed 90 tests; one live container test ignored by default | +| `cargo test -p agentctl-runtime process::tests::` | passed all 8 process lifecycle, cleanup, and container-contract tests | +| `cargo xtask acceptance` | passed all 46 credential-free packaged CLI scenarios | +| `cargo xtask resource-budget-live-openai` | passed with one GPT-5.6 request, 18 input tokens, and 5 output tokens; second request denied | +| `env -u OPENAI_API_KEY cargo xtask acceptance-container` | blocked before image build because Podman 5.8.2/libkrun `gvproxy` exited and both the configured TCP endpoint and forwarded Unix socket refused connections | + +The existing Podman VM was started and then cleanly stopped/restarted once. +The VM booted, but its forwarding process exited immediately on both attempts. +No image or container was started by this checkpoint. The OCI gate now includes +a real digest-pinned action-level container test and must be rerun when the +local engine is healthy. + +## OCI completion checkpoint + +Date: 2026-07-27, Asia/Kolkata. + +The existing Podman machine was recovered without deleting it or changing its +security configuration. Its libkrun and `gvproxy` processes remained available +while the starting terminal stayed open. + +| Gate | Result | +| --- | --- | +| `cargo test -p xtask` | passed all 7 tests, including Docker/Podman image-ID normalization and malformed-ID rejection | +| `env -u OPENAI_API_KEY cargo xtask acceptance-container` | passed on Podman 5.8.2, native Linux arm64 | +| Trivy 0.72.0 HIGH/CRITICAL fixed-vulnerability gate | passed with a freshly updated database and zero findings | +| Trivy 0.72.0 CycloneDX generation and `jq` validation | passed; 11 components, 20,821 bytes | +| Image configuration and history marker scan | passed; zero credential, authorization, bearer, or token-pattern lines | + +The first current-source run built the image and exposed a product-gate +compatibility defect: Podman 5.8 returned `.Id` as bare 64-hex while the +acceptance parser required Docker's `sha256:` prefix. The parser now validates +both forms, normalizes both to `sha256:`, and rejects every malformed +form. The cached rerun passed action-level digest-pinned isolation, strict tool +continuation, declared artifact export, durable inspection, parallel ordered +commit, selective repair, network-disabled replay, missing credentials, +invalid input, SIGTERM, non-root identity, read-only root, and mounted state +and artifacts. + +The exact image is Linux arm64, `nonroot:nonroot`, version `0.2.0`, and source +`opensourceops/agentctl`. Its local image digest is +`sha256:ddcf174ab2b1ce2481395380d482292a41d79ee5f4620fd52cbd3733e712127c`. +The ignored SBOM at +`.runtime/scan/agentctl-framework-completeness.cdx.json` has SHA-256 +`0ee27f16491108f0f018ac2bc7ad201b3f97bdb539cd6b78584264c9eedd67ff`. +No OpenAI request occurred. + +## Composite and live checkpoint + +Date: 2026-07-27, Asia/Kolkata. + +| Gate | Result | +| --- | --- | +| `env -u OPENAI_API_KEY cargo xtask completeness` | passed all three packaged composite groups | +| `env -u OPENAI_API_KEY cargo xtask acceptance-container` | passed the durable composite and compensation/reconciliation additions on native Linux arm64 | +| `cargo xtask examples-verify-live-openai` local phase | passed every public OpenAI example and the 11-request framework composite | +| `cargo xtask examples-verify-live-openai-container` | passed the focused native Linux arm64 live source, repair, and keyless replay continuation | + +The deterministic gate verified approval, parallel scheduling, a four-child +matrix, typed agent output, failed-only retry, repair after workspace artifact +deletion, CAS verify/export, keyless replay, sub-workflows, a two-iteration +loop, typed routing, MCP reconnect, compensation, reconciliation, +cancellation, and structured handoffs. + +The retained GPT-5.6 matrix used 27 requests, 3,939 input tokens, 560 output +tokens, 20 reasoning tokens, and 8 tool calls. It covered basic and tool +workflows, two agent branches, a two-child agent matrix, structured routing, +an agent loop, an agent sub-workflow, a typed two-role handoff, a deterministic +agent failure and failed-only retry, selective repair, artifact CAS reuse, +keyless replay, real streaming, and Linux arm64 container execution. The +separate one-request resource-budget run denied request two before dispatch. +See +[`LIVE_FRAMEWORK_VERIFICATION.md`](/agentctl/reference/live-framework-verification/) +for run IDs, cumulative request accounting, and fail-closed gate corrections. + +Two acceptance defects were corrected before closure. Repair planning now +returns a structured `resolved_input_unavailable` block instead of aborting +when an earlier incompatible reused task makes a downstream template +unresolvable. The live OCI gate now copies the actual public OpenAI repair +workflows rather than the credential-free fixture with unrelated task IDs. + +## Evidence rules + +- Deterministic gates run without provider credentials. +- Live gates use only `gpt-5.6`, at most 80 Responses API requests for this + program, and a target aggregate cost below USD 15. +- Live records retain only scenario, model, request/tool counts, token counts, + run ID, outcome, and recovery/replay reuse status. +- Raw model content, databases, and keys stay in ignored local evidence. +- Hosted jobs are described as executed only when exact-head run records and + retained artifact digests exist. +- Native and emulated container architecture results are labeled explicitly. +- Every verified limitation links to focused tests plus at least one public + product path. + +## Required deterministic gates + +```console +cargo xtask verify +cargo xtask acceptance +cargo xtask examples-verify +cargo xtask docs-verify +cargo xtask package +cargo xtask secret-scan +cargo xtask artifact-store-verify +cargo xtask migration-verify +cargo xtask protocol-resilience +cargo xtask completeness +``` + +## Required opt-in gates + +```console +cargo xtask examples-verify-live-openai +cargo xtask resource-budget-live-openai +cargo xtask acceptance-container +``` + +## Workstream evidence + +| Workstream | Focused evidence | Composite evidence | Status | +| --- | --- | --- | --- | +| Artifact CAS | 19 store tests and 38 runtime tests | CLI acceptance and hardened OCI acceptance passed | verified | +| Legacy upgrades | all retained schema fixtures, dry-run, rollback, import, boundary, repair/replay tests | migration verification command and the full deterministic gate passed | verified | +| Reconciliation | immutable transition matrix, schema/tool/hook/policy, repair and resume tests | packaged operational composition and native Linux arm64 compensation/reconciliation passed | verified | +| Terminal retry | runtime/store identity, roots, acknowledgements, reconciliation, lineage, source immutability, and replay tests passed | packaged durable pipeline and native Linux arm64 failed-only retry passed | verified | +| Sensitive-state encryption | authenticated context, wrong-key, tamper, inventory, stale-writer trigger, rollback, rotation, checkpoint, and retained-schema tests passed | packaged CLI scenario 31 and the 12-stage verification gate passed | verified | +| Secret references | environment compatibility, file bounds/missing/symlink containment, process allowlist/timeout/output/cancellation, zeroizing values, adapter redaction, and raw-database absence tests passed | packaged CLI scenario 32 and the 12-stage verification gate passed | verified | +| Parallel scheduling | overlap, caps, conflicts, ordered atomic commits, approvals, cancellation, retry, repair, and replay tests passed | packaged durable/native OCI composites and two live agent branches passed | verified | +| Foreach/matrix | compiler bounds/identity tests and runtime partial-failure, child retry, sibling reuse, aggregation, and replay tests passed | packaged durable/native OCI composites and the live two-child agent matrix passed | verified | +| Conditions/routers | compiler typed-case/guard failures and runtime durable condition, route, retry, changed-input repair, and skipped replay tests passed | packaged operational route and live structured-agent route passed | verified | +| Bounded loops | compiler bounds/identity tests and runtime zero/one/max, exhaustion, cancellation, uncertain effect, retry, repair, and replay tests passed | packaged operational loop and live two-iteration agent loop passed | verified | +| Sub-workflows | compiler namespacing/version/cycle/state-isolation tests and runtime typed boundary, retry, repair, and replay tests passed | packaged operational composition, integrity-pinned pack example, and live agent sub-workflow passed | verified | +| Compensation | compiler declarations plus runtime reverse order, approval, partial failure, source and inverse uncertainty, cancellation, retry, reconciliation, automatic trigger, repair/retry invalidation, and replay tests passed | packaged operational composition and native Linux arm64 compensation/reconciliation/replay passed | verified | +| Structured handoffs | compiler rejects hidden teams; typed role and handoff contracts use ordinary task recovery | packaged completeness and live collector/reviewer handoff passed | verified | +| Streaming | provider SSE fragmentation plus runtime bounds, redaction, final validation, and replay tests passed | packaged CLI scenario 40 and live OpenAI streaming marker/replay passed | verified | +| MCP/A2A resilience | 18 protocol tests, 93 runtime tests plus one ignored environment-gated container test, schema 13 migration/encryption/replay tests, and `cargo xtask protocol-resilience` passed | packaged CLI scenario 41 reconnects MCP once and continues one known A2A task through CAS, retry, and replay without resubmission | verified | +| Packs/trust/extensions | 6 resolver/trust tests and 3 focused runtime protocol tests cover graph, sources, locks, Sigstore, trust gating, bounds, cancellation, redaction, and replay | packaged CLI scenario 42 verifies a two-pack lock plus one explicitly authorized process extension invocation and effect-free replay | verified | +| Semantic memory | typed contracts; stable text/vector/hybrid ranking; filters, namespace, expiry, corrupt-dimension, encryption, external-adapter, OpenAI WireMock, credential-preflight, repair, and replay tests passed | packaged CLI scenario 43 covers hybrid retrieval, explicit promotion, CLI put/search/reindex, changed-memory repair, and effect-free replay | verified | +| Network enforcement | scheme/host/port, IPv4/IPv6 classification, every-answer validation, DNS pinning, proxy default deny, redirect refusal, CA success/failure, response bounds, and deterministic credential preflight passed | packaged CLI scenario 44 denies private egress before persistence or I/O | verified | +| Process isolation | DSL validation, plan requirements, command construction, environment, working directory, output/time/cancellation, process-tree cleanup, resource flags, missing-backend tests, and engine image-ID normalization passed | packaged CLI scenario 45 fails a requested unavailable engine before effect dispatch; the real content-addressed container action passed through native Linux arm64 Podman | verified | +| Resource and cost budgets | compiler, store, runtime, CLI, retry/repair/replay, race, and exact-bound tests passed | packaged CLI scenario 46 plus a one-request live GPT-5.6 denial-before-request-2 gate passed | verified | +| Stateless provider continuation | compiler/provider/runtime tests cover negotiation, ordered multiple calls, opaque reasoning, malformed items, encrypted persistence, pause/resume, repair freshness, and replay | packaged GPT-5.6 stateless tool run and keyless zero-effect replay passed | verified | +| Container/cross-platform | native Linux arm64 OCI runtime, signal, durable composite, retry, repair, CAS export, compensation/reconciliation, replay, Trivy 0.72.0, SBOM, and image inspection passed | exact-head hosted Linux x64, macOS arm64, Windows x64, container, security, package, and SBOM gates execute under XPLAT-001 | verified | +| OpenAI live matrix | 27-request retained GPT-5.6 matrix, 3,939 input tokens, 560 output tokens, 20 reasoning tokens, and 8 tool calls | packaged macOS arm64 and native Linux arm64 OCI runs cover basic, tool, parallel, matrix, route, loop, sub-workflow, handoff, retry, repair, CAS, replay, streaming, and budget boundaries | verified | +| Canonical and Pages docs | canonical docs and generated schema passed the full local documentation gate | Pages imported 61 canonical pages; writing, spelling, 70 HTML routes/links, search, and 44 responsive/accessibility browser tests passed | verified | + +## Final adversarial review + +Status: passed with no unresolved P0, P1, or scoped P2 finding. + +The clean pass reviewed security and secret handling, all retained migrations, +effect and reconciliation safety, artifact integrity, concurrent scheduling, +retry/repair/replay lineage, provider continuation, protocol reconnect, pack +trust, selected-field encryption, budgets, container behavior, every public +example, live evidence, hosted workflow coverage, and public claims. + +It found zero P0s, three P1s, and five scoped P2s. The P1s were a repair plan +that aborted instead of returning a blocked-input diagnostic, an OCI live gate +that copied the wrong repair fixture, and a live continuation that could check +an existing cost overrun only after dispatch. The scoped P2s were +model/tool-effect miscounting, a two-write evidence completion window, a +missing documented artifact-store command, missing completeness execution in +the hosted matrices, and stale pre-burn-down public status text. All findings +were fixed and covered by focused tests or local validation. The final +credential-free gates, actionlint, deterministic secret scan, native Linux +arm64 OCI acceptance, exact-image Trivy/SBOM checks, and retained GPT-5.6 +evidence are green. +> Canonical source: [`docs/execution/COMPLETENESS_VERIFICATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/execution/COMPLETENESS_VERIFICATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/database.md b/src/content/docs/_generated/reference/database.md index 3746d47..b12ba02 100644 --- a/src/content/docs/_generated/reference/database.md +++ b/src/content/docs/_generated/reference/database.md @@ -3,20 +3,32 @@ title: "Database and migrations" description: "SQLite records, schema migration, locking, backup, and retention." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/reference/DATABASE.md" --- -The local SQLite database is both history and part of the correctness boundary. The current database schema version is `4`. +The local SQLite database and its sibling artifact root are history and part of the correctness boundary. The current database schema version is `15`. ## Stored records -- runs, source workflow, compiled plan, inputs, output, mode, state, and parent linkage -- task states, attempts, output, and errors +- runs, source workflow, compiled plan, inputs, output, mode, state, parent linkage, and repair/retry source/root metadata +- task states, attempts, output, errors, disposition, source attempt, versioned fingerprints/digests, state delta, artifact manifest, reuse decision, and encrypted-capable execution memory snapshot - effects, request/result/error, confirmation, and uncertainty +- immutable effect reconciliation history, operator authorization, evidence, validated results, supersession, and compensation linkage - approvals and resolutions - checksummed checkpoints - ordered audit and trace events +- run-wide budget limits, planned graph counts, actual usage, active + reservations, reconciliation sources, and exceeded dimension - provider sessions and tool calls -- namespaced long-term memory with optional expiry +- MCP/A2A sessions and calls with remote identity, generation, continuation status, and replay linkage +- typed namespaced long-term memory with format version, searchable text, + metadata, embedding provider/dimensions/vector, creation time, and optional + expiry +- content-addressed blob metadata, logical run/task references, provenance, verification time, and bounded ingestion leases +- legacy-run upgrade analysis and the exact task metadata applied by each upgrade -Working memory is stored on the run and in checkpoints. Provider credentials are not stored. Other confidential content may be stored, including prompts, tool output, and remote artifacts. +Working memory is stored on the run and in checkpoints. Provider credentials and state-encryption key values are not stored. Prompts, workflow inputs and outputs, task output and errors, effect input/results, approvals, checkpoints, audit/trace payloads, provider continuations, reconciliation evidence, and long-term-memory values can be protected with application-level authenticated envelopes. + +Migration 5 adds `source_run_id`, `source_workflow_digest`, repair roots/reason/version, and task-boundary metadata used by repair. Migration 6 adds artifact blob, reference, and ingestion-lease tables. Migration 7 records transactional legacy-run upgrades. Migration 8 adds immutable effect reconciliation records. Migration 9 adds retry roots/reason/version and failed-only selection. Migration 10 adds state-encryption configuration and fail-closed write guards. Migration 11 adds the protected execution-memory snapshot used to preserve parallel task boundaries across crashes and approvals. Migration 12 adds encrypted-capable bounded provider stream events with task-attempt and replay-source sequence linkage. Migration 13 adds encrypted-capable MCP/A2A session and call records with generation, remote identity, status, and replay-source linkage. Migration 14 upgrades legacy long-term-memory values to typed format-versioned entries and adds searchable text, metadata, embedding identity/vector, creation time, and a namespace/expiry search index. Migration 15 adds per-run budget snapshots and idempotent effect reservations; retained runs receive an unlimited ledger with existing task counts. Embedding vectors are encryption-capable selected fields. A repair or retry transaction creates the run, materializes every reused task and artifact reference, creates pending fresh tasks, records provenance audit events, initializes its budget ledger, and writes its first checkpoint atomically. Protocol lineage is copied for materialized tasks before execution begins. The source identifier is durable lineage rather than a foreign-key dependency, so source garbage collection does not delete the derived run. + +Artifact manifests contain logical path/name, media type, byte size, SHA-256 digest, and CAS-relative path. Blob bytes live under `/artifacts/sha256/`; identical content is stored once. A completed repair/replay receives its own references, so source-row and workspace deletion do not break it. ## Migrations @@ -25,21 +37,35 @@ The store reads SQLite `user_version` and applies forward migrations in order in ```text agentctl db stats --db .agentctl/runtime.db --output json --color never agentctl db migrate --db .agentctl/runtime.db --output json --color never +agentctl runs --db .agentctl/runtime.db analyze RUN_ID --output json +agentctl runs --db .agentctl/runtime.db upgrade RUN_ID --dry-run --output json +agentctl runs --db .agentctl/runtime.db upgrade RUN_ID --output json +agentctl effects --db .agentctl/runtime.db list RUN_ID --output json +agentctl db --db .agentctl/runtime.db encryption inventory --output json +agentctl db --db .agentctl/runtime.db encryption enable --key-id KEY_ID --key-env KEY_ENV --dry-run +agentctl db --db .agentctl/runtime.db encryption rotate --key-id NEW_KEY_ID --key-env NEW_KEY_ENV --dry-run +agentctl artifacts --db .agentctl/runtime.db list --run RUN_ID --output json +agentctl artifacts --db .agentctl/runtime.db verify --all --output json +agentctl artifacts --db .agentctl/runtime.db export SHA256_DIGEST ./report.bin +agentctl artifacts --db .agentctl/runtime.db gc --older-than-days 30 --dry-run +agentctl memory --db .agentctl/runtime.db search NAMESPACE QUERY --mode hybrid +agentctl memory --db .agentctl/runtime.db reindex NAMESPACE ``` -`db migrate` may write the database. Back up the database and its WAL state before an upgrade. +`db migrate` and encryption enable/rotation may write the database. Back up the database and its WAL state before an upgrade. An encrypted backup requires the referenced key value; the database stores only the key ID and environment-variable name. Retire pre-encryption backups and snapshots according to their confidentiality requirements. ## Locking and permissions -The connection enables foreign keys, WAL mode, and a five-second busy timeout. Unix database files use mode `0600`. Windows relies on user-profile ACLs. Separate runs can share a database, but this is not a distributed lease and does not prevent two runs from changing the same external resource. +The connection enables foreign keys, WAL mode, and a five-second busy timeout. Unix database files use mode `0600`. Windows relies on user-profile ACLs. Artifact ingestion and GC use an advisory cross-process lock plus SQLite leases; this protects the local store but is not a distributed lease. Separate runs can share a database but can still change the same external resource. ## Backups and recovery -Use an SQLite-aware online backup or stop writers before copying the database and WAL files. Restore the set consistently. Do not use ordinary file synchronization that can separate a database from uncheckpointed WAL content. +Use an SQLite-aware online backup or stop writers before copying the database, WAL files, and sibling `artifacts/` directory. Restore the set consistently. Do not use ordinary file synchronization that can separate SQLite from uncheckpointed WAL content or the artifact bytes referenced by it. Delete old terminal history only after retention requirements are met: ```text agentctl gc --db .agentctl/runtime.db --older-than-days 30 --output json --color never +agentctl artifacts --db .agentctl/runtime.db gc --older-than-days 30 --output json --color never ``` -> Canonical source: [`docs/reference/DATABASE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/DATABASE.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/reference/DATABASE.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/DATABASE.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/environment.md b/src/content/docs/_generated/reference/environment.md index 0bea074..9c79a48 100644 --- a/src/content/docs/_generated/reference/environment.md +++ b/src/content/docs/_generated/reference/environment.md @@ -13,7 +13,16 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/reference/ENV | `anthropic` | `ANTHROPIC_API_KEY` | The workflow dispatches an Anthropic request. | | `google` | `GEMINI_API_KEY` | The workflow dispatches a Google request. | -These names are defaults used by repository examples. A workflow can name another valid environment reference. Policy must allow the name. Values never belong in YAML, CLI arguments, ordinary inputs, logs, or committed fixtures. +These names are defaults used by repository examples. A workflow can name +another valid environment reference or use a mounted-file or policy-gated +process reference. Primary provider credential environment names do not require +a duplicate environment allowlist entry; custom headers and action environment +values do. Values never belong in YAML, CLI arguments, ordinary inputs, logs, +or committed fixtures. See [Secret references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). + +## State-encryption keys + +State encryption accepts an environment-variable reference through `--key-env`. The referenced value must be base64 for exactly 32 bytes. The database stores the key ID and environment-variable name, never the value. Once enabled, every command that opens that database must receive the current reference. Rotation also needs the new reference for that command. ## Repository and acceptance variables @@ -21,7 +30,7 @@ These names are defaults used by repository examples. A workflow can name anothe | --- | --- | --- | | `AGENTCTL_CONTAINER_ENGINE` | local acceptance | Select `docker` or `podman` when auto-detection is unsuitable. | | `AGENTCTL_BUILD_CA_FILE` | local container build | Path to a reviewed CA bundle supplied as a build secret. | -| `AGENTCTL_BUILD_CA_PEM` | hosted container workflow | Protected secret materialized temporarily by CI. | +| `AGENTCTL_BUILD_CA_PEM` | non-PR hosted container workflow | Protected secret materialized temporarily by `main` or manually dispatched CI; pull-request runs never receive it. | Normal `cargo xtask docs-verify`, `cargo xtask verify`, and `cargo xtask acceptance` need no provider credential. @@ -32,7 +41,8 @@ Normal `cargo xtask docs-verify`, `cargo xtask verify`, and `cargo xtask accepta | Workflow file | positional argument | Read-only input, at most 1 MiB. | | Workspace | current directory | Override with `--workspace`. | | Runtime database | `.agentctl/runtime.db` | Override with `--db`; SQLite WAL belongs to the same state set. | -| Artifact path | workflow-defined | Must remain under a policy-approved writable root. | +| CAS artifact root | `/artifacts` | Immutable SHA-256 blobs; back up with SQLite. | +| Workflow output path | workflow-defined | Must remain under a policy-approved writable root; successful bounded files are ingested into CAS. | ## Container paths @@ -40,9 +50,10 @@ Normal `cargo xtask docs-verify`, `cargo xtask verify`, and `cargo xtask accepta | --- | --- | | `/config` | reviewed read-only configuration | | `/workspace` | normally read-only workspace | -| `/state` | writable durable state | -| `/artifacts` | writable collected output | +| `/state` | writable SQLite and content-addressed durable state | +| `/artifacts` | writable workflow output/export mount | +| `/run/secrets` | optional read-only mounted secret files granted through `secretFileRoots` | | `/tmp` | small runtime tmpfs when the root filesystem is read-only | State and artifacts must be writable by UID/GID 65532 in the production image. -> Canonical source: [`docs/reference/ENVIRONMENT_AND_PATHS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/ENVIRONMENT_AND_PATHS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/reference/ENVIRONMENT_AND_PATHS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/ENVIRONMENT_AND_PATHS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/limitation-burndown.md b/src/content/docs/_generated/reference/limitation-burndown.md new file mode 100644 index 0000000..9150e40 --- /dev/null +++ b/src/content/docs/_generated/reference/limitation-burndown.md @@ -0,0 +1,945 @@ +--- +title: "Limitation burn-down" +description: "Authoritative disposition of every identified framework limitation." +editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/execution/LIMITATION_BURNDOWN.md" +--- +This is the authoritative register for the framework-completeness program. It +supersedes roadmap language that classified core durability, recovery, +orchestration, security, or operability work as deferred merely because the +workflow API is young. + +Program state values are `open`, `in progress`, and `verified`. They describe +the active work queue and are not final dispositions. Before this program is +complete, every entry must have exactly one final disposition: + +- `implemented` +- `redesigned` +- `removed from supported surface` +- `externally blocked` + +Closure count: 30 limitations, comprising 24 implemented, 2 redesigned, and 4 +removed from the supported surface. No limitation remains externally blocked. +All 30 program states are verified. + +## Dependency order + +1. Persistence foundations: artifact content addressing, schema migration, + sensitive-field encryption, and durable reconciliation. +2. Recovery contracts: legacy-run analysis, terminal retry, compensation, and + artifact-independent repair/replay. +3. Deterministic scheduler: parallel commits, conflict detection, bounded + expansion, conditions, loops, and sub-workflows. +4. Bounded agent composition and event output: structured handoffs and + streaming. +5. Remote and extension boundaries: MCP, A2A, pack locking, trust, and the + isolated extension protocol. +6. Optional semantic memory, network/process isolation, and resource budgets. +7. Composite acceptance, container/cross-platform evidence, live OpenAI proof, + documentation, and adversarial review. + +## Register summary + +| ID | Category | Program state | Intended final disposition | +| --- | --- | --- | --- | +| ART-001 | Durable artifacts | verified | implemented | +| MIG-001 | Legacy selective repair | verified | implemented | +| EFX-001 | Effect reconciliation | verified | implemented | +| RET-001 | Terminal-run retry | verified | implemented | +| ENC-001 | Sensitive-state encryption | verified | implemented | +| SEC-001 | Secret providers | verified | implemented | +| NET-001 | Network policy | verified | implemented | +| ISO-001 | Process isolation | verified | implemented | +| BUD-001 | Resource and cost budgets | verified | implemented | +| SCH-001 | Deterministic parallel execution | verified | implemented | +| DYN-001 | Foreach and matrix | verified | implemented | +| COND-001 | Conditions and routers | verified | implemented | +| LOOP-001 | Bounded loops | verified | implemented | +| SUB-001 | Sub-workflows | verified | implemented | +| COMP-001 | Compensation | verified | implemented | +| TEAM-001 | Structured teams and handoffs | verified | redesigned | +| STR-001 | Streaming | verified | implemented | +| MCP-001 | MCP resilience | verified | implemented | +| A2A-001 | A2A resilience | verified | implemented | +| PACK-001 | Pack resolution and lockfiles | verified | implemented | +| TRUST-001 | Pack integrity and signing | verified | implemented | +| EXT-001 | Plugin strategy | verified | redesigned | +| MEM-001 | Semantic memory | verified | implemented | +| PROV-001 | Stateless provider continuation | verified | implemented | +| OCI-001 | Container execution | verified | implemented | +| XPLAT-001 | Cross-platform hosted evidence | verified | implemented | +| EVENT-001 | Event triggers and calendars | verified | removed from supported surface | +| DIST-001 | Distributed execution and storage | verified | removed from supported surface | +| REG-001 | Hosted public registry | verified | removed from supported surface | +| UI-001 | Hosted UI, chat, and visual orchestration | verified | removed from supported surface | + +## Persistence and recovery + +### ART-001: Durable content-addressed artifacts + +- Current behavior: successful bounded file outputs are atomically ingested + into an immutable local SHA-256 CAS beside the database. SQLite stores blob + metadata, per-run/task references, provenance, and ingestion leases. +- User impact: repair, replay, verification, and export continue after the + source workspace file is deleted. +- Security or durability impact: bytes and metadata form one backup boundary; + digest verification detects missing/corrupt blobs. +- Product decision: use a local filesystem content-addressed store beside the + state database. SQLite owns metadata, references, provenance, retention, and + reachability. Blob bytes never enter ordinary SQLite rows. +- Required implementation: atomic verified ingestion, immutable deduplicated + blobs, media type and logical-name metadata, run/task references, corruption + verification, export/materialization, inspection, and reachability GC. +- Migration impact: schema 6 adds CAS metadata/reference/lease tables. Explicit + legacy analysis/import is tracked separately by MIG-001. +- Tests: duplicate ingestion, partial writes, corrupt/missing/wrong-digest + blobs, disk failures, concurrent ingestion, traversal/symlink rejection, + workspace/source deletion, repair, replay, GC, read-only consumption, and + redaction. +- Examples: durable pipeline and container pipeline. +- Live evidence: bounded OpenAI artifact-producing repair plus offline replay. +- Documentation: artifact store, container mounts, backup, repair, replay, and + GC. +- Final disposition: implemented and verified by 19 store tests, 38 runtime + tests, credential-free artifact CLI acceptance, and hardened OCI acceptance. + +### MIG-001: Legacy run analysis and upgrade + +- Current behavior: `runs analyze` and `runs upgrade` derive only metadata + proven by retained workflow, plan, effects, outputs, and checksummed + checkpoints. Unprovable suffixes receive conservative safe repair roots. +- User impact: compatible proven predecessors remain reusable without a full + fork. +- Security or durability impact: fabricating missing fingerprints or deltas + would permit unsafe reuse. +- Product decision: implement transactional dry-run analysis and an explicit + run upgrade. Derive only provable metadata and calculate the earliest safe + root for everything else. +- Required implementation: `runs upgrade` analysis/apply UX, confidence and + provenance records, digest derivation, checkpoint-delta reconstruction, + artifact import, and earliest-safe-boundary output. +- Migration impact: schema 7 records additive transactional upgrades; every + retained schema fixture remains readable and source execution records remain + unchanged. +- Tests: schema fixtures 1 through 5, complete/partial/impossible derivation, + failed-upgrade rollback, dry run, corrupt checkpoints, and boundary choice. +- Examples: legacy analysis followed by selective retry/repair. +- Live evidence: not required; the contract is deterministic. +- Documentation: database migration, compatibility, and operator guidance. +- Final disposition: implemented and verified by retained-schema migration, + dry-run immutability, artifact-import, failed-upgrade rollback, + impossible-proof boundary, selective repair, workspace deletion, and offline + replay tests. + +### EFX-001: Complete operator reconciliation + +- Current behavior: source effects are immutable. Versioned reconciliation + records represent `applied`, `not_applied`, and `compensated` conclusions + with effective runtime projection. +- User impact: an operator can resume from a validated applied result, begin a + fresh attempt after not-applied/compensated evidence, and safely unblock a + compatible repair. +- Security or durability impact: operators may resort to unsafe forks or + out-of-band database edits. +- Product decision: preserve immutable source effects and append versioned + reconciliation records with one active conclusion. +- Required implementation: list, inspect, and reconcile outcomes `applied`, + `not_applied`, and `compensated`; identity, timestamp, reason, evidence, + optional validated result, supersession rules, compensation linkage, audit, + trace, policy, and non-interactive behavior. +- Migration impact: schema 8 adds reconciliation history and effective-effect + projection. Existing source effects are never rewritten. +- Tests: every transition, contradictory decisions, supersession, wrong + schemas, operator policy, repair/resume/retry integration, idempotency keys, + and transaction rollback. +- Examples: operational workflow with manual applied and compensated outcomes. +- Live evidence: selective repair after an explicitly reconciled mock effect. +- Documentation: effect recovery and honest external-state semantics. +- Final disposition: implemented and verified by transition/supersession, + contradiction, compensation-link, immutable-source, audit/trace, + result-schema/tool-contract/hook, policy approval, repair, and both resume + paths. + +### RET-001: Terminal-run retry + +- Current behavior: task retry is same-run and bounded; `agentctl retry` + creates a distinct source-linked run for an unchanged terminal workflow. +- User impact: operational retry of a failed unchanged workflow is obscure. +- Security or durability impact: a fork can repeat successful external effects. +- Product decision: add a distinct source-linked retry plan and run mode. It + requires the identical workflow definition and reuses compatible success. +- Required implementation: failed-only, selected roots, multiple roots, + successful-root acknowledgement, plan/JSON/human output, fresh attempts, + lineage, effect safety, reconciliation, and offline replay. +- Migration impact: new run mode and source/roots metadata are additive. +- Tests: failed-only closure, branches, multiple roots, workflow mismatch, + explicit successful restart, uncertain effects, source immutability, and + replay. +- Examples: durable pipeline retry after deterministic downstream failure. +- Live evidence: bounded deterministic provider failure followed by live retry. +- Documentation: retry versus resume, repair, replay, and fork. +- Final disposition: implemented and verified by failed-only and selected-root + planning, multiple-root and successful-root acknowledgement tests, exact + workflow identity enforcement, reuse and source-immutability checks, + uncertain-effect reconciliation coverage, schema-9 lineage persistence, + offline replay, and packaged CLI acceptance. + +### ENC-001: Envelope encryption for sensitive persisted fields + +- Current behavior: identified confidential fields can be inventoried and + transactionally migrated to authenticated envelopes, then fail closed. +- User impact: filesystem disclosure reveals confidential workflow history. +- Security or durability impact: SQLite permissions are not confidentiality at + rest. +- Product decision: use an established authenticated-encryption crate and a + versioned envelope for identified sensitive JSON/text fields. Do not claim + full-database encryption. +- Required implementation: key references, key IDs, authenticated associated + data, strict no-fallback decryption, rotation, redacted inspection, + backup/restore guidance, and bounded migration. +- Migration impact: transactional plaintext-to-envelope migration with dry-run + inventory and rollback on wrong/missing keys. +- Tests: known vectors where provided by the library, wrong key, tampering, + rotation, mixed versions, migration rollback, and no plaintext remnants in + protected columns. +- Examples: encrypted state with redacted inspection. +- Live evidence: no provider call required. +- Documentation: protected fields, key lifecycle, and residual metadata. +- Final disposition: implemented and verified by authenticated-context + roundtrips, missing/wrong-key and tamper failure, dry-run inventory, + protected-column scans, trigger-enforced no-fallback writes, injected + rotation rollback, full atomic rotation, schema-10 fixture migration, normal + read compatibility, checkpoint integrity, and packaged CLI replay. + +## Workflow language and runtime + +### SCH-001: Deterministic parallel scheduling + +- Current behavior: `maxConcurrency` accepts 1 through 64 and defaults to 1. +- User impact: independent model and deterministic tasks cannot overlap. +- Security or durability impact: naive concurrency would make state and effect + order race-dependent. +- Product decision: execute a stable ready batch concurrently but commit task + results in compiled order. Tasks declare working-memory write sets; conflicting + writes fail before dispatch unless an explicit deterministic merge exists. +- Required implementation: concurrency semaphore, isolated task snapshots, + ordered commit queue, failure/cancellation/approval behavior, effect and trace + parentage, repair/retry/replay integration, and plan visibility. +- Migration impact: additive DSL/plan fields retain sequential defaults. + Database migration 11 adds an encrypted-capable per-task execution-memory + snapshot so crashes and approvals preserve the original batch boundary. +- Tests: real overlap, stable commit order, conflict rejection, cancellation, + approval, failures, effects, replay, repair, and container execution. +- Examples: parallel deterministic and agent branches. +- Live evidence: two bounded OpenAI branches. +- Documentation: scheduling and state conflict rules. +- Final disposition: implemented. Deterministic verification covers real + overlap and the concurrency cap, compiled write-conflict rejection, runtime + declared-key enforcement before effects, atomic rollback injection, + plan-order audit assertions, disjoint state merge, stop/continue boundary + behavior, cancellation, multi-approval resume, failed-only retry, selective + repair, and offline replay. The packaged durable composite and native Linux + arm64 OCI composite both passed with four deterministic ready tasks and + ordered recovery. The packaged GPT-5.6 composite then executed two live + branches and keyless replay, closing the live boundary. + +### DYN-001: Bounded foreach and matrix expansion + +- Current behavior: static typed foreach lists and matrix axes compile to + bounded durable child tasks and an ordered aggregate. +- User impact: authors duplicate similar tasks and cannot retry individual + expanded units. +- Security or durability impact: model-controlled unbounded expansion could + exhaust resources. +- Product decision: compile static foreach and matrix values only. Runtime or + model-controlled graph growth is outside the supported surface. +- Required implementation: stable escaped child IDs, item binding, count + limits, aggregate output, partial-failure rules, child inspection, + repair/retry/replay, and task budgets. +- Migration impact: plan/checkpoint formats gain expansion records. +- Tests: order, ID collisions, bounds, aggregation, partial failure, individual + retry/repair, replay, and malformed input. +- Examples: small deterministic and agent matrices. +- Live evidence: two-item OpenAI matrix. +- Documentation: syntax, limits, IDs, and recovery. +- Final disposition: implemented. Static typed lists and Cartesian axes compile + to stable digest-qualified child IDs and an ordered parent aggregate. + Deterministic verification covers bounds, malformed bindings, identity, + output aggregation, partial failure, failed-only child retry, sibling reuse, + and offline replay. The packaged and native Linux arm64 composites both + passed a four-child matrix through retry, repair, and replay. The packaged + GPT-5.6 composite executed a two-child agent matrix with stable inspection + and keyless replay. + +### COND-001: Typed conditions and routers + +- Current behavior: constrained typed conditions and explicit pure router tasks + persist decisions and skip only enumerated destinations. +- User impact: nontrivial deterministic branching is awkward. +- Security or durability impact: expanding to arbitrary expressions would add + code execution and ambiguous dependencies. +- Product decision: version the existing constrained expression AST and add a + typed route selector with enumerated destinations. +- Required implementation: compile-time validation, durable evaluation input + and decision, skipped-state semantics, changed-input invalidation, plan + visibility, output option contracts, repair/retry/replay. +- Migration impact: task state and plan versions add condition decisions. +- Tests: types, missing/null, invalid routes, skips, downstream behavior, + changed decisions, repair, and replay. +- Examples: structured agent output routed to deterministic branches. +- Live evidence: one structured-output routing scenario. +- Documentation: expression grammar and skip semantics. +- Final disposition: implemented. Conditions use the constrained typed + evaluator and retain expression, context digest, and result. Routers compare + one exact typed selector against unique JSON cases, record selected value and + destinations, and durably skip unselected branches. Deterministic + verification covers strict typing, malformed routes, local vars, plan + guards, retry, changed-decision repair, skipped-task replay, and zero replay + effects. The packaged operational composite selected one route and durably + skipped the other before compensation. The packaged GPT-5.6 composite used + a structured agent output to select `execute`, durably skipped the default + branch, and replayed without effects. + +### LOOP-001: Bounded loops + +- Current behavior: a task-level loop compiles into a bounded sequential chain + of durable iteration tasks and one pure aggregate. +- User impact: bounded refine/verify workflows require duplicated tasks. +- Security or durability impact: an unbounded model-owned loop violates the + runtime's bounded-execution thesis. +- Product decision: implement a durable loop construct with typed condition, + explicit maximum iterations, and iteration-local output/state boundaries. +- Required implementation: stable iteration IDs, durable iteration state, + outputs, cancellation, effect identities, repair/retry at boundaries, replay, + and loop/resource budgets. +- Migration impact: the DSL and compiled plan gain additive loop records. + Iterations use existing task, checkpoint, effect, and attempt storage, so no + SQLite migration is required. +- Tests: zero/one/max iterations, bound exceeded, cancellation, uncertain + effect, repair/retry, and replay. +- Examples: bounded operational verification loop. +- Live evidence: a two-iteration maximum agent scenario. +- Documentation: loop safety and recovery. +- Final disposition: implemented. Iteration IDs and bindings are stable, + `maxIterations` is required and capped at 64, typed guards run before each + iteration, false guards durably skip the remaining chain, and a still-true + final guard fails closed. Deterministic verification covers zero, one, and + maximum iterations, bound exhaustion, cancellation with an uncertain + in-flight provider effect, per-boundary retry and repair, offline replay, and + zero replay effects. Packaged CLI scenario 36 and the operational composite + verify plan, two committed iterations, one skipped bound, cancellation, + inspection, and replay. The packaged GPT-5.6 composite executed two bounded + agent iterations, skipped the third compiled child, and replayed keylessly. + +### SUB-001: Reusable sub-workflows + +- Current behavior: inline and integrity-pinned pack definitions compile into a + typed input boundary, namespaced ordinary child tasks, and a typed output + aggregate. +- User impact: reusable graph composition requires copying tasks. +- Security or durability impact: implicit policy/provider inheritance could + broaden authority. +- Product decision: compile versioned sub-workflows into namespaced tasks with + explicit typed inputs/outputs and monotonic policy inheritance. +- Required implementation: pack/local definitions, namespace escaping, + recursion/cycle checks, state isolation, provider mapping, artifact ownership, + lineage, errors, inspection, repair/retry/replay. +- Migration impact: workflow and pack schemas gain additive reusable workflow + definitions. Compiled plans gain pure boundary variants; existing task, + effect, artifact, checkpoint, and attempt storage is reused. +- Tests: nesting, collisions, cycles, policy narrowing, output contracts, + failures, artifacts, repair/retry/replay. +- Examples: operational workflow calling a reusable sub-workflow. +- Live evidence: sub-workflow containing one OpenAI task. +- Documentation: authoring, versioning, and policy inheritance. +- Final disposition: implemented. Definitions carry a semantic version and + JSON Schema input/output interfaces. Nested calls flatten recursively and + cycles fail compilation. The caller's policy and providers remain + authoritative, deterministic memory keys are invocation-prefixed, and + namespaced children retain artifact/effect ownership and ordinary + retry/repair/replay lineage. Focused compiler and runtime verification covers + stable expansion, typed rejection, state isolation, selected-boundary retry + and repair, and zero-effect replay. Packaged CLI scenario 37 and the + integrity-pinned pack example pass. The operational composite also executed + its namespaced typed sub-workflow through failure and compensation. The + packaged GPT-5.6 composite executed one agent inside the versioned typed + sub-workflow and replayed the flattened graph without effects. + +### COMP-001: Explicit compensation + +- Current behavior: compensable tasks declare a named effectful inverse action. + `agentctl compensate` plans and executes eligible source effects through a + separate source-linked run. +- User impact: operators cannot durably coordinate best-effort reversal. +- Security or durability impact: documentation-shaped metadata can be mistaken + for transactional rollback. +- Product decision: compensation is an explicit sequential run in reverse + compiled graph order, never a transactional rollback claim. +- Required implementation: declaration validation, manual trigger, opt-in + automatic trigger, approval, idempotency, partial failure, linkage to effects + and reconciliation, audit, trace, retry/repair behavior. +- Migration impact: the additive `compensation` run mode reuses existing source + lineage, task, effect, approval, checkpoint, audit, trace, and reconciliation + storage. No database schema migration is required. +- Tests: order, approval, idempotency, partial failure, source and inverse + uncertainty reconciliation, terminal inverse-run blocking, cancellation, + retry/repair invalidation, and replay. +- Examples: operational workflow compensation. +- Live evidence: deterministic tool compensation only. +- Documentation: guarantees and non-guarantees. +- Final disposition: implemented. Source effects remain immutable; eligible + confirmed mutations execute declared action-based compensation in reverse + order. Successful inverse effects append linked `compensated` + reconciliations. Manual and explicitly automatic triggers, approval, + uncertainty blocking, bounded retries, partial continuation, repeat planning, + selected tasks, repair/retry invalidation, and effect-free replay use the + ordinary durable runtime. Focused compiler/runtime tests, packaged CLI + scenario 38, the 12-stage verification gate, examples, docs, packaging, and + secret scanning pass. + +### TEAM-001: Structured teams and handoffs + +- Current behavior: named bounded agent tasks exchange typed payloads through + explicit deterministic handoff tasks and reusable sub-workflows. +- User impact: roles, payloads, routing, tool visibility, and recovery + boundaries remain visible in the ordinary graph. +- Security or durability impact: hidden agent conversations would bypass the + compiled graph and policy. +- Product decision: redesign teams as explicit agent tasks, typed deterministic + handoff tasks, routers, and reusable sub-workflows. No autonomous hidden + conversation scheduler or `team:` DSL is added. +- Required implementation: bounded roles, typed handoff payloads, explicit + route conditions, per-role provider/tool visibility, durable handoff records, + and ordinary cancellation, repair, retry, replay, audit, and tracing. +- Migration impact: no storage migration. `team:` task uses fail compilation + with exact migration guidance. +- Tests: hidden-team rejection, role tool separation, handoff schemas, turn + bounds, packaged inspection, selected-boundary retry/repair, and replay. +- Examples: two-role evidence collection and verification workflow. +- Live evidence: two-role OpenAI handoff plus deterministic verifier. +- Documentation: compiled replacement, migration, guarantees, and non-goals. +- Final disposition: redesigned. Each role is a task-local bounded agent with + explicit provider, tools, limits, and structured output. Each handoff is an + ordinary typed task output with sender, recipient, payload, task state, + output digest, checkpoint, audit, and trace evidence. Typed routers provide + explicit branching. Packaged scenario 39 verifies role-specific tool + visibility, durable inspection, upstream handoff reuse during retry and + repair, and effect-free replay. Free-form `team:` orchestration is rejected + with migration guidance. The dedicated packaged completeness gate repeats + the typed handoff, downstream verification, retry reuse, and effect-free + replay as one composite. The packaged GPT-5.6 composite executed collector + and reviewer roles with the typed `LIVE_TEAM_READY` handoff and a + deterministic downstream verifier. + +### STR-001: End-to-end streaming + +- Current behavior: fake, OpenAI, and Azure OpenAI agents can emit bounded + durable provider progress while retaining normal final task output. +- User impact: long supported-provider calls expose inspectable progress in + human or JSONL mode. +- Security or durability impact: event and transport caps, redaction, + encrypted-capable storage, and final JSON isolation prevent unbounded deltas + from corrupting automation. +- Product decision: add durable bounded stream events and explicit human or + JSONL progress modes while retaining one final JSON document mode. +- Required implementation: provider fragments, sequence numbers, persisted + bounded/redacted records, backpressure, cancellation, reconnect semantics, + final result validation, and recorded stream replay. +- Migration impact: stream-event table and CLI output contract. +- Tests: fragmented events, backpressure, truncation, redaction, cancellation, + replay, reconnect, and final JSON isolation. +- Examples: streaming agent workflow. +- Live evidence: one packaged OpenAI streaming run. +- Documentation: stdout contracts and replay. +- Final disposition: implemented and verified. Provider + fragments cross an awaited persistence boundary with monotonic task-attempt + sequence numbers. SQLite schema 12 stores at most 256 events per task + attempt and 4 KiB per payload; OpenAI SSE is capped at 8 MiB. Cancellation + preserves accepted records. A dropped or malformed post-dispatch stream is + uncertain and is not reconnected or resubmitted automatically. Terminal + responses still pass ordinary finish-reason, usage, tool, structured-output, + and task-output validation. Human progress uses stderr, JSONL emits + versioned event envelopes plus the final outcome, and final JSON remains one + document. Recorded replay copies source-linked events and performs zero + effects. Focused provider/runtime tests and packaged CLI scenario 40 cover + fragmentation, bounds, redaction, inspection, output isolation, and replay. + The packaged GPT-5.6 composite persisted real stream events, returned the + exact final marker, and replayed with zero effects or provider sessions. + +## Remote protocols, packs, and memory + +### MCP-001: Safe MCP reconnect + +- Current behavior: SQLite schema 13 persists MCP session generations and + immutable call identities. Calls declared `pure`, `idempotent`, or `keyed` + may reinitialize once, refresh `tools/list`, verify the selected schema + digest, and redispatch. Unknown and at-most-once calls never redispatch after + ambiguity. +- User impact: safe observations cannot recover from server restart, and manual + recovery lacks protocol-specific evidence. +- Security or durability impact: automatic retry of an uncertain mutation can + duplicate work. +- Product decision: bounded reconnect is allowed before dispatch and for proven + observations/idempotent calls. Uncertain mutating calls require EFX-001. +- Required implementation: reinitialize, tool-list/schema refresh, auth refresh, + server restart handling, reconnect budget, call identity, streaming, and + repair/retry/replay integration. +- Migration impact: protocol session and call records gain generation/status. +- Tests: restart at each lifecycle boundary, schema change, auth refresh, + cancellation, timeout, and no duplicate mutation. +- Examples: operational mock MCP workflow. +- Live evidence: deterministic local server only. +- Documentation: safe reconnect matrix. +- Final disposition: implemented. Protocol tests cover restart, one-reconnect + bounds, unsafe refusal, stable and changed schemas, auth refresh, SSE, + cancellation, and timeout. Packaged acceptance scenario 41 verifies a + session-expiry reconnect, generation 2 inspection, durable reconnect event, + successful call, and exactly two call attempts. Retry and replay preserve + source-linked protocol records without effects. + +### A2A-001: Safe remote-task continuation + +- Current behavior: the call identity, remote task ID, latest task state, card + generation, and submission ambiguity are durable before observation. + `effects continue-remote` resumes a known task without `SendMessage`. +- User impact: a lost response can strand externally running work. +- Security or durability impact: blind `SendMessage` resubmission duplicates a + remote task. +- Product decision: persist external task IDs before polling and resume polling + or streaming; never resubmit an ambiguous task automatically. +- Required implementation: card refresh, interface compatibility, task ID and + durable local stream sequence persistence with canonical `GetTask` fallback, + auth refresh, artifact retrieval into ART-001, cancellation, bounded retry, + and EFX-001 linkage. +- Migration impact: protocol task/session records. +- Tests: ambiguous submission, polling/stream resume, card/interface change, + auth refresh, cancellation, artifacts, repair/retry/replay. +- Examples: resilient mock A2A workflow. +- Live evidence: deterministic local peer only. +- Documentation: continuation and reconciliation. +- Final disposition: implemented. Mock peers prove known-task continuation, + ambiguous-send refusal, card refresh, bounded polling and streaming fallback, + cancellation, same-origin interface and artifact policy, CAS ingestion, and + auth refresh. Runtime repair tests prove the applied completed result is + schema-validated and materialized while only descendants rerun. Packaged + acceptance scenario 41 performs one `SendMessage`, resumes by task ID, + retrieves an artifact, retries from the recovered boundary, and replays with + zero effects. + +### PACK-001: Deterministic pack resolution and lockfile + +- Current behavior: manifest v1 resolves semantic constraints across contained + local paths, full-commit Git sources, and digest-pinned tar-gzip archives. + Lock v1 records the sorted concrete graph, source, compatibility, digest, and + trust result. `--locked` rejects drift and `--offline` requires cache hits. +- User impact: reusable content has no dependencies, Git/archive source, locked + graph, or offline resolution. +- Security or durability impact: ad hoc fetching weakens reproducibility. +- Product decision: support local path, pinned Git commit, and immutable HTTPS + archive sources with semantic constraints and a checked-in lockfile. No hosted + registry is required. +- Required implementation: resolver, cycles/conflicts, canonical graph, + integrity, offline/locked modes, cache, and update command. +- Migration impact: pack reference and manifest versions plus lockfile v1. +- Tests: constraints, conflicts, cycles, tamper, offline, locked drift, Git + pinning, archive limits, and path escape. +- Examples: transitive local packs and pinned archive fixture. +- Live evidence: not required. +- Documentation: source/trust/lock workflows. +- Final disposition: implemented. Six focused CLI tests cover deterministic + transitive resolution, constraints, conflicts, cycles, path containment, + tamper, unreachable entries, pinned Git cache reuse, offline operation, + immutable archive download and extraction bounds, and link rejection. + Packaged acceptance scenario 42 verifies the checked-in two-pack graph through + the public `packs verify-lock`, run, and replay paths. + +### TRUST-001: Pack authenticity and trust policy + +- Current behavior: every locked manifest has SHA-256 integrity and an explicit + unsigned or Sigstore trust result. Optional verification checks the standard + bundle, public-good trust root, certificate chain, identity, issuer, + transparency proof, and timestamp. Unsigned policy is deny, warn, or allow. +- User impact: users must establish provenance manually. +- Security or durability impact: a valid digest from an untrusted source can + still execute dangerous content. +- Product decision: integrate optional Sigstore-compatible bundle verification + and explicit unsigned policy. Do not invent cryptography. +- Required implementation: identity/issuer allowlists, offline bundle + verification where possible, locked digest binding, unsigned deny/warn/allow, + and process-tool trust gating. +- Migration impact: lockfile trust metadata and policy fields. +- Tests: trusted/untrusted/expired/malformed bundles, unsigned policy, digest + mismatch, and no process execution before trust. +- Examples: signed-fixture verification and explicit unsigned local pack. +- Live evidence: deterministic verification fixture. +- Documentation: trust model and keyless-signing caveats. +- Final disposition: implemented. A public Cosign v3 fixture verifies + successfully through the embedded Rust verifier, even though its short-lived + certificate is now expired, because its signed timestamp proves validity at + signing time. Tampered bytes, invalid timing evidence, an unallowlisted + identity, and malformed bundles fail. Bundle digest and identity metadata are + locked. Unsigned process packs are denied before loading unless the workflow + explicitly acknowledges them. + +### EXT-001: Isolated extension model + +- Current behavior: the supported contracts are reviewed packs, MCP, and + `extension.process`. The process protocol performs an exact version, + schema, and capability handshake before a separately bounded invocation with + a durable effect ID. +- User impact: "plugin ABI" appears as an unresolved roadmap item. +- Security or durability impact: an in-process native ABI would undermine Rust + safety and process isolation. +- Product decision: remove native ABI from the supported surface. The supported + extension contracts are reviewed packs plus MCP or a versioned bounded process + protocol. +- Required implementation: process-protocol handshake, version negotiation, + declared schemas/capabilities, direct argv, timeout/output/cancellation, + policy, and effect identity. MCP remains the network extension option. +- Migration impact: pack action kinds and compatibility guide. +- Tests: version/schema mismatch, output overflow, timeout, cancellation, + policy, secret environment, and crash. +- Examples: local process-protocol extension. +- Live evidence: not required. +- Documentation: definitive plugin strategy and rejection of native libraries. +- Final disposition: redesigned and implemented. Native in-process libraries + are rejected from the product surface. Three runtime tests cover successful + negotiation, output validation, secret redaction, replay without execution, + mismatch before invocation, output overflow, timeout, crash, and + cancellation. Existing policy and process-tree tests cover direct argv, + allowlists, environment selection, output capture, and termination. Packaged + acceptance scenario 42 proves unsigned trust gating, one invocation, effect + inspection, and effect-free replay. + +### MEM-001: Optional semantic retrieval + +- Current behavior: typed namespaced long-term memory supports exact reads, + metadata-filtered text/vector/hybrid retrieval, explicit retention, and + explicit promotion. SQLite and `local_hash` are built in; OpenAI embeddings + and external memory adapters are optional. +- User impact: workflows can retrieve and selectively promote relevant prior + entries without hidden model state. +- Security or durability impact: implicit model memory could bypass retention + and replay boundaries. +- Product decision: add typed entries with deterministic text search, optional + local vector/hybrid search, explicit promotion, namespaces, filters, and + retention. Retrieval remains an effect and replay uses recorded results. +- Required implementation: provider-neutral embedding interface, deterministic + fake embedder, local index, optional OpenAI adapter, external adapter trait, + filters, ranking, and explicit promotion. +- Migration impact: memory schema and index version. +- Tests: deterministic ranking, filters, namespaces, retention, repair/replay, + index rebuild, corrupt dimensions, and fake embeddings. +- Examples: hybrid retrieval and promotion. +- Live evidence: one bounded embedding scenario only if publicly exposed. +- Documentation: memory versus provider cache and working state. +- Final disposition: implemented and verified. Core, store, runtime, provider, + compiler, and CLI tests cover typed/legacy entries, stable text and hybrid + ranking, metadata filters, namespaces, expiry, corrupt dimensions, adapter + validation, OpenAI request mapping and redaction, credential preflight, + reindexing, repair refresh, and replay without adapter calls. Packaged + acceptance scenario 43 executes the public local-hash example, CLI + administration, selective retrieval repair, explicit promotion, and + effect-free replay. No live embedding request is required because public + examples remain deterministic and credential-free. + +### PROV-001: Stateless tool continuation + +- Current behavior: OpenAI/Azure tool agents support `store: false` with + client-held, provider-neutral continuation. +- User impact: privacy-sensitive users can opt out of stored provider responses + without losing tool-loop continuation. +- Security or durability impact: reasoning and function-call items are + retained in order, and missing encrypted reasoning content fails closed. +- Product decision: persist provider-neutral opaque returned items needed for + stateless continuation and replay them on the next request. +- Required implementation: versioned continuation items, provider mapping, + size/redaction bounds, encryption under ENC-001, and capability negotiation. +- Migration impact: the existing provider-session format version 1 already + represents provider-neutral conversations, so no database migration was + required. +- Tests: multiple tools, reasoning items, cancellation, resume, repair session + freshness, encrypted persistence, and malformed items. +- Examples: stateless OpenAI tool workflow. +- Live evidence: one packaged `store: false` OpenAI tool run. +- Documentation: stateful versus stateless continuation. +- Final disposition: implemented and verified. The OpenAI/Azure adapter + automatically requests `reasoning.encrypted_content`, never sends + `previous_response_id` in stateless mode, preserves returned item order and + multiple call IDs, and rejects malformed unencrypted reasoning items. + The 8 MiB stateless-input cap, 4 MiB provider-response cap, secret scrubbing, + protected model-effect results, and protected provider-session columns + supply the size, redaction, and ENC-001 boundaries. + Compiler/provider/runtime tests cover + negotiation, multiple calls, reasoning items, cancellation, malformed + items, encrypted persistence, repair freshness, approval pause/resume, and + effect-free replay. Credential-free acceptance scenario 4 compiles the + stateless tool contract. The packaged GPT-5.6 run + `run-019fa30a-0b7d-79b2-84de-0ee48fc369c7` completed two stateless model + requests, one real tool call, and ordered call/result replay with 530 input + and 33 output tokens. Credential-free replay + `replay-019fa30a-7e3e-73b1-ba5c-5dd293dbbf33` produced identical output with + zero effects, tool calls, and provider sessions. Ignored exact evidence is + retained under `.release-evidence/openai-stateless-2026-07-27/`; the + credential value is absent. + +## Security and operations + +### SEC-001: Stable secret-reference providers + +- Current behavior: environment, bounded mounted-file, and policy-gated direct + process references work across provider credentials, provider/protocol + headers, and action environments. +- User impact: container-native secret files and reviewed credential helpers + work without wrapper scripts or secret-valued workflow inputs. +- Security or durability impact: resolved values stay in zeroizing memory, + while effect records retain only source descriptions and value digests. +- Product decision: version secret references for environment, bounded mounted + file, and optional direct process provider. Resolved values never persist. +- Required implementation: canonical file-root containment, dedicated process + allowlists, direct argv, cleared environments, process groups, + timeout/output/cancellation bounds, redaction registration, and lifecycle + zeroization. +- Migration impact: existing `{env: NAME}` remains valid. +- Tests: missing/oversized/symlink files, denied commands, timeout, redaction, + and database/trace absence. +- Examples: environment and read-only mounted-file container contracts in the + secret-reference guide and container documentation. +- Live evidence: OpenAI credential remains environment-only for task evidence. +- Documentation: secret reference types and threat model. +- Final disposition: implemented and verified by DSL compatibility and policy + tests; missing, oversized, and symlink-escape file tests; denied, timed-out, + output-limited, and cancelled process tests; provider adapter redaction; raw + SQLite absence checks; and packaged CLI acceptance scenario 32. + +### NET-001: Network destination enforcement + +- Current behavior: exact/wildcard host grants compose with HTTP(S) scheme, + effective-port, resolved-address, private-network, proxy, CA, connect-time, + and response-size policy. Redirects and Unix sockets are disabled. +- User impact: public endpoints can be narrowed to HTTPS/443, while intentional + local and internal peers require explicit private-network authority. +- Security or durability impact: direct clients validate the complete DNS + answer and pin it before dispatch. Proxy routing is disabled by default; + explicit proxy opt-in is documented as a trust delegation. +- Product decision: resolve and validate each destination against scheme, host, + port, IP class, proxy, redirect, and TLS/CA policy at the adapter boundary. +- Required implementation: resolved-IP checks, private-range controls, + rebinding defense, explicit proxy and Unix-socket denial, response limits, + bounded DNS/connect setup, and protected custom-CA references. +- Migration impact: public HTTP(S) scheme defaults remain compatible. Private + destinations now require `allowPrivate: true`; environment proxies require + `allowProxy: true`. +- Tests: core policy and DSL tests cover credentials in URLs, schemes, ports, + empty and mixed DNS answers, loopback/private/public IPv4 and IPv6, explicit + private opt-in, limits, and custom-CA reference policy. Provider and protocol + tests cover pinned synthetic DNS, redirect refusal, CA bundle success and + failure, and policy-composed response limits. +- Examples: constrained MCP and A2A examples explicitly authorize localhost. +- Live evidence: the final public OpenAI matrix remains tracked separately; the + security decisions here are proven without credentialed traffic. +- Documentation: network guide, policy, YAML, provider, security, threat model, + limitations, architecture, and ADR 0019. +- Final disposition: implemented and verified by focused adapter/core tests, + generated schema verification, and packaged CLI acceptance scenario 44, + which denies a private destination before database creation or network I/O. + +### ISO-001: Honest process isolation + +- Current behavior: every shell and process-extension action exposes + plan-visible `process` or `container` isolation. Existing actions default to + bounded host-process mode, explicitly not a sandbox. +- User impact: users can select a portable stronger boundary without confusing + executable policy with isolation. +- Security or durability impact: host mode retains the agentctl identity. + Container mode uses a local digest-pinned image with fixed read-only, + networkless, non-root, capability-dropped, resource-bounded invocation. +- Product decision: require an explicit isolation mode. `process` is the honest + host mode; `container` is the portable strong boundary. Optional platform + backends can be added when detected, but no weak emulation is claimed. +- Required implementation: implemented DSL/plan visibility, fail-closed + engine/image preflight, memory/CPU/PID/output/time limits, forced named + container cleanup, protected engine environment, direct entrypoint, and + explicit unsupported native-backend documentation. +- Migration impact: existing actions default to documented host-process mode. +- Tests: 61 core tests and 8 focused process tests cover defaults, invalid + combinations, plan visibility, engine-safe environment, working directory, + process tree, output/time/cancellation, cleanup construction, and container + resource/security flags. Packaged CLI acceptance scenario 45 proves a + requested missing engine fails before process effect dispatch. +- Examples: `examples/v1/process-isolation.yaml` contains explicit host and + content-addressed container actions. +- Live evidence: the credential-free OCI gate invokes a real action inside the + exact repository image. On 2026-07-27 the action completed through Podman + 5.8.2 on native Linux arm64 after keeping the libkrun starting terminal open. +- Documentation: process-isolation guide, policy, YAML, DSL, security, threat + model, limitations, architecture, container contract, terminology, and ADR + 0020. +- Final disposition: implemented and verified. The real content-addressed + action ran through the production container path with the fixed networkless, + read-only, non-root, capability-dropped, and resource-bounded contract. + Docker-style `sha256:` and Podman 5.8's bare 64-hex `.Id` output are + both validated and normalized before dispatch; malformed IDs fail closed. + +### BUD-001: Enforceable resource and cost budgets + +- Current behavior: the compiled plan carries optional run-wide request, turn, + tool, token, wall-time, process-output, artifact, task, expansion, loop, and + monetary limits. +- Security and durability: SQLite atomically reserves known units before fresh + provider, tool, process, or artifact dispatch. Actual usage is reconciled + afterward. The wall deadline uses the durable run creation timestamp. +- Cost decision: token-only limits require no price. Monetary limits require + authoritative provider cost or explicit versioned integer custom pricing + keyed by `provider/model`; unknown cost is exposed and never fabricated. +- Migration: schema 15 adds run budget and idempotent reservation records. + Budget snapshots are present in checkpoints, audit, and CLI inspection. +- Evidence: compiler graph-count/custom-pricing tests, every dynamic dimension + and exact-bound test, parallel reservation race test, actual-overrun runtime + test, provider/tool/process/artifact pre-dispatch termination tests, wall + cancellation and paused-resume tests, pricing-class reconciliation, + retry/repair/replay accounting, public example, acceptance scenario 46, and + the complete 12-stage deterministic gate. +- Live evidence: `cargo xtask resource-budget-live-openai` passed through the + packaged CLI with one `gpt-5.6` dispatch, 18 input tokens, 5 output tokens, + no tool calls, and a durable denial before attempted request 2. +- Final disposition: implemented and verified. + +### OCI-001: Complete container execution + +- Current behavior: the production image and public mount contract execute + through Docker or Podman with `/config` and `/workspace` read-only, + `/state` and `/artifacts` explicitly writable, and the root filesystem + read-only. +- User impact: durable state, content-addressed artifacts, declared exports, + inspection, repair, and replay work through the documented container path. +- Security or durability impact: the runtime uses UID/GID 65532, a read-only + root, no network for replay, bounded temporary storage, and only the two + declared writable mounts. Build CA extension remains a protected secret + mount and never enters a layer. +- Product decision: keep the artifact store beside the database under + `/state`, authorize declared exports through `/artifacts`, and truthfully + probe Docker/Podman before building or executing. +- Required implementation: complete. Runtime detection, persistent Podman + operation, non-root/read-only runs, mounted roots, ART-001, selective repair, + offline replay, signals, limits, CA extension, SBOM, vulnerability and image + inspection, plus hosted multi-architecture configuration are present. +- Migration impact: the container documentation defines the corrected mount + contract; no state migration is required. +- Tests: deterministic mount/command tests, native Linux arm64 execution, and + hosted Linux x64 execution are labeled separately. +- Examples: the credential-free container workflows cover a strict tool call, + declared artifact, durable inspection, parallel ordered commit, a four-child + matrix, approval, failed-only retry, selective repair after workspace + artifact deletion, CAS verify/export, compensation reconciliation, and + replay. +- Live evidence: `env -u OPENAI_API_KEY cargo xtask acceptance-container` + passed on 2026-07-27 through Podman 5.8.2 and native Linux arm64. It covered + action-level content-addressed container isolation, non-root/read-only + workflow execution, mounted state/artifacts, success and failure exits, + SIGTERM, the durable composite, failed-only retry, repair, CAS reuse, + compensation reconciliation, and network-disabled replay. No provider + request occurred. +- Documentation: runtime troubleshooting, persistent Podman terminal handling, + mount contract, state retention, artifact export, and CA extension. +- Final disposition: implemented and verified. The exact image was Linux + arm64, `nonroot:nonroot`, version `0.2.0`, and source + `opensourceops/agentctl`, with local image digest + `sha256:ddcf174ab2b1ce2481395380d482292a41d79ee5f4620fd52cbd3733e712127c`. + Trivy 0.72.0 with a freshly updated database found zero fixed HIGH/CRITICAL + vulnerabilities. A valid 20,821-byte CycloneDX SBOM is retained at the + ignored local evidence path + `.runtime/scan/agentctl-framework-completeness.cdx.json`; its SHA-256 is + `0ee27f16491108f0f018ac2bc7ad201b3f97bdb539cd6b78584264c9eedd67ff`. + Image configuration and history scans found no credential or authorization + markers. Hosted architecture execution is tracked under XPLAT-001. + +### XPLAT-001: Hosted platform evidence + +- Current behavior: pull requests run exact-head Linux x64, macOS arm64, + Windows x64, container, security, package, and SBOM validation. A separate + manual release-preparation workflow produces the three release packages. +- User impact: platform claims have exact-commit hosted evidence and retained + package/SBOM artifacts rather than configuration-only coverage. +- Security or durability impact: platform-specific path, process, packaging, and + migration bugs may remain. +- Product decision: require complete least-privilege hosted matrices on the + exact pull-request head and retain artifact digests. +- Required implementation: build/test/acceptance/package/examples/completeness + jobs for macOS ARM64, Linux x64, Windows x64, and container/security jobs + with artifacts and digests. Native Linux ARM64 OCI evidence remains + separately labeled. +- Migration impact: none. +- Tests: local workflow lint, action pin scan, matrix completeness check, and + exact-head hosted execution on all three supported targets. +- Examples: all public examples inventoried by jobs. +- Live evidence: provider credentials are neither required nor exposed by + these hosted jobs. Historical OpenAI evidence remains separately labeled. +- Documentation: hosted workflow inventory, exact-head checkout contract, + artifact verification, and release process. +- Final disposition: implemented and verified by the automatic pull-request + gates plus the exact-commit manual release-preparation gate. The independent + candidate report records immutable run IDs and artifact digests. Repository + branch protection remains an owner-controlled governance setting, not a + product implementation limitation. + +## Removed unsupported surface + +### EVENT-001: Event triggers and calendars + +- Current behavior: external schedulers invoke the CLI. +- Product decision: remove event/calendar scheduling from the limitations list. + It is outside the deterministic single-run runtime thesis. +- Required implementation: reject any event-trigger DSL fields and keep cron, + systemd, CI, and Kubernetes invocation guides. +- Compatibility impact: no current supported syntax changes. +- Tests: strict unknown-field rejection. +- Final disposition: `removed from supported surface`. + +### DIST-001: Distributed execution and storage + +- Current behavior: one local process and SQLite are the correctness boundary. +- Product decision: distributed scheduling, leases, multi-host execution, and + distributed storage are explicit non-goals, not incomplete core behavior. +- Required implementation: remove roadmap ambiguity and make local ownership + explicit. +- Compatibility impact: none. +- Tests: documentation/product-boundary verification. +- Final disposition: `removed from supported surface`. + +### REG-001: Hosted public registry + +- Current behavior: no hosted pack service. +- Product decision: a public registry is unnecessary. PACK-001 supports local, + Git, and immutable archive sources without a hosted control plane. +- Required implementation: remove public-registry roadmap claims. +- Compatibility impact: none. +- Tests: source resolver coverage. +- Final disposition: `removed from supported surface`. + +### UI-001: Hosted UI, chat, and visual orchestration + +- Current behavior: the CLI and embeddable Rust runtime are authoritative. +- Product decision: hosted SaaS, IDE, visual editor, chat application, and + free-form conversation orchestration are explicit non-goals. +- Required implementation: reject hidden model-owned control flow and document + TEAM-001 as compiled workflow syntax. +- Compatibility impact: none. +- Tests: compiler rejects unsupported control-flow fields. +- Final disposition: `removed from supported surface`. + +## Baseline evidence + +Recorded on 2026-07-23 before framework-completeness implementation: + +- `cargo xtask verify`: passed all 12 stages. +- `cargo xtask acceptance`: passed 28 scenarios. +- `cargo xtask examples-verify`: passed. +- `cargo xtask docs-verify`: passed. +- `cargo xtask package`: passed. +- `cargo xtask secret-scan`: passed. +- `env -u OPENAI_API_KEY cargo xtask acceptance-container`: the Podman VM + required a persistent terminal to keep forwarding alive; after reaching the + OCI binary, acceptance failed with exit 3 because + `/artifacts/report.txt` escaped the authorized workspace root. No credential + was supplied and no OpenAI call occurred. +> Canonical source: [`docs/execution/LIMITATION_BURNDOWN.md`](https://github.com/opensourceops/agentctl/blob/main/docs/execution/LIMITATION_BURNDOWN.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/limitations.md b/src/content/docs/_generated/reference/limitations.md index 6eb1754..ed45b74 100644 --- a/src/content/docs/_generated/reference/limitations.md +++ b/src/content/docs/_generated/reference/limitations.md @@ -1,54 +1,147 @@ --- title: "Limitations" -description: "Current release boundary, deferred work, and non-goals." +description: "Current supported boundary, operational limits, and non-goals." editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/LIMITATIONS.md" --- -This classification is part of the product contract. A deferred feature is not a current capability, but its absence is not automatically a release blocker for the local, externally scheduled, and generic OCI-step journeys. +This classification is part of the product contract. Core runtime limitations +are closed in the +[framework limitation burn-down](/agentctl/reference/limitation-burndown/). +Capabilities outside the product thesis are explicit non-goals, and +environment-specific evidence is labeled separately from implementation. ## Release blockers -No known P0/P1 implementation defect remains for the stated local, scheduled, and OCI journeys. The local container build now has a secure optional CA secret path, and the current image passed OCI acceptance, Trivy 0.72.0, and CycloneDX validation. The remaining RC gate is external evidence: the new Linux x64, macOS arm64, Windows x64, container, security, package, and SBOM workflows are configured and locally linted but have not been pushed or dispatched. The recommendation is **Ready for hosted RC validation**, not an already validated RC or stable v1.0. +No known P0/P1 implementation defect remains for the stated local, scheduled, +and OCI journeys. The local container build has a secure optional CA secret +path, and exact-head pull-request gates execute Linux x64, hosted macOS arm64, +Windows x64, container, security, package, and SBOM validation without +provider credentials. Exact run and artifact digests belong to the independent +candidate report. This is a `v1alpha1` framework candidate, not stable v1.0. ## Required hardening completed for this release -- Provider-specific options are allowlisted, type-checked, included in plan capability negotiation, and either mapped or rejected. Streaming and programmatic tool calling are rejected rather than ignored. +- Provider-specific options are allowlisted, type-checked, included in plan capability negotiation, and either mapped or rejected. Streaming is explicit and capability-checked; programmatic tool calling is rejected rather than ignored. - Tool input/output schemas are strict; built-in tool kinds have compiler-checked capability/effect/idempotency contracts. - Provider calls, function-call IDs/results, continuations, effects, checkpoints, audit events, and redacted trace events are durable and publicly inspectable. - Timeout/transport ambiguity is not automatically retried; confirmed effects survive resume; call IDs are scoped by run; missing credentials fail before run/database creation. - Non-interactive approvals durably pause, signals cancel safely, JSON errors include available run/trace correlation, and SQLite uses WAL plus a bounded lock wait. - The packaged CLI, clean-directory quickstart, cron-like empty environment, and non-root/read-only OCI contract have executable acceptance coverage. +- Successful bounded file outputs are atomically ingested into a local immutable content-addressed store with durable references, verification/export commands, lease-safe reachability GC, interrupted-GC recovery, and local/OCI acceptance coverage. +- Identified confidential JSON and text fields can be transactionally migrated to versioned AES-256-GCM envelopes, rotated through environment key references, inventoried without content disclosure, and fail closed on missing/wrong keys, tampering, plaintext writes, or stale-key writes. - Shell execution and acceptance/container helpers use bounded concurrent capture. Output overflow terminates/reaps the child with a structured secret-safe error; timeouts and cancellation retain durable uncertain-effect semantics. +- Process actions expose plan-visible `process` or `container` isolation. + Host mode is explicitly not a sandbox. Container mode requires a local + digest-pinned Docker/Podman image and runs networkless, read-only, non-root, + capability-dropped, and memory/CPU/PID/output/time bounded without host + fallback. +- Optional run-wide budgets enforce provider requests, turns, tool calls, + input/output/total tokens, durable wall time, captured process output, + ingested artifact bytes, compiled task/expansion/loop counts, and cost when + explicit versioned pricing is configured. - Hosted workflows use least privilege, full-SHA action pins with version comments, complete-history/tree Gitleaks, deterministic fake-secret detection, dependency/image scans, and required production/image CycloneDX artifacts with digests. -## Post-v1 features +## Optional integration boundaries -These are useful extensions but are not required by the product thesis. They need new deterministic state and compatibility contracts before implementation: +These are extension points, not incomplete core runtime behavior: -- parallel task execution; `foreach` and matrix expansion; loops; routers; sub-workflows; compensation execution; -- structured agent teams and handoffs; -- model token streaming into CLI/workflow state; -- opt-in MCP reconnection and A2A resubmission with explicit remote reconciliation; -- pack dependency resolution, pack lockfiles, remote fetching, publisher signatures, and a versioned plugin ABI; -- vector memory; -- encrypted application-level persistence and external secret-manager adapters; -- reliable monetary cost enforcement when providers expose sufficient authoritative metadata. +- external secret-manager adapters beyond environment, mounted-file, and policy-gated process references; +- provider-maintained pricing discovery. Monetary limits require authoritative + response cost or operator-supplied versioned custom pricing. ## Explicit non-goals - Event triggers and calendars: external schedulers trigger `agentctl`. - MongoDB migration, distributed scheduling, multi-host execution, and distributed storage: the correctness boundary is one local process and SQLite database. -- An in-process OS sandbox or stronger network isolation: allowlists are defense in depth, while containers/VMs, identities, egress policy, and platform sandboxes own isolation. +- Native Linux namespace/bubblewrap, macOS sandbox-profile, and Windows + restricted-token/job-object isolation backends. Explicit action container + mode and externally managed containers/VMs provide the supported isolation + boundaries. - Free-form multi-agent conversation control flow: the compiled workflow remains authoritative. ## Current operational limits - The document API is `v1alpha1`; pin the binary/image version and validate before upgrading. -- Scheduling is sequential (`maxConcurrency: 1`). Separate runs may overlap safely in SQLite, but they can still target the same external resource. Use the external scheduler's overlap controls (`flock`, systemd unit serialization, or Kubernetes `concurrencyPolicy: Forbid`) when effects must not overlap. +- Parallel scheduling is local to one run and process, bounded at 64 tasks, and defaults to sequential execution. Working-memory conflicts fail compilation, but tasks that target the same external resource still require explicit `needs` ordering or that system's concurrency controls. Separate runs also require external overlap controls when effects must not overlap. +- Run budgets are optional. Provider input tokens and future token classes are + estimated conservatively before dispatch; actual provider usage is + reconciled after the response. Custom pricing is operator-maintained and is + not automatically refreshed from public price pages. +- Foreach and matrix expansion accepts only static workflow values, requires + `maxItems`, and is capped at 256 children. Runtime or model-controlled graph + growth is not supported. +- Conditions support typed paths, equality, inequality, numeric ordering, and + `not`; routers support exact typed selectors and enumerated destinations. + Arbitrary expressions, implicit dependencies, and model-owned hidden routing + are rejected. +- Loops are sequential, require a maximum from 1 through 64, and compile all + iteration boundaries before execution. Runtime or model-controlled graph + growth and unbounded loops are rejected. +- Sub-workflows are compile-time namespaced graphs with semantic versions and + typed input/output boundaries. Definitions inherit the caller's policy and + providers and cannot request independent authority. +- Compensation is explicit best-effort inverse execution. It runs as a + source-linked sequential workflow, skips effects already reconciled as + compensated, and never claims transactional rollback or exactly-once + external mutation. +- Structured collaboration is an explicit graph of bounded role tasks and + typed handoff tasks. A hidden `team:` conversation scheduler is rejected. + Role tool visibility is fixed by each agent definition; workflow policy + remains authoritative for every role. +- Streaming is available for fake, OpenAI, and Azure OpenAI agents only. + Progress records are capped at 256 events per task attempt and 4 KiB per + payload. The OpenAI SSE transport is capped at 8 MiB. Transport loss is not + automatically reconnected or resubmitted, and final task output still + requires a terminal validated provider response. +- MCP reconnects at most once only for `pure`, `idempotent`, or `keyed` + actions and only while the selected tool schema remains identical. Calls + with `unknown` or `at_most_once` idempotency remain uncertain after a lost + response and require reconciliation. +- A2A continuation requires a persisted remote task ID. An ambiguous + `SendMessage` without a returned task ID is never resubmitted automatically. + `effects continue-remote` can resume polling or streaming of a known task, + retrieve bounded same-origin artifacts, and make the recovered boundary + reusable by retry. +- Pack resolution has no hosted registry or version discovery. Every root and + dependency names one local, pinned Git, or immutable archive source. The + checked-in lock is per workflow directory. Sigstore verification uses the + trust root embedded in the installed agentctl version; rotate agentctl when + public-good trust material changes. +- `extension.process` is a reviewed process contract, not a native ABI or OS + sandbox. Handshake is a non-mutating protocol promise; invocation failures + after dispatch remain uncertain. Set `isolation: container` or use a stronger + externally managed platform boundary for hostile executables. +- SQLite memory search scans at most 10,000 active entries and returns at most + 100 results. Its `local_hash` vectors are deterministic lexical features, not + neural embeddings. Use the optional OpenAI embedding adapter or implement the + public embedding and memory adapter traits when semantic quality or a + specialized external index is required. Promotion into run working memory is + always explicit. - SQLite is local durable state, not a secret vault or distributed lease service. Persist `/state` across container invocations and back it up according to the workflow's recovery needs. -- Filesystem/process/network allowlists are not an OS sandbox. Run untrusted workflows in a restricted container/VM with least-privilege credentials and egress. +- State encryption is explicit and selected-field only. Before it is enabled, the database is plaintext. It does not encrypt artifact bytes or operational metadata, and it cannot retroactively protect old backups or snapshots. Preserve the current referenced key with encrypted backups. +- Network preflight validates the HTTP(S) scheme, host, effective port, and + every resolved IPv4/IPv6 address before run creation, then pins accepted + direct DNS answers. Private addresses and environment proxies are denied by + default; redirects and Unix sockets are disabled. Explicit `allowProxy` + delegates routing and destination resolution to that trusted proxy, so use + external egress isolation for hostile workflows. +- Filesystem/process/network allowlists and `isolation: process` are not an OS + sandbox. Individual `isolation: container` actions are networkless and mount + only the authorized working directory read-only, but still trust the engine, + image, and explicitly passed secrets. Run untrusted whole workflows in a + dedicated container/VM identity with external resource and egress controls. - At-most-once model/remote calls can become uncertain in the dispatch/acknowledgement window. Inspect and reconcile externally; use `fork` only when fresh effects are knowingly acceptable. -- Tool-using OpenAI/Azure agents require stored-response continuation. `store: false` is rejected until stateless response-item replay is implemented. -- Anthropic, Google, Azure OpenAI, MCP, and A2A are native and mock-tested in this release, not live-tested. Only the OpenAI GPT-5.6 tool path has live end-to-end evidence. -- The current local OCI runtime, vulnerability-scan, and SBOM evidence is Linux arm64. Linux x64 is configured in the unpushed Ubuntu workflow but has not executed. +- Successful tasks from databases created before schema 5 require explicit `runs analyze`/`runs upgrade`. Only provable metadata is imported; unprovable boundaries are returned as conservative safe repair roots. +- Automatic artifact ingestion covers regular files up to 16 MiB reported by successful built-in workspace-mutation results. Larger outputs and artifacts produced only by opaque external effects require an explicit bounded import/export integration. The local CAS must be backed up with SQLite; missing or corrupt blob bytes block repair before run creation and report the expected artifact identity. +- An applied non-idempotent mutation in a repair closure remains blocked from duplicate execution unless a confirmed compensation is linked. Reconciliation supports immutable `applied`, `not_applied`, and `compensated` records, validated results, policy authorization, and operation-specific verification hooks; it does not provide exactly-once delivery. +- Terminal retry requires an identical workflow digest and a terminal source. It creates a new source-linked run, reuses only proven compatible successful boundaries, and freshly executes the selected closure. Use repair for a changed definition, resume for a non-terminal run, replay for effect-free reconstruction, and fork for knowingly broad fresh execution. +- Anthropic, Google, Azure OpenAI, MCP, and A2A are native and mock-tested in + this release, not live-tested. OpenAI GPT-5.6 has bounded live evidence for + basic and tool agents, parallel branches, matrix tasks, structured routing, + loops, sub-workflows, typed handoffs, retry, selective repair, artifact CAS + reuse, keyless replay, streaming, resource-budget termination, and native + Linux arm64 container execution. +- Local OCI runtime evidence is Linux arm64. The hosted container runtime, + vulnerability scan, and image SBOM run on Linux x64 and are labeled + separately from that local evidence. - GitHub runner availability, organization action policy, branch protection, and required-check configuration are repository-owner operations and cannot be proven by repository-local lint. -> Canonical source: [`docs/LIMITATIONS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/LIMITATIONS.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/LIMITATIONS.md`](https://github.com/opensourceops/agentctl/blob/main/docs/LIMITATIONS.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/live-framework-verification.md b/src/content/docs/_generated/reference/live-framework-verification.md new file mode 100644 index 0000000..6ab1483 --- /dev/null +++ b/src/content/docs/_generated/reference/live-framework-verification.md @@ -0,0 +1,103 @@ +--- +title: "Live framework verification" +description: "Sanitized GPT-5.6 scenario, recovery, replay, usage, and container evidence." +editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/execution/LIVE_FRAMEWORK_VERIFICATION.md" +--- +Date: 2026-07-27, Asia/Kolkata. + +Status: passed. + +The packaged macOS arm64 CLI and the production Linux arm64 OCI image executed +the bounded public OpenAI matrix with model `gpt-5.6`. Every run used a clean +temporary database and workspace. Raw provider responses and databases remain +only in ignored temporary or evidence paths. No credential value or resolved +secret was written to committed content. + +## Retained successful matrix + +| Scenario | Requests | Tool calls | Run | Result | +| --- | ---: | ---: | --- | --- | +| Stateless tool workflow | 2 | 1 | `run-019fa39d-de49-7410-b973-d50fed711010` | exact verdict and artifact | +| Basic agent | 1 | 0 | `run-019fa39d-e8ca-7f73-b218-f105e4c16b92` | succeeded | +| Environment secret reference | 1 | 0 | `run-019fa39d-eeb6-79a1-9f65-879196c4193d` | succeeded without persisted secret | +| Provider portability | 1 | 0 | `run-019fa39d-f6b2-7a21-946a-81d4b6d5269f` | succeeded | +| Framework live composite | 11 | 0 | `run-019fa39d-feea-7ad2-9ff7-38e7bc005655` | all bounded constructs succeeded | +| Deliberate agent failure source | 3 | 2 | `run-019fa39e-3567-7bb3-a47f-496162a23d12` | failed at the designed task boundary | +| Terminal retry of that failure | 1 | 1 | `retry-019fa39e-4ce3-7773-a3d0-dcd18d46b85b` | upstream agent reused; failed task reattempted once | +| Selective repair | 2 | 1 | `repair-019fa39e-55f9-7142-b6ae-06f21a1ead8e` | upstream reused; artifact CAS reference retained | +| Linux arm64 OCI failure source | 3 | 2 | `run-019fa3a6-2fc6-7733-b201-eb806fd70425` | expected failure retained in mounted state | +| Linux arm64 OCI selective repair | 2 | 1 | `repair-019fa3a6-5b2e-7851-9a44-e3ea3e019ce0` | upstream reused and artifact exported | + +The retained matrix used 27 Responses API requests, 8 tool calls, 3,939 input +tokens, 560 output tokens, 20 reasoning tokens, and no reported cache tokens. +The provider did not return billing metadata, so no billed amount is +fabricated. The gate's deliberately conservative token calculation is below +USD 0.07 for this retained matrix and its hard ceiling is USD 10. + +## Composite feature proof + +The public +[`live-composite.yaml`](https://github.com/opensourceops/agentctl/blob/main/examples/framework-completeness/live-composite.yaml) +compiled to 21 tasks and made 11 bounded provider requests: + +- two independent agent branches executed under `maxConcurrency: 4`; +- a two-child agent matrix retained stable child IDs and ordered aggregation; +- a structured agent result selected `execute`, while the default route was + durably skipped; +- two agent loop iterations committed and the third bounded child was skipped; +- one agent ran inside a versioned typed sub-workflow; +- collector and reviewer roles exchanged one typed durable handoff; +- one OpenAI streaming task persisted stream events and produced the exact + final marker; +- final deterministic verification succeeded. + +Replay `replay-019fa39e-34a3-71a1-a1d2-e7fcefbb66d4` +reproduced the composite output without the credential and recorded zero fresh +effects, tool calls, or provider sessions. + +## Recovery, CAS, and container proof + +The selective-repair source deliberately gives `publish` only one turn. It +therefore persists its tool call and fails before a final structured response. +The identical-workflow terminal retry reused `analyze`, made exactly one fresh +model attempt for `publish`, and failed again as designed. The repaired +workflow raised the bounded turn allowance. Repair then reused `analyze`, +executed only the repair closure, wrote the expected artifact, and succeeded. + +Replay `replay-019fa39e-6273-7212-a60e-5519e2d88a25` +reproduced the repaired local result with zero fresh effects. The production +image repeated the source and repair path as UID/GID 65532 with read-only +configuration and workspace mounts plus writable state and artifact mounts. +Container replay +`replay-019fa3a6-7187-7481-bb8f-abed11943457` +ran with no credential and `--network none`, producing zero fresh effects, +tool calls, or provider sessions. + +## Resource-budget proof + +Run `run-019fa2f4-4252-7aa3-8aa8-72c31cb5dfcf` allowed exactly one +provider request. The first task succeeded with 18 input and 5 output tokens. +The second reservation was denied before dispatch, and inspection recorded +`providerRequests` with limit 1 and attempted value 2. + +## Request accounting + +The successful retained framework matrix used 27 requests. Two fail-closed +gate attempts were also made while implementing the evidence assertions: + +- the first stopped after 20 requests because it counted the model and tool + effects together for the terminal retry; +- the second completed all 22 local requests, then exposed that the live OCI + block copied the credential-free repair fixture instead of the public OpenAI + workflow; +- the focused OCI continuation used the remaining 5 requests and passed. + +Including the separate one-request resource-budget proof, this limitation +burn-down used 48 live requests, below the authorized maximum of 80. The first +failed attempt's temporary database was deleted by the fail-closed harness, so +its token counts are not reconstructed. No blind retry loop or live fuzzing +was used. + +Sanitized machine-readable evidence is retained at the ignored path +`.release-evidence/selective-repair/live-summary.json`. +> Canonical source: [`docs/execution/LIVE_FRAMEWORK_VERIFICATION.md`](https://github.com/opensourceops/agentctl/blob/main/docs/execution/LIVE_FRAMEWORK_VERIFICATION.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/migration.md b/src/content/docs/_generated/reference/migration.md index 6915355..d8b7ce0 100644 --- a/src/content/docs/_generated/reference/migration.md +++ b/src/content/docs/_generated/reference/migration.md @@ -16,4 +16,4 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/MIGRATING_FRO The automatic translator covers simple top-level metadata, modules/actions, tasks, heuristic agents, common approval mode, and initial working memory. It discards unsupported legacy provider endpoint/cache/profile fields with a migration warning rather than preserving unsafe or obsolete semantics. Pack-backed actions, remote transports, MongoDB/vector memory, arbitrary profiles, and custom TypeScript executors must be rewritten against the Rust contracts. Use `fixtures/compat/v0/assign.playbook.yaml` as the minimum preserved contract and compare changes against [Compatibility](/agentctl/reference/compatibility/). The old source is non-production reference material; do not add new behavior to it. -> Canonical source: [`docs/MIGRATING_FROM_TYPESCRIPT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/MIGRATING_FROM_TYPESCRIPT.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/MIGRATING_FROM_TYPESCRIPT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/MIGRATING_FROM_TYPESCRIPT.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/output.md b/src/content/docs/_generated/reference/output.md index 2dccc2e..08b57b9 100644 --- a/src/content/docs/_generated/reference/output.md +++ b/src/content/docs/_generated/reference/output.md @@ -15,7 +15,16 @@ agentctl run workflow.yaml --output json --color never The envelope version is `agentctl.dev/cli/v1` and includes `kind`, `ok`, `data`, and `diagnostics`. A successful run includes run ID, trace ID, terminal state, and declared output. A failure writes a versioned error envelope to stderr, with run and trace correlation when a run exists. -JSONL progress output is not implemented in this release. Event-level information remains available in durable audit and trace records. +JSONL mode emits one versioned envelope per durable provider stream event, +followed by one final outcome envelope: + +```text +agentctl run workflow.yaml --output jsonl --color never +``` + +Human mode writes provider progress to stderr. JSON mode never renders progress +and remains exactly one final document. All modes persist the same bounded +records for `agentctl inspect`. ## Exit codes @@ -23,7 +32,7 @@ JSONL progress output is not implemented in this release. Event-level informatio | --- | --- | --- | | `0` | success | Collect outputs and artifacts. | | `2` | usage or validation | Correct arguments, YAML, references, templates, or capabilities. | -| `3` | policy or approval | Inspect denial or retain state for operator approval. | +| `3` | policy, approval, or blocked repair plan | Inspect denial/compatibility evidence or retain state for operator approval. | | `4` | run failure | Inspect the failed task and effect history. | | `5` | persistence | Check database compatibility, permissions, corruption, and locking. | | `6` | provider or protocol | Diagnose authentication, network, native API, MCP, or A2A evidence. | @@ -31,6 +40,8 @@ JSONL progress output is not implemented in this release. Event-level informatio Do not automatically retry every nonzero code. A provider, protocol, process, or tool operation may be uncertain after dispatch. +`repair --plan` returns kind `RepairPlan`. A compatible plan exits `0`; a blocked plan exits `3` while remaining a successful, parseable machine envelope with `compatible: false` and `blockedReuse` explanations. Repair execution returns kind `RepairOutcome` with new/source run IDs, trace ID, state, reused tasks, executed tasks, and output. `inspect` exposes the complete run and task lineage. + ## Example ```text @@ -39,4 +50,4 @@ agentctl run examples/v1/hello.yaml --db /tmp/hello.db --output json --color nev ``` These commands need no credential. `check` writes no runtime database; `run` writes `/tmp/hello.db`. -> Canonical source: [`docs/reference/CLI_OUTPUT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/CLI_OUTPUT.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/reference/CLI_OUTPUT.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/CLI_OUTPUT.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/terminology.md b/src/content/docs/_generated/reference/terminology.md index 1467b6d..d154781 100644 --- a/src/content/docs/_generated/reference/terminology.md +++ b/src/content/docs/_generated/reference/terminology.md @@ -10,22 +10,30 @@ Use these terms consistently in workflows, documentation, issues, and reviews. | Workflow | One versioned declarative YAML document and its compiled graph. | | Task | One ordered graph node that invokes an action or agent. | | Action | A typed runtime operation selected directly by a task. | +| Process mode | Bounded direct execution with the agentctl host identity. It is not a sandbox. | +| Container mode | Explicit process-action isolation in a local digest-pinned Docker/Podman image with the fixed agentctl container contract. | +| Isolation | An operating-system or container authority boundary. Policy and allowlists alone are not isolation. | | Agent | A bounded provider-backed executor for one task. | +| Role | A named agent task with explicit provider, tool visibility, limits, and output contract. | +| Handoff | A typed durable task output consumed by an explicitly dependent role task. | | Tool | A strict capability contract that an agent may request. | | Provider | A native model API adapter behind provider-neutral contracts. | +| Stream event | One bounded, redacted provider progress record ordered within a task attempt. | | Effect | A durably identified operation that observes or changes state outside pure computation. | -| Run | One durable execution, check, replay, or fork record. | +| Run | One durable execution, check, replay, repair, or fork record. | | Attempt | One bounded execution attempt for a task. | | Resume | Continue the same non-terminal run using durable progress. | | Recorded replay | Create a new record from terminal stored results without calling executors. | | Retry | Start another bounded attempt for a task after a definitive retry-safe failure. | +| Repair | Create a linked run from a terminal source, reuse compatible successful tasks outside selected boundaries, and execute the roots and descendants from a target workflow. | | Fork | Create a child run that intentionally permits fresh effects. | -| Rerun | Informal term. Prefer fork when referring to the supported fresh-run operation. | +| Rerun | Informal term. Prefer repair for boundary selection or fork for a broader fresh execution. | +| Disposition | Whether a successful task was freshly `executed`, source-linked `reused`, or copied as `recorded` replay evidence. | | Approval | A durable operator decision required before an effect may continue. | | Checkpoint | A versioned, checksummed snapshot used for recovery. | | Working memory | One run-local JSON object changed by explicit memory actions. | | Long-term memory | Namespaced SQLite values shared across runs and managed by retention. | | Pack | A local versioned manifest and reviewed reusable content with integrity checking. | -Do not use resume, replay, retry, and fork interchangeably. None of them means exactly-once execution. -> Canonical source: [`docs/reference/TERMINOLOGY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/TERMINOLOGY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Do not use resume, replay, retry, repair, and fork interchangeably. None of them means exactly-once execution. +> Canonical source: [`docs/reference/TERMINOLOGY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/TERMINOLOGY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/reference/yaml.md b/src/content/docs/_generated/reference/yaml.md index 450aa0b..758b97a 100644 --- a/src/content/docs/_generated/reference/yaml.md +++ b/src/content/docs/_generated/reference/yaml.md @@ -28,37 +28,101 @@ Unknown fields fail. Documents, ordinary input files, packs, direct reads, exist | `agents` | `{}` | Named bounded model executors. | | `actions` | `{}` | Named deterministic or protocol actions. | | `tools` | `{}` | Strict model-callable tool contracts. | +| `subworkflows` | `{}` | Semantically versioned reusable task graphs with typed input and output boundaries. | +| `compensation` | manual, policy approval | Best-effort compensation trigger and approval behavior. | | `tasks` | required list | Ordered graph nodes. | | `policy` | safe defaults | Filesystem, process, network, provider, tool, and approval rules. | -| `memory` | empty | Initial working memory and optional SQLite long-term namespace. | +| `memory` | empty | Initial working memory and optional typed long-term store, namespace, retention, and embedding configuration. | | `mcpServers` | `{}` | Pinned MCP Streamable HTTP peers. | | `a2aPeers` | `{}` | Pinned A2A Agent Card peers. | -| `packs` | `[]` | Local reviewed pack references. | -| `runtime` | sequential defaults | Runtime controls. `maxConcurrency` must be `1`. | +| `packs` | `[]` | Semver-constrained local, pinned Git, or immutable archive pack roots. | +| `packTrust` | unsigned warning, process denied | Unsigned policy, Sigstore identity/issuer allowlist, and explicit unsigned-process acknowledgement. | +| `runtime` | bounded defaults | Runtime controls. `maxConcurrency` defaults to `1` and accepts `1` through `64`. | | `output` | defaults | Output presentation contract. | +## Network policy + +`policy.networkAllowlist` contains exact hosts or `*.suffix` subdomain rules. +The wildcard never matches the suffix apex. Every network action also uses the +following `policy.network` fields: + +| Field | Default | Validation and behavior | +| --- | --- | --- | +| `allowedSchemes` | `[https, http]` | Nonempty subset of `https` and `http`. | +| `allowedPorts` | `[]` | Empty permits the scheme's known or explicit port; otherwise the effective port must appear here. Port `0` is invalid. | +| `allowPrivate` | `false` | When false, private, loopback, link-local, shared, documentation, benchmark, unspecified, multicast, and reserved IPv4/IPv6 answers fail. | +| `allowProxy` | `false` | When false, environment proxy discovery is disabled. Enabling it explicitly trusts that proxy's routing and resolution. | +| `customCa` | none | Environment, mounted-file, or policy-gated process secret reference containing only PEM certificates. Environment references must appear in `environmentAllowlist`. | +| `connectTimeoutSeconds` | `10` | Bounds DNS resolution and TCP connection setup; valid range is 1 through 120. | +| `maxResponseBytes` | `8388608` | Upper network response bound; valid range is 1 through 67108864 and composes with lower adapter limits. | + +Required provider, MCP, and A2A URLs are checked before a run record is +created. Agentctl resolves the destination, rejects the complete answer if any +address is forbidden, and pins all accepted addresses into the direct client. +Redirects and Unix-socket transports are disabled. See [Network +policy](https://github.com/opensourceops/agentctl/blob/main/docs/guides/NETWORK_POLICY.md). + ## Tasks -Each task requires `id` and `uses`. `uses` is `action:name` or `agent:name`. +Each task requires `id` and `uses`. `uses` is `action:name`, `agent:name`, +`workflow:name`, or `router`. | Field | Default | Validation | | --- | --- | --- | | `needs` | `[]` | Every ID must exist; cycles fail. | +| `foreach` | none | Static typed `items`, binding `as`, and `maxItems`. Mutually exclusive with `matrix`; maximum 256 children. | +| `matrix` | none | Static `axes` Cartesian product and `maxItems`. Axis names are template-safe identifiers; maximum 256 children. | +| `route` | required for `uses: router` | Exact typed `select`, unique typed cases, enumerated destinations, and optional default destinations. Every destination must depend on the router. | +| `loop` | none | Required `maxIterations` from 1 through 64, exact typed `while`, and optional typed `initial` value. Mutually exclusive with `when`, `foreach`, `matrix`, and `route`. | +| `memoryWrites` | inferred or `[]` | Working-memory keys. Literal memory-write keys are inferred; templated keys require an explicit set. Unordered overlaps fail when concurrency is greater than one. | | `when` | true | Constrained boolean/equality expression. | | `vars` | `{}` | Task-local JSON values. | | `with` | `{}` | Typed action or agent input. | +| `outputSchema` | action-owned object or agent structured contract | Valid JSON Schema checked at task completion and selective-repair reuse. | | `retry` | bounded default | Only definitive retry-safe failures may repeat. | | `timeoutSeconds` | action or agent default | Must be within the implementation bound. | +| `compensate` | none | Named effectful action, typed `with`, bounded retry, and timeout. Valid only on a potentially mutating task. | | failure behavior | fail | Unsupported dynamic control flow is rejected. | -Ready tasks run in YAML declaration order. There is no `foreach`, matrix, loop, router, sub-workflow, handler, or parallel group in this version. +`extension.process` actions require +`protocolVersion: agentctl.dev/process-extension/v1`, explicit idempotency, +input and output JSON Schemas, a declared capability list, direct command/args, +and bounded process limits. See [Extensions](https://github.com/opensourceops/agentctl/blob/main/docs/EXTENSIONS.md). + +Ready tasks are selected in YAML declaration order up to `maxConcurrency`. +They read isolated durable snapshots and commit in compiled order. There is no +runtime or model-controlled expansion. Static `foreach` and `matrix` tasks +compile to inspectable child tasks and a parent aggregate. Bounded loops +compile to a sequential child chain and parent aggregate. Sub-workflows compile +to namespaced ordinary tasks with typed input and output boundaries. There is +no handler or separate parallel group in this version. Compensation is planned +after a terminal run and executes declared inverse actions in reverse graph +order through an ordinary source-linked durable run. ## Agents An agent requires `provider` and `model`. Defaults are `maxTurns: 8`, `maxToolCalls: 16`, `maxOutputTokens: 2048`, and `timeoutSeconds: 120`. Set tighter values for known work. Optional fields include instructions or `instructionsFile`, variables, tools, retry, reasoning, structured output, usage limits, and provider-specific options. +`structuredOutput` asks the provider for typed JSON and becomes the default task output contract. A task-level `outputSchema` can define the complete task contract explicitly. An agent result that feeds downstream tasks must have one of these contracts before it can be reused by selective repair. Schema documents are compiled when the workflow is checked; values are validated both when completed and when reused. + Capability negotiation happens during compilation. A provider must explicitly support every requested feature. +## Runtime budgets + +`runtime.maxConcurrency` defaults to `1`, and +`runtime.defaultTimeoutSeconds` defaults to `120`. Optional +`runtime.budgets` fields are `maxProviderRequests`, `maxTurns`, +`maxToolCalls`, `maxInputTokens`, `maxOutputTokens`, `maxTotalTokens`, +`maxWallTimeSeconds`, `maxProcessOutputBytes`, `maxArtifactBytes`, +`maxTasks`, `maxExpansionItems`, `maxLoopIterations`, and +`maxCostMicrousd`. Values must be greater than zero. + +`maxCostMicrousd` requires `runtime.pricing.version` and a +`runtime.pricing.models` entry for every cost-limited `provider/model`. +Input and output rates are integer micro-US-dollars per million tokens. +Optional reasoning and cache rates fall back to output and input rates. See +[Resource and cost budgets](https://github.com/opensourceops/agentctl/blob/main/docs/guides/RESOURCE_BUDGETS.md). + ## Actions Supported action kinds: @@ -71,12 +135,55 @@ Supported action kinds: - `builtin.memory.read` - `builtin.memory.write` - `builtin.long_term_memory.read` +- `builtin.long_term_memory.search` - `builtin.long_term_memory.write` +- `builtin.long_term_memory.promote` - `mcp.call` - `a2a.delegate` `builtin.shell.exec` uses a direct executable and argument list. Output defaults are 1 MiB per stream and 2 MiB combined, with a maximum configured value of 16 MiB. Its maximum timeout is 86,400 seconds. +Both process action kinds accept `isolation`. `process` is the default and +means bounded host execution, not sandboxing. `container` requires a +`container` block: + +| Field | Default | Validation and behavior | +| --- | --- | --- | +| `image` | required | Local content address in `NAME@sha256:DIGEST` or `sha256:IMAGE_ID` form. Pulls are disabled. | +| `runtime` | `auto` | `auto`, `docker`, or `podman`. Explicit selection never falls back. | +| `memoryLimitBytes` | `268435456` | 16 MiB through 16 GiB. | +| `cpuLimitMillis` | `1000` | 1 through 64,000; 1,000 is one CPU. | +| `pidsLimit` | `64` | 1 through 4,096. | + +Container mode fixes a read-only root and workspace mount, non-root user, +network none, dropped capabilities, `no-new-privileges`, bounded `/tmp`, and +direct entrypoint/arguments. The compiled plan exposes process requirements. +See [Process isolation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/PROCESS_ISOLATION.md). + +`mcp.call` accepts an optional `idempotency` declaration. Only `pure`, +`idempotent`, or `keyed` permits the bounded reconnect path, and a refreshed +tool schema must match exactly. Omitted idempotency is `unknown`. + +An A2A peer accepts `timeoutSeconds`, `maxPolls` from 1 through 1,000, and +`pollIntervalMs` from 1 through 60,000. Defaults are 120 seconds, 100 polls, +and 100 milliseconds. These bounds apply to observation of a known task; +`SendMessage` remains at most once. + +## Long-term memory + +`memory.longTerm` defaults to the built-in `sqlite` provider and `default` +namespace. `retentionDays`, when set, is 1 through 36,500. Its `embedding` +block defaults to `local_hash` with 64 dimensions and accepts 8 through 4096 +dimensions. Any non-local embedding provider must name a compatible entry in +`spec.providers`. OpenAI embeddings also require `embedding.model`. + +Memory writes accept a versioned `entry`, a typed `content` block, or a legacy +`value` plus optional searchable `text` and metadata. Search accepts exact +metadata filters and `text`, `vector`, or `hybrid` mode, with a result limit +from 1 through 100. Promotion is a separate internal-state action and requires +its working-memory key in `memoryWrites` when the key is templated. See +[State and memory](/agentctl/concepts/memory/). + ## Tools A tool requires `kind`, description, strict input and output JSON Schema, capability, risk, effect class, idempotency, retry safety, timeout, and approval behavior. Built-in tool executors are workspace read, workspace write, and echo. Declared semantics must match the built-in kind. @@ -92,11 +199,16 @@ ${{ memory.path }} ${{ tasks.task-id.output.path }} ``` -An exact template preserves objects, arrays, booleans, numbers, strings, and null. Text interpolation accepts scalars. Conditions add `not` and equality against a JSON literal or string. There is no code execution, arithmetic, arbitrary function, indexing, or implicit dependency. +An exact template preserves objects, arrays, booleans, numbers, strings, and null. Text interpolation accepts scalars. Conditions add `not`, type-sensitive `==` and `!=`, and numeric `<`, `<=`, `>`, and `>=`. There is no code execution, arithmetic, arbitrary function, indexing, or implicit dependency. ## Secret references -Provider credentials, action environment values, and protocol headers use `{ env: NAME }`. The environment name is stored in the workflow, but the value is resolved only at the adapter boundary and must be allowed by policy. +Provider credentials, action environment values, and protocol headers use +`{ env: NAME }`, `{ file: PATH }`, or a bounded `{ process: ... }` reference. +The source description is stored in the workflow, but the value is resolved +only at the execution boundary. File and process sources require explicit +`secretFileRoots` or `secretProcessAllowlist` policy. See +[Secret references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md). ## Example and validation @@ -108,5 +220,12 @@ agentctl plan examples/v1/dataflow.yaml agentctl run examples/v1/dataflow.yaml --db /tmp/dataflow.db --output json --color never ``` -Related guides: [Workflow authoring](/agentctl/guides/workflow-authoring/), [Policies](/agentctl/concepts/policies/), [Tools](/agentctl/concepts/tools/), and [Workflow DSL](/agentctl/concepts/workflow-model/). -> Canonical source: [`docs/reference/YAML.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/YAML.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +Related guides: [Workflow authoring](/agentctl/guides/workflow-authoring/), [Matrix +and foreach](https://github.com/opensourceops/agentctl/blob/main/docs/guides/MATRIX_AND_FOREACH.md), [Conditions and +routers](https://github.com/opensourceops/agentctl/blob/main/docs/guides/CONDITIONS_AND_ROUTERS.md), [Bounded +loops](https://github.com/opensourceops/agentctl/blob/main/docs/guides/BOUNDED_LOOPS.md), [Reusable +sub-workflows](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SUB_WORKFLOWS.md), +[Compensation](https://github.com/opensourceops/agentctl/blob/main/docs/guides/COMPENSATION.md), [Secret +references](https://github.com/opensourceops/agentctl/blob/main/docs/guides/SECRET_REFERENCES.md), [Policies](/agentctl/concepts/policies/), +[Tools](/agentctl/concepts/tools/), and [Workflow DSL](/agentctl/concepts/workflow-model/). +> Canonical source: [`docs/reference/YAML.md`](https://github.com/opensourceops/agentctl/blob/main/docs/reference/YAML.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/security/index.md b/src/content/docs/_generated/security/index.md index 309a5c6..f484346 100644 --- a/src/content/docs/_generated/security/index.md +++ b/src/content/docs/_generated/security/index.md @@ -6,23 +6,92 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/SECURITY.md" ## Controls - Workflow parsing is strict, bounded to 1 MiB, source-aware, and has no executable expression language. -- Environment-backed primary credentials are resolved immediately before provider dispatch; custom header references are resolved while constructing the adapter, before a run or database is created. There are no API-key flags. Provider/protocol response JSON keys and values, provider request IDs, errors, subprocess output, and traces redact every known configured secret value before persistence or output. +- Provider credentials in the fresh execution closure are preflighted before a + new run record or effect is created; custom header references are resolved + while constructing a required adapter; action environment references are + resolved at the task boundary. References may use an environment variable, a + bounded canonical file under `secretFileRoots`, or a direct bounded process + under `secretProcessAllowlist`. Values use zeroizing memory wrappers and never + enter ordinary persisted state. There are no API-key flags. + Provider/protocol response JSON keys and values, provider request IDs, errors, + subprocess output, and traces redact every known configured secret value + before persistence or output. - Canonical read/write roots reject `..` and symlink escape. Writes use temporary files and rename. -- Processes require an allowed executable basename, direct argv, cleared environment, selected variables, validated output/timeout bounds, concurrent stdout/stderr draining, and cancellation. Output-limit, timeout, and cancellation paths terminate and reap the child; diagnostics are bounded and omit captured output when secret environment values are present. -- Network destinations require an exact/wildcard host grant. Provider and protocol clients disable redirects and use rustls. +- Processes require an allowed executable basename and explicit isolation + mode. Default `process` mode uses direct host arguments, a cleared + environment, selected variables, validated output/timeout bounds, concurrent + stdout/stderr draining, cancellation, and process-tree termination, but is + not a sandbox. `container` mode requires a local digest-pinned image and + available Docker or Podman engine. It disables pulls/networking, fixes a + read-only root/workspace, runs non-root, drops capabilities, enables + `no-new-privileges`, and bounds memory/CPU/PIDs/output/time. Engine/image + preflight fails without host fallback; abnormal exits trigger forced named + container cleanup. +- Required provider and protocol destinations are authorized before run + persistence. Scheme, effective port, and host must be granted. Every resolved + address is checked against private/reserved policy and the complete accepted + answer is pinned into the direct HTTP client, preventing a second DNS lookup. + Empty or mixed public/private answers fail closed. Redirects and Unix sockets + are disabled. Environment proxies are ignored by default. TLS uses rustls; + optional custom CA bundles are certificate-only protected references. + DNS/connect time, protocol operation time, task time, and response bytes are + bounded. - Tool input and output JSON Schemas are enforced. Models, MCP annotations, A2A cards, remote schemas, and results cannot grant capabilities. - Requests are ledgered before effects. Global denial or approval cannot be weakened by a tool contract. Approval is durable; non-interactive mode pauses with exit `3` or uses an explicitly stricter deny/fail mode, never a prompt or implicit approval. +- Optional run-wide budgets use atomic SQLite reservations before provider, + tool, process, and artifact dispatch. Actual usage is reconciled afterward, + and the durable creation timestamp bounds wall time across resume. Monetary + enforcement requires authoritative cost or explicit versioned custom + pricing. - SQLite uses foreign keys, WAL/busy timeout, version checks, checksummed checkpoints, and mode `0600` on Unix. -- Packs require a supported manifest/version and can be checked against SHA-256 integrity. +- Optional application-level state encryption uses versioned AES-256-GCM envelopes with per-value random nonces, field-bound authenticated data, key IDs, environment references, transactional migration/rotation, and database triggers that reject plaintext or stale-key writes after enablement. Missing, wrong, unsupported, or tampered keys/envelopes fail closed. +- Repair never mutates a terminal source. Reuse requires versioned definition/input/contract/output/state metadata and verified content-addressed artifact sizes and SHA-256 digests. Artifact ingestion uses atomic no-clobber writes, immutable blobs, bounded leases, and a cross-process GC lock. Repair creation and reused-task/reference materialization are one SQLite transaction. +- A recorded replay cannot be a repair source because it has no direct effect ledger. A materialized reused/recorded task cannot be selected for restart without returning to direct effect history. Repaired agents start fresh provider sessions. +- Pack graphs are content-locked. Local paths remain contained; Git commits are + fully pinned; immutable archives are redirect-free, digest-checked, and + extraction-bounded. Optional Sigstore bundles verify an allowlisted identity + and issuer against the embedded public-good trust root. Unsigned process packs + cannot load without an explicit review acknowledgement. +- Process extensions negotiate an exact version, schemas, and capabilities + before invocation. They use direct argv, cleared selected environment, + bounded input/output/time, process-tree cancellation, a durable effect + identity, and secret redaction. +- Long-term memory uses typed bounded entries, exact metadata filters, explicit + retention, bounded result/candidate counts, finite dimension-checked vectors, + and recorded retrieval effects. External adapter results are validated before + entering task state. Embedding credentials use the same secret resolution + and redaction boundary as model providers. - The workspace forbids unsafe Rust, denies warnings, locks dependencies, checks licenses/sources/advisories, scans secret patterns, and keeps live tests outside CI. ## Limitations -Path and executable allowlists are not a sandbox. A permitted program can access anything the operating-system identity can access. Host allowlists do not defend against every DNS rebinding, proxy, local-service, or compromised endpoint scenario; use network isolation for hostile workflows. SHA-256 integrity establishes sameness, not author identity. SQLite protects local correctness but is not encrypted and is not a secret store. +Path and executable allowlists are not a sandbox. A permitted program, including +a secret helper, can access anything the operating-system identity can access. +Container-isolated actions can read their mounted working directory and +receive explicitly authorized secrets; the selected image and container engine +remain trusted dependencies. No native Linux namespace, macOS sandbox-profile, +or Windows restricted-token backend is claimed. +Redaction cannot prevent an authorized recipient from transforming a secret +before exfiltration. Enabling `allowProxy` explicitly delegates routing and +name resolution to the configured environment proxy, so treat that proxy as a +trusted network boundary. An authorized or compromised endpoint can still +exfiltrate data it legitimately receives. Use external egress isolation for +hostile workflows. SHA-256 integrity establishes sameness; Sigstore +identity depends on the configured issuer, subject, bundle evidence, and +installed trust root. State encryption is application-level selected-field protection, not +full-database encryption, access control, or a secret store. Prompts, file content, model output, remote artifacts, and tool output may be confidential or malicious. Treat them as data, validate before mutation, minimize trace export, and isolate untrusted automation. Workflow, input, pack, direct-read, existing-write-target, and instruction files are capped at 1 MiB. Approval is a decision point, not proof that an operation is safe. At-most-once recovery may leave an uncertain external outcome for human reconciliation. -MCP reconnection and A2A resubmission are intentionally not automatic. Streaming is bounded but completed results, not token deltas, enter workflow state. Windows cannot express Unix database mode bits; rely on the user profile ACL and CI tests. +MCP reconnects at most once only for calls declared `pure`, `idempotent`, or `keyed`, and verifies the refreshed tool schema before redispatch. Unknown and at-most-once MCP calls are never automatically repeated after ambiguity. A2A persists a known remote task ID and may resume observation, but never resubmits an ambiguous `SendMessage`. Streaming is bounded but completed results, not progress deltas, enter workflow state. Windows cannot express Unix database mode bits; rely on the user profile ACL and CI tests. + +SQLite and sibling artifact-root access are the repair authorization boundary. There is no tenant identity or row-level authorization. Run IDs, task/effect identity, status, timing, digests, paths, sizes, schema metadata, and key references remain visible. Artifact blob bytes are not encrypted. An identity that can modify the state directory can corrupt or replace local history, although envelope authentication and artifact digest verification prevent silent use of changed protected content. + +Memory keys, namespaces, format versions, timestamps, expiry, embedding provider, +and dimensions remain operational metadata. Entry payloads, searchable text, +metadata JSON, and embedding vectors are protected when selected-field state +encryption is enabled. The local hash provider is deterministic lexical +indexing and must not be described as a confidential local neural model. Report vulnerabilities privately to the repository maintainer. Do not include credentials, database contents, or production prompts in a report. -> Canonical source: [`docs/SECURITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/SECURITY.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/SECURITY.md`](https://github.com/opensourceops/agentctl/blob/main/docs/SECURITY.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/security/threat-model.md b/src/content/docs/_generated/security/threat-model.md index 577375d..3804db0 100644 --- a/src/content/docs/_generated/security/threat-model.md +++ b/src/content/docs/_generated/security/threat-model.md @@ -5,7 +5,12 @@ editUrl: "https://github.com/opensourceops/agentctl/edit/main/docs/THREAT_MODEL. --- ## Assets and boundaries -Assets are workspace files, allowed environment secrets, provider accounts, external systems reached by tools, workflow history, prompts/results, approvals, and the integrity of deterministic scheduling. Boundaries are the YAML/pack parser, filesystem/process/network executors, provider APIs, MCP servers, A2A peers, SQLite, trace exporters, and dependencies. +Assets are workspace files, content-addressed artifact bytes, referenced +environment/file/process secrets, provider accounts, external systems reached +by tools, workflow history, prompts/results, approvals, and the integrity of +deterministic scheduling. Boundaries are the YAML/pack parser, secret resolver, +filesystem/process/network executors, provider APIs, MCP servers, A2A peers, +SQLite and its sibling artifact root, trace exporters, and dependencies. The local operator and reviewed binary are trusted. Workflow authors are only as trusted as policy grants. Models, file content, remote descriptions/results, pack content without independent provenance, and all network peers are untrusted. The host OS, CA store, and Rust dependency supply chain are assumed but monitored dependencies. @@ -13,17 +18,28 @@ The local operator and reviewed binary are trusted. Workflow authors are only as | --- | --- | --- | | Malicious YAML/template causes code execution or resource exhaustion | strict fields, constrained paths/equality, 1 MiB bound, fuzzing | deeply nested valid data remains bounded mainly by parser behavior | | Path traversal or symlink escape | canonical roots and focused tests | TOCTOU is possible if another process swaps paths; isolate hostile workspaces | -| Secret exfiltration through CLI/log/database/trace | env references, no key flags, allowlists, redaction, secret scan | authorized tools can deliberately transmit permitted data | +| Secret exfiltration through CLI/log/database/trace | typed references, canonical file roots, bounded allowlisted process helpers, zeroizing values, no key flags, redaction, raw-database tests, secret scan | authorized recipients can deliberately transmit or transform permitted data | +| SQLite disclosure reveals confidential run content | optional AES-256-GCM field envelopes, external key reference, authenticated context, fail-closed triggers, transactional rotation | metadata and artifact bytes remain visible; unencrypted and pre-migration backups remain sensitive | | Command injection | direct argv, no shell, cleared env, executable allowlist | an allowed executable may interpret malicious arguments | -| SSRF/redirect bypass | URL parse, host allowlist, disabled redirects, tests | DNS/proxy behavior needs external network containment for hostile inputs | +| Host process exceeds intended authority | explicit plan-visible `process` versus `container` mode; container mode is digest-pinned, local-only, networkless, read-only, non-root, capability-dropped, resource-bounded, and fail-closed | host mode and secret helpers retain the agentctl identity; container engine/image are trusted; readable workspace and explicit secrets remain visible inside the container | +| SSRF, DNS rebinding, or redirect bypass | strict HTTP(S) scheme/host/port policy, every-answer IP classification, direct-client DNS pinning, private-network deny by default, redirects and Unix sockets disabled, proxies denied by default, bounded responses | explicit proxy opt-in trusts that proxy; authorized or compromised destinations remain data recipients; external egress isolation is still stronger | +| Unreviewed remote pack acquisition reaches an unwanted source | immutable exact source, HTTPS except loopback fixtures, no URL credentials/query/fragment, redirects disabled, digest and extraction bounds, locked offline execution option | runtime network policy does not authorize configuration-time pack fetches; use `--locked --offline` for untrusted workflows and prepare the cache through a trusted operator path | | Prompt injection grants tool authority | policy outside model, visible tool set, schema validation, approvals | an operator may approve deceptive content | +| Parallel or iterative work exhausts provider, time, process-output, artifact, or cost allowance | compiled graph limits, atomic run-wide reservations before dispatch, actual-usage reconciliation, durable wall deadline, per-operation limits | provider input and cost can be estimated before response; an accepted effect can exceed an estimate and then fail the run | | MCP annotation or A2A card claims safety | always treated as untrusted metadata | compromised authorized peer can return malicious but schema-valid data | | Crash duplicates an external mutation | request-before-start ledger, uncertain state, no silent retry | external action may have happened without acknowledgement | | Replay reissues effects | recorded replay uses stored terminal output only | replayed data may no longer reflect current reality, by design | +| Repair reuses tampered or unrelated state | stable workflow identity, versioned task/input/contract/output/state fingerprints, immutable CAS blobs, artifact digest checks, transactional materialization | an attacker with database/artifact-root write access is inside the local application trust boundary | +| Repair duplicates a partial mutation | closure effect inspection, conservative uncertainty block, narrow operator `not-applied` reconciliation | remote truth may remain unknowable and keep the repair blocked | +| Repair carries failed model state | every repaired agent starts a fresh provider session; dataflow uses validated JSON output | a valid reused output can still contain hostile content and must remain policy constrained | +| Source or workspace deletion breaks repair | reused output/state metadata and independent CAS references are materialized into the repair run | deleting/corrupting the shared CAS or restoring SQLite without it still blocks repair | +| Concurrent GC removes an in-flight artifact | cross-process lock, durable ingestion leases, transactional references, quarantine recovery | network filesystems with broken advisory-lock semantics are unsupported | | Approval bypass in CI | non-interactive durable pause or explicit deny/fail; operator resolution | stolen database write access is outside application trust boundary | | Pack substitution | SHA-256 verification and semver/API checks | digest source/signature trust is manual | | Corrupt or future state misexecutes | schema/version/checksum/deserialization failures | SQLite file deletion or rollback by an attacker is not prevented | | Dependency compromise | locked registry-only deps, cargo-deny, license/source checks | registry compromise and zero-days remain possible | -No unresolved critical or high-severity defect is knowingly accepted for the implemented boundary. Deferred sandboxing, signature verification, distributed concurrency, and encrypted storage are explicit product limitations, not implied controls. -> Canonical source: [`docs/THREAT_MODEL.md`](https://github.com/opensourceops/agentctl/blob/main/docs/THREAT_MODEL.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +No unresolved critical or high-severity defect is knowingly accepted for the implemented boundary. Host process policy, native OS sandboxing, signature verification, and distributed concurrency are not implied controls. Container isolation is claimed only for actions that explicitly request and successfully preflight that mode. State encryption protects its documented columns only and is not described as full-database encryption. + +Run access control is the database file and operating-system identity. `agentctl` has no multi-tenant authorization layer; do not let an untrusted principal select another tenant's source run from a shared database. +> Canonical source: [`docs/THREAT_MODEL.md`](https://github.com/opensourceops/agentctl/blob/main/docs/THREAT_MODEL.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/_generated/troubleshooting/index.md b/src/content/docs/_generated/troubleshooting/index.md index dabd08f..6d2cff9 100644 --- a/src/content/docs/_generated/troubleshooting/index.md +++ b/src/content/docs/_generated/troubleshooting/index.md @@ -15,7 +15,7 @@ flowchart TD D --> E{Pending approval?} E -->|Yes| F[Review and resolve approval, then resume] E -->|No| G{Uncertain effect?} - G -->|Yes| H[Reconcile the external system before any fork] + G -->|Yes| H[Reconcile the external system before repair or fork] G -->|No| I[Use task, effect, provider, and audit evidence] ``` @@ -40,9 +40,11 @@ agentctl schema --write /tmp/workflow.schema.json --output json --color never ## Provider authentication failure -**Symptom:** Exit `6` reports a missing environment reference or authentication response. +**Symptom:** Exit `6` reports an unavailable secret reference or authentication response. -**Likely cause:** The workflow names a credential environment variable that is absent or the provider rejected it. +**Likely cause:** The workflow names an absent environment value, unavailable +or denied file/process source, or the provider rejected the resolved +credential. **Diagnose:** @@ -51,9 +53,13 @@ agentctl auth check workflow.yaml --output json --color never agentctl providers inspect workflow.yaml --output json --color never ``` -**Expected evidence:** The environment variable name and provider capability, never the secret value. +**Expected evidence:** The safe source description and provider capability, +never the secret value. Process references report `unchecked` and are not +executed by diagnostics. -**Resolve:** Inject the named secret through the shell, scheduler, or CI secret facility. Do not add a key to YAML or a command argument. +**Resolve:** Inject the named environment value, mount the file under an allowed +root, or repair the process policy/helper. Do not add a key to YAML or a command +argument. ## Provider capability mismatch @@ -112,6 +118,22 @@ ls -ld /state /state/runtime.db **Resolve:** Resume only a safe non-terminal run. Replay only a terminal run. Reconcile uncertain external state before an explicit fork. +## Repair plan blocked + +**Symptom:** `repair --plan` emits a valid `RepairPlan` with `compatible: false` and exits `3`. + +**Diagnose:** + +```text +agentctl repair target.yaml SOURCE_RUN_ID --from TASK --plan \ + --db .agentctl/runtime.db --output json --color never +agentctl effects --db .agentctl/runtime.db inspect SOURCE_RUN_ID --task TASK +``` + +**Expected evidence:** Each `blockedReuse` item names the task, compatibility rule, safe source/target fingerprints, suggested root, and whether a full fork is required. + +**Resolve:** Choose the earliest changed/incompatible producer as another repair root, restore the exact verified artifact, add a structured output contract and create a fresh source result, or reconcile an uncertain effect only after checking external reality. Do not edit task rows or use fork as a generic force option. See [Repair a failed workflow](/agentctl/guides/selective-repair/). + ## Container permission or read-only failure **Symptom:** The image cannot create `/state/runtime.db` or write `/artifacts`. @@ -120,6 +142,31 @@ ls -ld /state /state/runtime.db **Resolve:** Provision and mount `/state` and `/artifacts` with appropriate ownership. Keep the root filesystem read-only and use `/tmp` as a small `noexec,nosuid` tmpfs. +## Podman machine or forwarding unavailable + +**Symptom:** `podman info` reports connection refused even though Podman is +installed, or `cargo xtask acceptance-container` cannot reach the engine. + +**Diagnose:** + +```text +podman machine list +podman system connection list +podman machine start podman-machine-default +podman info +``` + +**Expected evidence:** The existing machine is running and the configured +forwarded socket answers `podman info`. + +**Resolve:** Start the existing machine without deleting or recreating it. Some +macOS command harnesses terminate libkrun and `gvproxy` children when the +starting shell exits; keep that terminal open and probe from another terminal. +If `machine stop` reports a stale `gvproxy` PID, first prove the recorded PID +does not exist, move only that temporary PID file aside, stop cleanly, and +start again. Do not delete the machine, images, or connection configuration +and do not weaken TLS to make the probe pass. + ## Corporate CA failure **Symptom:** The image build cannot verify the intercepted dependency-network certificate. @@ -130,9 +177,12 @@ ls -ld /state /state/runtime.db **Symptom:** A workspace or database path parses differently from a Unix example. -**Resolve:** Use native absolute paths and quote paths with spaces. Windows cannot express Unix database mode bits, so rely on the user profile ACL. Hosted Windows evidence is configured but still pending for the current candidate. +**Resolve:** Use native absolute paths and quote paths with spaces. Windows +cannot express Unix database mode bits, so rely on the user profile ACL. The +exact-head hosted Windows verification, acceptance, completeness, and package +gates pass for the current candidate. ## Safe issue report Include the exact `agentctl version`, operating system, redacted command, exit code, diagnostic code, workflow API version, minimal non-secret workflow, and relevant run/trace IDs. Share a narrow redacted `inspect` excerpt only when needed. Report security problems through the private process in [Security](/agentctl/security/), not a public issue. -> Canonical source: [`docs/guides/TROUBLESHOOTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/TROUBLESHOOTING.md). Verified against agentctl commit `f3181f93afac7546f01923491f77dabdf26b5ace`. +> Canonical source: [`docs/guides/TROUBLESHOOTING.md`](https://github.com/opensourceops/agentctl/blob/main/docs/guides/TROUBLESHOOTING.md). Verified against agentctl commit `736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47`. diff --git a/src/content/docs/examples/index.md b/src/content/docs/examples/index.md index 2a9c301..acb2e12 100644 --- a/src/content/docs/examples/index.md +++ b/src/content/docs/examples/index.md @@ -1,6 +1,6 @@ --- title: Examples and use cases -description: Start from complete checked workflows for repository review, release gates, scheduled runs, CI, approvals, replay, and providers. +description: Start from complete checked workflows for repository review, release gates, scheduled runs, CI, approvals, repair, replay, and providers. --- Every prominent YAML block on this site is imported from a checked file in the `agentctl` repository. Normal verification uses deterministic actions, the fake provider, or local protocol mocks. Live provider examples are opt-in and labeled. @@ -12,8 +12,11 @@ Every prominent YAML block on this site is imported from a checked file in the ` - [Scheduled operational review](/agentctl/examples/scheduled-review/): an external scheduler invokes one durable non-interactive run. - [CI quality gate](/agentctl/examples/ci-quality-gate/): typed evidence becomes a stable exit code and JSON result. - [Approval-gated action](/agentctl/examples/approval-gated/): policy pauses a mutation for operator review. +- [Selective workflow repair](/agentctl/guides/selective-repair/): reuse compatible upstream output and execute a corrected failed suffix. - [Offline recorded replay](/agentctl/examples/recorded-replay/): a terminal result is reconstructed without executors. - [Provider portability](/agentctl/examples/provider-portability/): one neutral agent shape uses fake and OpenAI configurations with distinct evidence levels. +- [Framework completeness](/agentctl/concepts/framework-completeness/): combine parallel tasks, bounded expansion, routing, loops, sub-workflows, compensation, protocols, and typed handoffs. +- [Live framework verification](/agentctl/reference/live-framework-verification/): inspect sanitized GPT-5.6 recovery, replay, streaming, usage, and container evidence. ## Verification levels diff --git a/src/content/docs/overview.md b/src/content/docs/overview.md index 9b1b0e9..f4b7b58 100644 --- a/src/content/docs/overview.md +++ b/src/content/docs/overview.md @@ -24,7 +24,7 @@ description: Understand the problem agentctl solves, its control model, current ## Current maturity -The workflow API is `agentctl.dev/v1alpha1`. The current source is production-oriented alpha software preparing for hosted release-candidate validation. Deterministic and fake-provider journeys have executable local evidence. Native provider and protocol evidence varies by adapter and is stated in the [capability matrices](/agentctl/reference/capabilities/). +The workflow API is `agentctl.dev/v1alpha1`. The current source is production-oriented alpha software with exact-commit local and hosted release-candidate evidence. Deterministic and fake-provider journeys have executable local evidence, while Linux x64, macOS arm64, Windows x64, container, security, package, SBOM, and release-preparation gates have hosted evidence. Native provider and protocol evidence varies by adapter and is stated in the [capability matrices](/agentctl/reference/capabilities/). This site does not claim stable v1 compatibility, exactly-once execution, an operating-system sandbox, distributed scheduling, parallel task execution, or live validation across every provider. diff --git a/src/data/agentctl-source.json b/src/data/agentctl-source.json index 2bb63aa..eb3f9d8 100644 --- a/src/data/agentctl-source.json +++ b/src/data/agentctl-source.json @@ -2,8 +2,8 @@ "product": "agentctl", "version": "0.2.0", "workflowApi": "agentctl.dev/v1alpha1", - "commit": "f3181f93afac7546f01923491f77dabdf26b5ace", + "commit": "736379ed5f49b0dbe1ad79ac4e4ba794e2c73c47", "dirty": false, "sourceRepository": "https://github.com/opensourceops/agentctl", - "importedFiles": 56 + "importedFiles": 61 } diff --git a/tests/site.spec.ts b/tests/site.spec.ts index 2dc4b25..54fac60 100644 --- a/tests/site.spec.ts +++ b/tests/site.spec.ts @@ -55,7 +55,7 @@ test('Mermaid diagrams render without client errors', async ({ page }) => { const errors: string[] = []; page.on('pageerror', (error) => errors.push(error.message)); await page.goto('/agentctl/architecture/diagrams/'); - await expect(page.locator('pre.mermaid svg')).toHaveCount(14, { timeout: 20_000 }); + await expect(page.locator('pre.mermaid svg')).toHaveCount(15, { timeout: 20_000 }); await expect(page.locator('.error-icon')).toHaveCount(0); expect(errors).toEqual([]); });