Continuous Delivery Intake
Continuous governed delivery starts before any agent writes code. The intake surface turns delivery signals into repo-native artifacts that can be triaged, challenged, and governed without inventing a hosted control plane.
This is the v3 entrypoint that exists today. It records signals, creates delivery intents, exposes triage and approval workflows, and generates execution-ready planning artifacts. It does not auto-start implementation or bypass human authority.
What ships today
The current CLI surface is eight commands:
agentxchain intake record
agentxchain intake triage
agentxchain intake approve
agentxchain intake plan
agentxchain intake start
agentxchain intake resolve
agentxchain intake scan
agentxchain intake status
Artifact layout
All intake state lives under the repo-local .agentxchain/intake/ directory:
.agentxchain/intake/
events/
<event_id>.json
intents/
<intent_id>.json
observations/
<intent_id>/
loop-state.json
events/stores the raw trigger signal.intents/stores the governed delivery intent derived from that event.observations/is created when an intent resolves tocompleted. S5 only scaffolds the directory; later slices may write evidence under it.loop-state.jsonis a cache written byintake status. It is not the source of truth.
Concrete artifact paths:
.agentxchain/intake/events/<event_id>.json.agentxchain/intake/intents/<intent_id>.json.agentxchain/intake/observations/<intent_id>/.agentxchain/intake/loop-state.json
intake record
Use intake record to ingest a signal from a file, stdin, or inline flags.
# inline manual signal
agentxchain intake record \
--source manual \
--signal '{"description":"release smoke failed"}' \
--evidence '{"type":"text","value":"release-postflight.sh failed on tarball smoke"}'
# file-driven CI signal
agentxchain intake record --file ./failed-run.json --json
# stdin-driven schedule signal
cat stale-release-check.json | agentxchain intake record --stdin --json
Supported sources today:
manualci_failuregit_ref_changeschedule
manual is valid for intake record. It is intentionally excluded from intake scan.
Event schema
intake record writes an event file like this:
{
"schema_version": "1.0",
"event_id": "evt_1712173200000_a1b2",
"source": "ci_failure",
"category": "ci_failure_signal",
"created_at": "2026-04-03T20:10:00Z",
"repo": null,
"ref": null,
"signal": {
"workflow": "publish-npm-on-tag",
"run_id": "23944719936"
},
"evidence": [
{
"type": "url",
"value": "https://github.com/shivamtiwari93/agentXchain.dev/actions/runs/23944719936"
}
],
"dedup_key": "ci_failure:6e544bb0df4c4b11"
}
The command also creates a linked intent in detected state.
Deduplication is deterministic
The intake surface is idempotent by contract. Duplicate signals do not create duplicate backlog noise.
Dedup key:
${source}:${sha256(JSON.stringify(sortedSignal)).slice(0, 16)}
Implications:
- signal keys are sorted before hashing
- repeated records for the same source + signal return the existing event
- the linked intent is reused instead of creating a second one
If your intake layer cannot answer "did we already see this signal?" deterministically, it is not governed delivery. It is chaos with JSON files.
intake triage
Use intake triage to turn a detected intent into governed, reviewable work.
agentxchain intake triage \
--intent intent_1712173200000_c3d4 \
--priority p1 \
--template cli-tool \
--charter "Stabilize the published install smoke contract" \
--acceptance "tarball installs by explicit path,docs match release proof"
Current triage actions:
detected -> triageddetected -> suppressedtriaged -> rejected
Examples:
# suppress a noisy or already-handled signal
agentxchain intake triage \
--intent intent_1712173200000_c3d4 \
--suppress \
--reason "duplicate of active release fix"
# reject a triaged intent after review
agentxchain intake triage \
--intent intent_1712173200000_c3d4 \
--reject \
--reason "not worth automated follow-up"
Intent schema
{
"schema_version": "1.0",
"intent_id": "intent_1712173200000_c3d4",
"event_id": "evt_1712173200000_a1b2",
"status": "planned",
"priority": "p1",
"template": "cli-tool",
"charter": "Stabilize the published install smoke contract",
"acceptance_contract": [
"tarball installs by explicit path",
"docs match release proof"
],
"approved_by": "release-manager",
"planning_artifacts": [
".planning/command-surface.md",
".planning/platform-support.md",
".planning/distribution-checklist.md"
],
"requires_human_start": true,
"target_run": null,
"created_at": "2026-04-03T20:10:00Z",
"updated_at": "2026-04-03T20:18:00Z",
"history": [
{
"from": null,
"to": "detected",
"at": "2026-04-03T20:10:00Z",
"reason": "event ingested"
},
{
"from": "detected",
"to": "triaged",
"at": "2026-04-03T20:15:00Z",
"reason": "triage completed"
},
{
"from": "triaged",
"to": "approved",
"at": "2026-04-03T20:16:00Z",
"reason": "critical release regression",
"approver": "release-manager"
},
{
"from": "approved",
"to": "planned",
"at": "2026-04-03T20:18:00Z",
"reason": "generated 3 planning artifact(s) from template \"cli-tool\"",
"artifacts": [
".planning/command-surface.md",
".planning/platform-support.md",
".planning/distribution-checklist.md"
]
}
]
}
intake approve
Use intake approve to move a triaged intent through the authorization gate.
agentxchain intake approve \
--intent intent_1712173200000_c3d4 \
--approver release-manager \
--reason "critical release regression"
Approval is not triage with different wording. It is the explicit transition from classified work to authorized work.
Current approval actions:
triaged -> approvedblocked -> approved
approved still does not start a governed run. It only means the intent may proceed to planning.
intake plan
Use intake plan to materialize template-backed planning artifacts and transition an approved intent to planned.
agentxchain intake plan \
--intent intent_1712173200000_c3d4 \
--project-name AgentXchain \
--json
Current planning action:
approved -> planned
Planning behavior is template-aware:
cli-tool,api-service, andweb-appcan generate.planning/artifacts from the governed template manifestgenericis valid and may generate zero planning artifacts- if any target artifact already exists, planning fails atomically unless
--forceis supplied
planned means execution-ready. It does not mean execution has started until intake start links the intent to a governed run.
intake start
Use intake start to bridge one planned intent into the existing governed run engine.
agentxchain intake start \
--intent intent_1712173200000_c3d4 \
--role dev \
--json
Current start action:
planned -> executing
Success output includes:
- the resolved
run_id - the first assigned
turn_id - the chosen role
- the dispatch directory for the new governed turn
On success the intent gains:
target_runtarget_turnstarted_at
intake start is a governed handoff, not a second execution engine. It reuses the same governed state, turn-assignment, and dispatch-bundle machinery as the rest of the CLI.
Start constraints
intake start rejects deterministically when:
- the intent is not in
planned - any recorded planning artifact is missing on disk
- another governed turn is already active
- the run is
blocked - the run is
completed - the run is paused on
pending_phase_transitionorpending_run_completion
Do not blur that last rule. Under the current governed-state contract, paused is an approval-held state, not a generic resumable idle state for intake.
intake resolve
Use intake resolve to close the loop between a governed run outcome and the linked intake intent.
agentxchain intake resolve \
--intent intent_1712173200000_c3d4 \
--json
intake resolve reads .agentxchain/state.json, verifies that the governed run_id still matches the intent's target_run, and then maps the run outcome back onto intake state truth.
Run-outcome mapping
| Governed run status | Intent transition | Notes |
|---|---|---|
blocked | executing -> blocked | Copies run_blocked_on, run_blocked_reason, and run_blocked_recovery onto the intent |
completed | executing -> completed | Copies run_completed_at, run_final_turn, and creates .agentxchain/intake/observations/<intent_id>/ |
failed | executing -> failed | Records failure-linked run fields without reopening the run |
active | no change | Returns ok: true, no_change: true; the intent stays executing |
paused | no change | Returns ok: true, no_change: true; approval-held pause is not an intake outcome |
idle | error | Indicates the governed state was reset or no longer matches the started intent |
Resolve result shape
Structured output includes:
previous_statusnew_statusrun_outcomeno_change- the updated
intent
Example success result:
{
"ok": true,
"previous_status": "executing",
"new_status": "blocked",
"run_outcome": "blocked",
"no_change": false,
"intent": {
"intent_id": "intent_1712173200000_c3d4",
"status": "blocked",
"target_run": "run_20260403_001",
"run_blocked_on": "human_approval",
"run_blocked_reason": "pending_review"
}
}
Re-approval after a block
S5 makes the recovery path explicit:
planned -> executing -> blocked -> approved -> planned -> executing
intake resolve does not restart work by itself. It records the outcome. If the run blocked and the operator decides to continue, the next step is agentxchain intake approve --intent <id> followed by re-planning and a new intake start.
intake scan
Use intake scan to ingest a deterministic source snapshot through the existing recordEvent() path.
agentxchain intake scan \
--source ci_failure \
--file ./ci-failures.snapshot.json \
--json
cat release-checks.snapshot.json | \
agentxchain intake scan --source schedule --stdin --json
Supported scan sources:
ci_failuregit_ref_changeschedule
manual is excluded on purpose. Manual one-off intake already has agentxchain intake record, and scan is not a generic batch wrapper for every source type.
Snapshot contract
intake scan consumes one source-specific snapshot object:
{
"source": "ci_failure",
"captured_at": "2026-04-03T23:00:00Z",
"items": [
{
"signal": {
"workflow": "publish-npm-on-tag",
"run_id": "23944719936",
"status": "failed"
},
"evidence": [
{
"type": "url",
"value": "https://github.com/shivamtiwari93/agentXchain.dev/actions/runs/23944719936"
}
],
"category": "delivery_regression"
}
]
}
Contract notes:
itemsmust be a non-empty array- each item must include a non-empty
signalobject and non-emptyevidencearray category,repo, andrefare optional passthrough fieldscaptured_atis informational metadata in S4; it is accepted but not validated or stored--sourcemust matchsnapshot.source
Scan result semantics
Each snapshot item produces one deterministic result:
created: a new event and linkeddetectedintent were writtendeduplicated: the signal already existed and the existing event/intent were returnedrejected: the item failed validation and was not recorded
Machine-readable output includes aggregate counts plus per-item results:
{
"ok": true,
"source": "ci_failure",
"scanned": 2,
"created": 1,
"deduplicated": 1,
"rejected": 0,
"results": [
{
"status": "created",
"event_id": "evt_1712273200000_a1b2",
"intent_id": "intent_1712273200100_c3d4"
},
{
"status": "deduplicated",
"event_id": "evt_1712273199000_e5f6",
"intent_id": "intent_1712273199100_a7b8"
}
]
}
Scan failure rules
intake scan rejects deterministically when:
--sourceis not one ofci_failure,git_ref_change,schedule- neither
--filenor--stdinis supplied - both
--fileand--stdinare supplied - the snapshot file cannot be read
- the snapshot JSON is invalid
snapshot.sourcedisagrees with--sourceitemsis missing or empty
Mixed snapshots are processed per item. One bad item does not roll back valid siblings.
State machine: shipped vs deferred
The broader v3 direction defines a larger intake lifecycle. The shipped CLI surface now covers S1 through S5.
Implemented now
detected -> triaged
detected -> suppressed
triaged -> approved
triaged -> rejected
approved -> planned
planned -> executing
executing -> blocked
executing -> completed
executing -> failed
blocked -> approved
Deferred beyond the shipped intake surface
completed -> awaiting_release_approval
awaiting_release_approval -> released
released -> observing
observing -> reopened
reopened -> planned
That distinction still matters. The repo continues to store requires_human_start: true. Approval and planning prepare work; intake start is the explicit human-authorized bridge that turns prepared work into governed execution. intake resolve closes the loop after execution without creating release authority or post-release observation evidence. intake scan only widens ingestion. It does not widen execution authority.
intake status
Use intake status to inspect backlog state or one specific intent.
# summary
agentxchain intake status
# machine-readable summary
agentxchain intake status --json
# one intent plus linked event
agentxchain intake status --intent intent_1712173200000_c3d4 --json
Summary mode reports:
- total events
- total intents
- counts by status
- recent intents ordered by
updated_at
Detail mode returns:
- the selected intent
- linked source event
- full transition history
Governance boundary
Intake is an entrypoint, not a loophole.
- recording an event does not create a governed run
- approving or planning an intent does not create a governed run
- scanning a snapshot does not triage, approve, plan, or start anything
intake startdoes create or attach one planned intent to the governed execution boundaryintake resolvereads governed outcome state and updates the intent; it does not create release evidence or reopen runsplannedis not the same thing asexecuting- the future continuous loop still has to respect explicit approval transitions
- neither
intake scannorintake startauto-triages, auto-approves, or auto-starts from raw signals
If you want automatic code-writing execution from repo signals, that is a later governance decision, not a default.