@xdxer/dingtalk-agent 0.1.5-beta.1 → 0.1.5-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +209 -0
- package/README.en.md +99 -66
- package/README.md +99 -66
- package/dist/bin/dingtalk-agent.js +735 -149
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/actions.js +3 -2
- package/dist/src/actions.js.map +1 -1
- package/dist/src/agent-audit.js +202 -85
- package/dist/src/agent-audit.js.map +1 -1
- package/dist/src/agent-bindings.js +4 -8
- package/dist/src/agent-bindings.js.map +1 -1
- package/dist/src/agent-definition.js +7 -3
- package/dist/src/agent-definition.js.map +1 -1
- package/dist/src/agent-enhance.js +51 -32
- package/dist/src/agent-enhance.js.map +1 -1
- package/dist/src/agent-platform.js +3 -3
- package/dist/src/agent-platform.js.map +1 -1
- package/dist/src/bootstrap.js +6 -2
- package/dist/src/bootstrap.js.map +1 -1
- package/dist/src/development-workspace.js +210 -34
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/doctor.js +65 -9
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/dws.js +67 -3
- package/dist/src/dws.js.map +1 -1
- package/dist/src/init.js +2 -1
- package/dist/src/init.js.map +1 -1
- package/dist/src/map.js +157 -0
- package/dist/src/map.js.map +1 -0
- package/dist/src/memory/candidates.js +8 -0
- package/dist/src/memory/candidates.js.map +1 -1
- package/dist/src/memory/noop-receipt.js +320 -0
- package/dist/src/memory/noop-receipt.js.map +1 -0
- package/dist/src/memory/operational.js +27 -3
- package/dist/src/memory/operational.js.map +1 -1
- package/dist/src/memory/remote-state.js +2 -1
- package/dist/src/memory/remote-state.js.map +1 -1
- package/dist/src/multica-deploy.js +692 -125
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/multica-provider.js +303 -25
- package/dist/src/multica-provider.js.map +1 -1
- package/dist/src/multica-runtime-vocabulary.js +110 -0
- package/dist/src/multica-runtime-vocabulary.js.map +1 -0
- package/dist/src/opencode-evals.js +6 -6
- package/dist/src/opencode-evals.js.map +1 -1
- package/dist/src/opencode-provider.js +21 -7
- package/dist/src/opencode-provider.js.map +1 -1
- package/dist/src/opencode-workspace.js +3 -3
- package/dist/src/opencode-workspace.js.map +1 -1
- package/dist/src/personal-event-evals.js +4 -2
- package/dist/src/personal-event-evals.js.map +1 -1
- package/dist/src/promotion.js +2 -1
- package/dist/src/promotion.js.map +1 -1
- package/dist/src/remote-semantic-state-live-evals.js +14 -8
- package/dist/src/remote-semantic-state-live-evals.js.map +1 -1
- package/dist/src/remote-state-evals.js +2 -2
- package/dist/src/remote-state-evals.js.map +1 -1
- package/dist/src/robot-evals.js +3 -3
- package/dist/src/robot-evals.js.map +1 -1
- package/dist/src/schedule-plan.js +380 -0
- package/dist/src/schedule-plan.js.map +1 -0
- package/dist/src/sessions.js +1 -1
- package/dist/src/sessions.js.map +1 -1
- package/dist/src/skill-manager.js +145 -13
- package/dist/src/skill-manager.js.map +1 -1
- package/dist/src/skills.js +2 -0
- package/dist/src/skills.js.map +1 -1
- package/dist/src/state-dir.js +120 -0
- package/dist/src/state-dir.js.map +1 -0
- package/dist/src/tui.js +369 -0
- package/dist/src/tui.js.map +1 -0
- package/dist/src/upgrade.js +113 -33
- package/dist/src/upgrade.js.map +1 -1
- package/dist/src/waits.js +2 -1
- package/dist/src/waits.js.map +1 -1
- package/dist/src/workspace.js +12 -7
- package/dist/src/workspace.js.map +1 -1
- package/docs/AGENT-IN-PRODUCTION.md +255 -0
- package/docs/ARCHITECTURE.md +165 -31
- package/docs/INSTALLATION.md +7 -7
- package/docs/PLATFORM-GUARDRAILS.md +188 -0
- package/docs/PRIOR-ART.md +4 -0
- package/docs/SELF-TEST.md +4 -4
- package/docs/architecture/agent-platform-connection-layer.svg +120 -0
- package/docs/architecture/digital-employee-composition.svg +92 -0
- package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
- package/docs/assets/digital-employee-at-work.svg +77 -0
- package/docs/schemas/multica-deployment-plan.schema.json +3 -1
- package/docs/schemas/multica-deployment-receipt.schema.json +17 -3
- package/docs/schemas/multica-deployment-status.schema.json +6 -2
- package/docs/schemas/multica-workspace-inspection.schema.json +16 -0
- package/docs/schemas/multica-workspace-run-plan.schema.json +31 -0
- package/docs/schemas/multica-workspace-run.schema.json +161 -0
- package/docs/schemas/multica-workspace-status.schema.json +2 -0
- package/docs/schemas/project.schema.json +54 -3
- package/docs/schemas/workspace-scaffold.schema.json +38 -0
- package/examples/agents/README.md +10 -8
- package/examples/agents/fde-coach/AGENTS.md +2 -34
- package/examples/agents/fde-coach/agent/AGENTS.md +35 -0
- package/examples/agents/fde-coach/agent.bindings.json +10 -0
- package/examples/agents/release-manager/AGENTS.md +2 -34
- package/examples/agents/release-manager/agent/AGENTS.md +35 -0
- package/examples/agents/release-manager/agent.bindings.json +10 -0
- package/lab/agent-eval/catalog.json +5 -5
- package/lab/agent-eval/classic-failures.json +4 -4
- package/lab/agent-eval/completion-gate-regression.json +9 -9
- package/lab/agent-eval/personal-event-live.example.json +3 -3
- package/lab/agent-eval/remote-semantic-state-live.example.json +1 -1
- package/lab/agent-eval/workspace/opencode.json +2 -2
- package/lab/project-workspace/fake-multica-provider.mjs +171 -17
- package/lab/project-workspace/multica-deploy.fixture.json +2 -2
- package/lab/project-workspace/multica-readonly.fixture.json +4 -16
- package/lab/project-workspace/opencode-provider-suite.json +3 -3
- package/lab/project-workspace/project.fixture.json +2 -6
- package/lab/robot-eval/suite.json +1 -1
- package/lab/robot-eval/workspace/AGENTS.md +1 -1
- package/lab/robot-eval/workspace/opencode.json +2 -2
- package/lab/schemas/personal-event-eval.schema.json +1 -1
- package/package.json +12 -9
- package/skills/README.md +10 -8
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/SKILL.md +48 -23
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/AGENTS.template.md +1 -1
- package/skills/core/dta-agent-compose/assets/REPOSITORY.template.md +10 -0
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.dingtalk-doc.template.json +2 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/agent.bindings.local.template.json +2 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/hosts/opencode/opencode.template.json +3 -2
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/evals/evals.json +4 -4
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/agent-definition-contract.md +7 -7
- package/skills/core/dta-agent-compose/references/drive-and-schedules.md +166 -0
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/host-loading-contract.md +11 -13
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/claude-code.md +13 -12
- package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/hosts/opencode.md +14 -13
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/SKILL.md +2 -2
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/assets/eval-catalog.template.json +1 -1
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/evals/evals.json +1 -1
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/eval-topology.md +3 -3
- package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/interactive-debug-channels.md +10 -4
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/SKILL.md +21 -5
- package/skills/core/dta-basic-behavior/references/event-to-behavior.md +38 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/memory-and-evolution.md +3 -1
- package/skills/core/dta-basic-behavior/references/perception-and-gates.md +87 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/risk-authority-and-privacy.md +12 -0
- package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/truth-and-recovery.md +4 -2
- package/skills/core/dta-people-group-memory/COMPLETENESS.md +36 -0
- package/skills/core/dta-people-group-memory/SKILL.md +69 -0
- package/skills/core/dta-people-group-memory/references/adapters.md +273 -0
- package/skills/core/dta-people-group-memory/references/assembly-guidance.md +40 -0
- package/skills/core/dta-people-group-memory/references/binding.md +110 -0
- package/skills/core/dta-people-group-memory/references/cold-start.md +70 -0
- package/skills/core/dta-people-group-memory/references/config-binding.md +89 -0
- package/skills/core/dta-people-group-memory/references/consent-and-visibility.md +83 -0
- package/skills/core/dta-people-group-memory/references/consolidation.md +162 -0
- package/skills/core/dta-people-group-memory/references/event-ingest.md +103 -0
- package/skills/core/dta-people-group-memory/references/guided-setup.md +70 -0
- package/skills/core/dta-people-group-memory/references/model.md +148 -0
- package/skills/core/dta-people-group-memory/references/storage-port.md +107 -0
- package/skills/platforms/deap/PLATFORM.md +30 -1
- package/skills/platforms/multica-dingtalk/PLATFORM.md +34 -8
- package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/SKILL.md +10 -8
- package/skills/platforms/multica-dingtalk/dta-deploy-multica/references/multica-deployment-contract.md +67 -0
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/SKILL.md +81 -11
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/bootstrap.sh +2 -2
- package/skills/platforms/multica-dingtalk/{multica-external → dta-ops-multica}/scripts/multica_ext.py +264 -16
- package/docs/assets/agent-delivery-lifecycle.svg +0 -103
- package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +0 -24
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +0 -28
- package/skills/platforms/multica-dingtalk/dingtalk-agent-boot-multica/SKILL.md +0 -40
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/references/multica-deployment-contract.md +0 -49
- /package/examples/agents/fde-coach/{skills → agent/skills}/fde-coach/SKILL.md +0 -0
- /package/examples/agents/release-manager/{skills → agent/skills}/release-manager/SKILL.md +0 -0
- /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/assets/role-skill.template.md +0 -0
- /package/skills/core/{dingtalk-agent-compose → dta-agent-compose}/references/storage-routing.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/evidence-contract.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/failure-to-case.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/local-connector-smoke.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/scenario-taxonomy.md +0 -0
- /package/skills/core/{dingtalk-agent-eval → dta-agent-eval}/references/storage-modes.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/memory-candidate-proposal.json +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/assets/task-checkpoint.json +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/action-contract.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/runtime-modes.md +0 -0
- /package/skills/core/{dingtalk-basic-behavior → dta-basic-behavior}/references/task-lifecycle.md +0 -0
- /package/skills/platforms/multica-dingtalk/{dingtalk-agent-deploy-multica → dta-deploy-multica}/references/promotion-observation-contract.md +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,215 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@xdxer/dingtalk-agent` are documented here. The project follows semantic versioning; prerelease entries describe release candidates and do not imply that Live canaries or registry publication have completed.
|
|
4
4
|
|
|
5
|
+
## 0.1.5-beta.11 - 2026-07-25
|
|
6
|
+
|
|
7
|
+
A one-fix release, and the fix is a boundary that was being checked with the wrong instrument: string comparison cannot prove that a directory belongs to the host. The state-directory contract now has exactly one owner, and both the receipt store and the candidate store read it instead of keeping private copies. Ships on the `beta` dist-tag; `latest` stays at 0.1.4. Merged as PR #54.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **A symlink inside the agent root let prepared no-op receipts be written outside it (closes #52).** #47 correctly widened the prepared write boundary from the literal `.dingtalk-agent` to "anywhere in the agent root", but it compared `resolve()` strings only. A directory symlink inside the root pointing outside it therefore passed containment, and `mkdirSync`/the atomic write then followed that link: `recordMemoryNoop(root, claim, {stateDir: '.state-link'})` returned a lexical path under the root while `realpath` landed in a directory the host does not own — which is exactly the deployment fact #42 rests authenticity on ("the state directory is host-owned"), so a lexical check can prove neither ownership nor containment. The stateDir contract now has a single owner (`src/state-dir.ts`): lexical containment, stateDir may not equal the root (the bindings "separate private directory" rule), and the realpath of the existing prefix — plus a re-check after the directory is created, covering nested segments and swap races — must stay inside the agent root; a dangling symlink fails closed instead of surfacing as `ENOENT`. `loadAgentBindings` and the prepared candidate store read that same contract instead of keeping private copies (candidate writes were escapable the same way). Legitimate `.agent-private` setups keep issuing and tracing; `../outside-root`, a root-internal symlink to the outside (as stateDir or as its nested `memory/`), and `stateDir='.'` are all refused, and scenario #75 asserts the outside directories stay receipt-free.
|
|
12
|
+
|
|
13
|
+
## 0.1.5-beta.10 - 2026-07-25
|
|
14
|
+
|
|
15
|
+
The registry-and-receipts wave: every "the declaration says X" now has a reader on the other side that can prove or refute it. Completion predicates became referenced registry entries with a readback-verified marker; the memory save-decision leaves a typed, forgery-hardened trace; and three review rounds on this very wave (#35/#38/#39, #42, #45/#46/#47) were folded back in before shipping. Ships on the `beta` dist-tag; `latest` stays at 0.1.4. Merged as PRs #34, #36, #37, #41, #43, #44, #48, #49.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **predicateRef readback contract (advances #40).** The `[dta-completion-predicate] <id>` marker emitted into autopilot descriptions was written by `dta schedule plan` and then trusted blindly — no consumer parsed it back, so a platform that dropped or rewrote the description would leave declaration and runtime silently disagreeing, which is the exact failure the registry exists to prevent. The marker now has exactly one parser definition, mirrored across languages (`parseCompletionPredicateMarker` in `src/schedule-plan.ts`, `parse_predicate_marker` in `multica_ext.py`; conflicting markers are a loud `conflict`, never a pick-one). `autopilot-create` performs an independent GET readback after create and compares markers — the create response may merely echo the request, so only the readback counts; missing/rewritten marker exits non-zero with `predicateRef: {declared, remote, verified:false, reason}` instead of reporting the deploy as done. `autopilot-list`/`autopilot-get` annotate parsed `predicateRef` for reconcile. New local `predicate-resolve --manifest dingtalk-agent.json (--id | --description)` resolves a predicate from the same manifest the declaration lives in (no platform credentials needed; unregistered id / conflicting markers exit non-zero) — an operator-side tool for now: runtime reachability (manifest and resolver delivered into the target runtime, invoked per schedule run) is NOT wired and is tracked as a repo-side blocker in #46, distinct from the platform gap. Scenario #70's fake server models the echo-vs-store split and pins drop/mangle/resolve negatives plus TS/Python parser agreement. The remaining half of #40 — per-run host receipts freezing the predicateRef — needs platform capability that does not exist: ledgered as MUL-011 with fixed-upstream criteria (ops skill 0.4.0, compose 0.16.2).
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **Marker validation ran after the non-idempotent create, and malformed markers skipped verification entirely (closes #45).** `autopilot-create` POSTed first and judged the declared marker afterwards, so a locally-detectable conflict still left an orphan autopilot on the platform; and a marker line whose id was empty or ill-formed (`[dta-completion-predicate] Bad_ID`) parsed as "no marker", silently skipping the entire readback verification — the same fail-open shape as #39. The parser (both mirrors) now has a `malformed` state (a marker-intent line with an invalid id never degrades to `none`), `autopilot-create` validates the declared description before any API call and refuses conflict/malformed with zero writes, the readback reason vocabulary gains `remote-marker-malformed`, and `predicate-resolve`'s `--id`/`--description` are mutually exclusive (two sources of truth in one invocation is the exact fork the registry exists to kill). Scenario #70 asserts the POST counter stays flat across refused creates, malformed exits non-zero, and the dual-source resolve is rejected.
|
|
24
|
+
- **Docs claimed the manifest travels with `skill-push`; it does not (advances #46).** The #40 delivery stated the project manifest reaches the runtime workspace with the skill payload — wrong: `skill-push` uploads only the skill directory, the target runtime is not guaranteed to carry `multica_ext.py`, and nothing invokes the resolver per schedule run. The ops and compose docs now state plainly that `predicate-resolve` is an operator-side tool against the local checkout and that runtime reachability is an open repo-side blocker (#46) — separate from the platform-capability gap MUL-011 (ops skill 0.4.1, compose 0.16.3).
|
|
25
|
+
- **Prepared no-op receipts rejected legitimate custom private state directories (closes #47).** The prepared-mode write root was hardcoded to the literal `.dingtalk-agent`, but the bindings/enhance contract explicitly allows an agent to keep its host-managed private state elsewhere in the agent root (e.g. `.agent-private`) — with such a configuration the receipt could not be issued at all and operators saw `no-trace`, misreading "incompatible configuration" as "the step never ran". The boundary is now what it always meant: the state dir must live inside the agent root (escapes still refuse); scenario #75 pins the custom-stateDir prepared path end-to-end plus the escape rejection.
|
|
26
|
+
- **No-op receipts could be forged through both "trusted" entrances (closes #42).** The receipt hash is a keyless integrity digest, not a host signature — any caller who can write the state directory can recompute it — yet `readReceipt` accepted a hand-written file missing `$schema`/`id`/`issuer` as long as its hash was self-consistent (making `trace` answer `ran-empty` for a step that never ran), and `DTA_RUN` pointed at any project-relative directory with a three-field `run.json` was accepted as a "trusted Prepared Run". Reading is now a strict structural contract: exact field set, schema constant, enum/grammar checks, issuer-mode invariants (`prepared` requires `runId` matching the `run:<runId>` occurrence; `direct` requires empty issuer fields), integrity hash, and the receipt id re-derived from `(step, scopeId, occurrence)` and required to match the filename — any violation fails loudly and never counts toward `ran-empty`. The prepared issuer resolves only through the canonical Session tree (`DTA_SESSION` under the configured session root, run under that session's `runs/`, `run.sessionId`/`contextId` cross-checked), mirroring the task-checkpoint discipline. Docs stop calling the digest a signature and state the actual trust boundary: authenticity rests on the state directory being host-owned. Scenario #75 gains the four adversarial negatives (forged partial file, id/filename mismatch, out-of-tree `DTA_RUN`, run↔session identity drift); basic-behavior 0.14.1.
|
|
27
|
+
- **Predicate gate fail-open edges (closes #39) and its human interface (closes #38).** Two malformed inputs slipped past the new completion-predicate gate as "legacy free text": an explicit empty registry (`"predicates": {}`) was collapsed into "no registry declared", and `predicate:` with an empty/invalid id lost its prefix and was judged as free text — both exited 0 and produced apply commands without the predicate marker. Declaring a registry — including an explicitly empty one — now means the project is in reference mode (free-text `completion` blocks), and completion parsing is three-state (free text / valid `predicate:<id>` / malformed reference): any `predicate:` prefix whose id is empty or ill-formed blocks outright instead of degrading. The human interface now fails as closed as the exit code: `schedule show` renders `completionRefIssues` and derives its green summary line from the same `scheduleBlockers` source as the exit code (a new blocker class can never again print green over exit 2), and a blocked `schedule plan` hides the copy-pasteable `autopilot-create` commands and the "执行" guidance entirely. Scenario #74 gains both fail-open negatives plus CLI-level assertions (exit 2, no green line, no executable command).
|
|
28
|
+
- **Expected-negative probes no longer pollute stderr with top-level `[FAIL]` (closes #35).** `dws.die()` printed `[FAIL]` unconditionally before throwing, so a passing eval scenario that intentionally exercises failure paths (#73 prints five of them) showed failure banners on stderr — exactly the surface CI log greps and release gates read. `die` now only throws; diagnosis belongs to the final consumer (the CLI top-level catch prints `错误: <msg>`, an uncaught throw still crashes loudly with the message). #73 asserts that a caught negative probe keeps its full error text while writing nothing to stderr.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **Typed no-op / nothing-to-save receipts (closes #25).** `dta-basic-behavior` demanded that a save-decision which found nothing worth keeping still leave a trace, but never defined where it goes, what it looks like or how to read it back — so agents invented ad-hoc logs and operators still could not tell "ran and judged empty" from "never ran". The host now issues a signed, typed receipt (`src/memory/noop-receipt.ts`, `memory-noop-receipt@1`) under `.dingtalk-agent/memory/noop-receipts/`. Identity is `(step, scopeId, occurrence)`: a Prepared Run's occurrence is derived from trusted run state (`run:<runId>` — an anchor claimed in the body is not accepted), Direct mode must name an explicit event anchor or is refused. Replays are idempotent against the existing receipt; a conflicting claim for the same occurrence fails loudly instead of silently overwriting. The redaction line holds structurally: `reason` is an enum, free-text fields are rejected at validation, and the considered content may only enter as a sha256 digest. New CLI surface `dta memory noop record|list|trace`; `trace --scope --occurrence` answers the operational question directly — `ran-empty` (receipt found) vs `no-trace` (exit code 3). Contract scenario #75 (core tier) pins issuance, idempotency, conflict, validation refusals and both trace verdicts; the basic-behavior reference now points at the typed contract instead of "invent a log" (0.14.0).
|
|
33
|
+
- **Completion-predicate registry (closes #24).** A free-text `completion` predicate is a sentence the runtime model can be talked out of ("already ran today"), and the declared copy and the runtime copy (autopilot description) were hand-maintained twins that silently forked — a real incident ran 30 hours on diverged predicates with no alarm. The manifest gains a top-level `predicates` registry (kebab-case id → `{description` required`, source}`), `completion` references it as `predicate:<id>`, and both sides now carry the *same id*: the schedule plan entry exposes `completionPredicate` and the generated autopilot apply command appends a `[dta-completion-predicate] <id>` marker to the description, so the platform-side readback can be matched against the declaration. Gating is progressive: a reference to an unregistered id blocks; once a registry is declared, free-text `completion` blocks too (all-in); legacy projects without a registry keep working and get a `unregisteredCompletion` migration nudge instead of a wall. The registry lives in the manifest JSON itself, so the Python engine (`multica_ext.py`) reads the same file and the same ids — no second predicate source. Contract scenario #74 (core tier) pins all four states plus registry validation (bad id / empty description / unknown key throw at manifest load). Compose skill's drive-and-schedules reference documents the registry and the cross-language contract (0.16.0).
|
|
34
|
+
- **Read-completeness seal for AI-table reads (closes #23).** Completeness can no longer be inferred from a response body — the platform emits page-aligned truncated prefixes that still claim `hasMore:false`, and `records:null` is a version-dependent truncation/soft-timeout signal. `recordsRead` makes completeness a typed state decided by *how* the read was performed: enumeration is always `unproven` (`hasMore:false` is not evidence), `proven` has exactly two sources — recordId-bounded reads and `proveByCountLedger` cross-checks against an independent ledger (mismatch dies; `records:null` may not participate) — and `records:null` folds to `unproven('records-null')` instead of `[]`, never to "the table is empty". `queryAiTableRecords` now returns `{records, completeness}`; operational-memory key/scope lookups stop loudly on `window-full` and `records-null` instead of treating an unread table as an absent record (which would have minted duplicates). Contract scenario #73 (core tier) pins the matrix, including the indistinguishability of a complete read and a page-aligned truncation.
|
|
35
|
+
|
|
36
|
+
## 0.1.5-beta.9 - 2026-07-25
|
|
37
|
+
|
|
38
|
+
Fixes for the blockers recorded across three real acceptance sessions (2026-07-23/24, the `~/xdx/blockers` corpus). The common shape: fail-closed held the line, but the judge read the wrong evidence, the error named the wrong cause, or the locked state had no clean way out. Ships on the `beta` dist-tag; `latest` stays at 0.1.4. Merged as PRs #21, #27, #29, #30, #31, #32.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **The load-smoke judge could structurally never reach `ready` on a cloud runtime.** It hardcoded the tool names `skill`/`write`/`bash` and required *every* tool_use to match a whitelist, while Multica cloud runtimes surface skill loads as `read_file` ("Loading skill '<name>'") and commands as `terminal` — a smoke that actually succeeded on the platform (all skills loaded, exact JSON posted) was judged `failed` with `loadedSkills: []`. Trace reading now goes through per-runtime-provider vocabularies (`src/multica-runtime-vocabulary.ts`), skill loads are proven by positive evidence (the host-generated `**Skill loaded**` tool_result, or the vocabulary's skill tool_use — model text never counts), and the response is taken from the Issue's own comments first, which no tool rename can break. The `.every(whitelist)` negative gate is gone: one extra harmless tool no longer kills a healthy trace (that had already caused two production false negatives); only dws — as a tool name or shelled out in a command — stays fatal, with a named `smoke.forbidden-tool:dws` failure. Unknown tool names are recorded in `smoke.unrecognizedTools` instead of judged.
|
|
43
|
+
- **Cold-sandbox deploys systematically failed their first smoke.** Pushed skills take minutes to materialize into a runtime sandbox, and deploy fired the smoke immediately, reporting `Skill not found` with no way to tell "not ready yet" from "really broken" — the exact wrong signal that sent one acceptance session off rewriting the agent and swapping templates. A terminal smoke whose trace shows skill-not-found wording is now classified `skills-not-visible`: the receipt converges to `verifying` (not `failed`), apply retries with a bounded, budgeted mention inside the smoke window, and `deploy --status --execute --yes` performs one controlled retry — honestly reported as `remoteWrite: true` / `sideEffect: multica-read-write`.
|
|
44
|
+
- **Switching runtimes deadlocked deploy and retire together.** `scope.agent-binding-mismatch` blocked apply *and* the retire that would have resolved it; the only way out was editing the env back to the old runtime id by hand. Runtime drift is now an inspection diff (`agent.runtime-drift`), not a hard failure: plain apply is still refused (no silent agent migration), `--retire` proceeds (archiving is convergence, not a write to protect), and the new `deploy --rebind-runtime` migrates explicitly — plan-gated, with `previousRuntimeId` baked into the planId and `rebind: {from,to}` on the receipt.
|
|
45
|
+
- **`MULTICA_AGENT_ID` in the environment made every dta call report "Not authenticated. Run 'multica login'".** The multica CLI treats that variable as an agent-identity switch; dta passed the whole process env through, so a manifest envRef with that natural-looking name deadlocked second deploys behind a message pointing at login (one session lost 20+ minutes to it). dta now strips the reserved variable from every provider subprocess (values still resolve from the raw env first), records the removal in `envSanitized`, and `workspace doctor` warns when a manifest ref collides with a reserved name. The fixture example is renamed off the reserved name.
|
|
46
|
+
- **Deploying onto a hermes runtime "succeeded" and then every skill load failed with zero warning.** dta never checked the runtime's provider kind, and the server default for new FC runtimes is hermes — where workspace skills are never visible. Inspection now fails closed (`scope.runtime-provider-unsupported`, expected/actual in the detail) before any remote write when the target runtime's provider has no registered trace vocabulary.
|
|
47
|
+
- **Failures named the enum and hid the facts.** `scope.profile-workspace-mismatch` didn't say which workspace the profile pointed at; provider CLI stderr was hashed and discarded, so "calls all passed yet not authenticated" was undiagnosable without reading source. Scope/auth/binding failures now carry structured `failureDetails` (`code`/`expected`/`actual`/`hint` — IDs and enums only, the redaction contract is untouched), renderers print them, and a failing provider call's stderr is streamed to dta's own stderr in the moment while evidence files keep storing only hashes. Plan-invalidation errors explain the actual rule: don't run `inspect` between dry-run and apply.
|
|
48
|
+
- **`deploy --status` without `--execute` looked like the smoke fields were all null.** It returns the receipt frozen at apply time — for a `verifying` deploy that's the pending snapshot. The report now says so (`receiptFrozen`, `smokeStale`) and hands over the exact refresh command in `nextAction`; the human renderer prints the smoke block and the hint instead of leaving the fields to be misread as a broken readback.
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- Contract coverage for all of the above in #53/#54: cloud-vocabulary smoke with noise commands, hermes fail-closed, reserved-env sanitization on both the inspect and deploy write paths (the fake multica replicates the Go CLI's identity-switch semantics), skills-not-visible retry/convergence/recovery, frozen-status fields, rebind end-to-end (including stale-plan smuggling refusal) and retire-under-drift. The fake provider gained deterministic increasing run timestamps, an issue-comment store with `issue comment list`, cloud and cloud-spoof trace vocabulary modes, a bounded skill-not-found mode, and an async-run-creation mode (`DTA_FAKE_MULTICA_RUN_DELAY_READS`).
|
|
53
|
+
- **ops skill (`dta-ops-multica` 0.3.0, BREAKING)**: `runtime-create-fc` now injects `--provider opencode` by default — the server default is hermes, where workspace skills structurally never load; template auto-pick filters `waiting` and, with several ready candidates, fails closed listing them by `created_at`. `agent-check` **removes the single `healthy` boolean** (it reported green while users could not reach the agent at all) in favor of `infrastructureHealthy` + `userReady` with `reasons[]`, a single `nextAction`, and a `userReadyCaveat` naming the upstream blind spot (installations don't read back effective `allow_unbound`). `dingtalk-account-begin`/`-unbind` carry the server-enforced `binding_mode` (body vs query — the asymmetric wire contract is pinned in comments); `dingtalk-bind` without `--allow-unbound` now says on stderr that unbound senders (the owner included) will only get a binding prompt. PLATFORM.md's false claim that `autopilot-create` stdout carries a non-JSON prefix is corrected (it is pure JSON; the real hazard — non-idempotent create — stays). `multica_ext.py` gains its first automated regression: a fake HTTP server that records every request (#70).
|
|
54
|
+
- **scaffold / schedule**: `workspace create` now atomically creates the declared artifacts directory (with `.gitkeep`), so a fresh project's first `workspace doctor` passes instead of failing on the scaffold's own omission; output states explicitly that only the local manifest was written — no remote Multica resources. Schedule planning shares deploy's exact agent-binding fallback (`multicaAgentIdSource`): a declared `agentIdFrom` env ref wins, otherwise the agent ID saved to workspace state by the first deploy is used verbatim — the golden path no longer demands hand-wiring (#71 pins deploy/schedule consistency). First agent creation prints how the ID will be reused; `agent.unbound-name-candidates` renders the candidate IDs it always had in JSON.
|
|
55
|
+
- **gates**: `agent audit --verify-load` failures now carry a `failureSummary` (probe exitCode/durationMs/answer-match per failing surface) surfaced into the check summary and human output, and probe-execution-class failures get one fresh-session re-confirmation — recorded in `verification.attempts` with `passedOnAttempt`, so a flaky pass is visible instead of unexplainable (`--strict-single-run` opts out; static failures never retry). `check-skill-versions` closes the `git mv` blind spot: rename detection re-attaches the new directory to its old baseline (pure renames require a bump too — the directory name is the flat-namespace interface), with a frontmatter-name fallback for low-similarity rewrites (#72).
|
|
56
|
+
- **docs**: `docs/UPSTREAM-REQUIREMENTS.md` — the ledger of the 14 gaps this repo cannot fix (MUL-001..009 / DWS-001..005) with per-item evidence grades, workarounds and fixed-upstream criteria; the compose skill's drive-and-schedules reference gains the capability-vs-delivery-policy boundary (delivery targets and recipients live in the schedule wake prompt, never in `SKILL.md`).
|
|
57
|
+
|
|
58
|
+
An adversarial review pass on the first cut of this change confirmed and fixed six defects before release: load *attempts* counted as load *evidence* (a failed cold-sandbox load emits the same "Loading skill" tool_use as a successful one — attempts now only feed race classification, and the `**Skill loaded**` banner is only trusted from skill-capable tools' results, so a `terminal` echo cannot forge it); the mention retry loop judged the stale terminal run and could fire duplicate mentions (a new run now counts as arrived only when the latest taskId changes, and the loop stops rather than re-mentions when none appears); a transient failure of the retry *or* first-enqueue-recovery comment escalated into a full rollback of an already-verified deployment (both now just end the attempt and leave the receipt at `verifying`); the dws command scan missed `/usr/bin/dws`, quoted and backticked forms (now tokenized with basename matching, and the tool-name denylist is case-insensitive and segment-based so `mcp__dws__send` counts); and the reserved-env strip list gains `MULTICA_SERVER_URL` and `MULTICA_TOKEN` — a stray pre-prod URL or token in the shell must never retarget a named-profile deploy.
|
|
59
|
+
|
|
60
|
+
## 0.1.5-beta.8 - 2026-07-23
|
|
61
|
+
|
|
62
|
+
Follow-up to the beta.7 rename, from watching a real machine take the upgrade: the four core skills migrated cleanly, the two platform skills sat untouched and unannounced. The three defects below are the same shape — "clean up" was not carried through to the end. Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- Renamed platform skills were stranded, not migrated. `skill install` / `upgrade` only install `BUNDLED_SKILL_NAMES` (the four core skills), so the "replacement must exist before deleting the old copy" gate correctly declined to touch `dingtalk-agent-deploy-multica` and `multica-external` — but nothing ever installed their replacements either, leaving those machines permanently on pre-rename copies with no notice. Stale-copy handling is now a real migration: a legacy skill that is present but whose replacement is not installed gets the replacement installed first, then the old copy removed. This only ever acts on skills the machine already had, so it preserves existing capability rather than adding anything.
|
|
67
|
+
- Dangling exposure symlinks survived cleanup. `~/.agents/skills/<name>` is deleted before `~/.claude/skills/<name>`, which leaves the latter pointing at nothing — and `rmSync` stats the *target*, so `force: true` swallowed the resulting `ENOENT` as "already gone" and left the link in place. The skill therefore stayed visible to Claude Code and was re-reported on every pass. Symlinks are now removed with `unlinkSync`.
|
|
68
|
+
- `dingtalk-agent-boot-multica`, removed from the package back in 0.1.5-beta.2, was still installed on machines and still exposed to Hosts through its `~/.claude/skills` symlink. Withdrawn skills now have their own removal list; unlike a rename they have no replacement to gate on, so they are simply deleted.
|
|
69
|
+
|
|
70
|
+
### Migration
|
|
71
|
+
|
|
72
|
+
`dta upgrade` once more. A machine that took beta.7 has its platform skills carried to the new names on the next `skill install` / `upgrade`, and every removed copy is printed by name — the operation is never silent.
|
|
73
|
+
|
|
74
|
+
## 0.1.5-beta.7 - 2026-07-23
|
|
75
|
+
|
|
76
|
+
**BREAKING.** All six first-party skills move to a `dta-` prefix. The names were previously drawn from three unrelated grammars (`dingtalk-*`, `dingtalk-agent-*`, and a bare `multica-external` with no first-party signal at all), and they all land in `~/.agents/skills/<name>/` — a flat namespace shared with Claude Code, Codex, and OpenCode that this repository does not own. The prefix puts the package owner in the first segment. Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- Renamed, with directories, frontmatter `name`, the platform registry, and `package.json#files` all moved together: `dingtalk-basic-behavior` → `dta-basic-behavior`, `dingtalk-agent-compose` → `dta-agent-compose`, `dingtalk-agent-eval` → `dta-agent-eval`, `dingtalk-people-group-memory` → `dta-people-group-memory`, `dingtalk-agent-deploy-multica` → `dta-deploy-multica`, `multica-external` → `dta-ops-multica`.
|
|
81
|
+
- Two naming grammars are now stated and enforced: core skills are `dta-<domain>`, platform skills are `dta-<role>-<platform>` where `<role>` equals the role in the `src/agent-platform.ts` registry. The old `ops` role carried the name `multica-external`, so the filesystem and the registry disagreed about what that skill was; they no longer can.
|
|
82
|
+
- `skill install` / `skill upgrade` (and therefore `setup`) delete the pre-rename copies from `~/.agents/skills` and `~/.claude/skills` after the new names are in place. A renamed skill is not a second skill — leaving both installed means two nearly identical descriptions are visible to every Host at once, and which one triggers is undefined. Removal is limited to names registered in `LEGACY_SKILL_RENAMES` and to this package's own two install locations; current-name copies and third-party skills are untouched, and repeating the operation is a no-op.
|
|
83
|
+
- An Agent Project manifest that still declares the old Basic name in `agent.skills` is accepted and counts as declaring Basic, but the name is **not** normalized: path resolution keeps following the declared name, because the directory checked into the user's repository still carries it. This is the one place `dta` cannot migrate on the user's behalf.
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- `check:docs` gains a fourth finding kind, `legacy-skill-name`: any pre-rename name appearing anywhere in the repository fails the check. The allowlist is explicit and short — historical evidence that must not be rewritten (`CHANGELOG.md`, `evals/baselines/`, the dated `docs/roadmap/` studies) plus the migration machinery that has to spell the old names out loud. A one-time sweep cleans the present; only a standing gate keeps it clean.
|
|
88
|
+
- Contract scenarios #67–#69 cover the pruning of stale copies, manifest tolerance for the old Basic name, and self-consistency of the naming grammar (prefix, directory basename = frontmatter `name` = registry name, platform role/suffix shape, complete rename ledger, and `package.json#files` coverage). All three run in-process and add no measurable time to the core suite.
|
|
89
|
+
|
|
90
|
+
### Fixed
|
|
91
|
+
|
|
92
|
+
- `dta doctor` output is re-laid out (PR #20). Three concrete defects, not cosmetics: the `⚠️` summary and its `detail` printed the same platform-skill drift twice; `detail` joined four canonical paths and the drift string with ` | ` into a 200+ character line that always wrapped; and three separator styles (`·`, `;`, `|`) coexisted with no column aligned. The cause was that the renderer only ever received pre-joined sentences, so `DoctorCheck` now carries structured `value` / `items` fields (additive — existing `--json` assertions are untouched) and the printer lays out one fact per line with indented details, aligned by `displayWidth`. The three client checks and the `hosts` section are merged into one block instead of stating the same thing twice. Status glyphs stay `✅`/`⚠️`/`❌`: colour may be added, but the glyphs that carry the meaning are part of the stable stdout interface.
|
|
93
|
+
- `dta doctor` pointed at a command that could not fix the problem it reported. On platform-skill drift it suggested `skill upgrade`, which only iterates `BUNDLED_SKILL_NAMES` and never touches a platform skill; on an `ahead` copy it omitted `--allow-downgrade`, which `upgradeGlobalSkill` requires before it will overwrite. Repair commands are now generated per skill from `canonical.state`, and the `outdated` / `modified` / `ahead` states are spelled out in words rather than printed as bare identifiers.
|
|
94
|
+
- `package-lock.json` is realigned to `0.1.5-beta.7`; the manifest had been bumped without it.
|
|
95
|
+
- `check:docs` walked into directories that `.gitignore` had already declared as not-repository-content: `.claude/worktrees/` (full working copies of other branches) and `.dingtalk-agent/` (runtime state). The markdown count had silently grown from 88 to 773, and the new `legacy-skill-name` gate then failed on pre-rename names sitting in someone else's branch — making `release:check` unpassable on any machine that has a worktree. The walker now derives its skip set from `.gitignore`'s directory entries instead of keeping a second hardcoded list.
|
|
96
|
+
- `lab/robot-eval/suite.json` pinned `dta-basic-behavior@0.12.0` while the skill's `metadata.version` had moved to 0.13.0, so the robot-pool scenario's version-sync assertion failed.
|
|
97
|
+
- `npm run release:check` now builds first. The contract runner imports 17 modules from `dist/` at load time, so the gate only ever worked when `dist/` happened to be current — any newly added source file turned the whole release gate into an opaque `ERR_MODULE_NOT_FOUND` before a single check ran.
|
|
98
|
+
|
|
99
|
+
### Migration
|
|
100
|
+
|
|
101
|
+
Existing installs need `dta upgrade` (or `dta skill upgrade`) once; it installs the new names and removes the old copies in the same run. Beyond this repository, three steps are **not** automated: push the renamed platform skills to the Multica workspace and delete the old-named server-side entries (`bootstrap.sh` pulls by name, so both present means pulling the wrong one), and redeploy any deployed Agent whose instructions reference the old Basic name.
|
|
102
|
+
|
|
103
|
+
## 0.1.5-beta.6 - 2026-07-23
|
|
104
|
+
|
|
105
|
+
The CLI's output layer becomes a human/machine dual channel: a person at a terminal gets colour, hierarchy and step-by-step progress, while an Agent capturing stdout through a Bash tool reads text with **not a single ANSI escape** in it (PR #17). Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
|
|
109
|
+
- `src/tui.ts`, a zero-dependency output layer built on two deliberately independent switches. The **colour axis** follows `NO_COLOR` / `NODE_DISABLE_COLORS` / `CLICOLOR` / `TERM=dumb`; the **motion axis** (`\r` redraw, cursor control, column alignment) follows `stream.isTTY` and nothing else. `NO_COLOR` therefore strips colour while leaving the layout skeleton byte-for-byte intact — the same rule half the spinner libraries in the ecosystem get wrong.
|
|
110
|
+
- `StepReporter`: one event stream, two renderers. On a TTY the in-progress line is redrawn in place and collapses into a single terminal fact (`[2/7] 安装 … ✔ (2.1MB, 0.3s)`); off a TTY it emits one line per step with a greppable leading status word and zero control characters. `dta upgrade` now reports its seven natural phases instead of going silent for up to 338 seconds.
|
|
111
|
+
- `dta upgrade --check` (resolve the target without installing, `dingtalk-agent/upgrade-check@1`), `--yes`, and `--help`. `--color` / `--no-color` / `--color=<auto|always|never>` are accepted globally: they are stripped from `argv` before dispatch, so a single site replaces edits to 23 strict-mode `parseArgs` blocks. Two contract scenarios (`DualChannelOutput`, `ConfirmSettles`) pin the invariants in the default `core` tier.
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
- **Environment variables can now only turn colour off, never on.** `FORCE_COLOR=1` / `CLICOLOR_FORCE=1` no longer force colour into a pipe; the only way to colourise non-TTY output is an explicit `--color` on the command line. This deliberately departs from the npm-ecosystem convention, because dta's non-TTY reader is primarily an Agent: an inherited `FORCE_COLOR` would turn escape sequences into model-visible noise, and the leak is invisible to a human on a colour terminal. `TERM` / `COLORTERM` are likewise not treated as enabling signals — they survive into the Agent's environment untouched.
|
|
116
|
+
- Every human-facing printer, `fail()`, the help screens and `dta schedule` route through the theme. **The text and line structure are unchanged byte-for-byte**: semantics still ride on the existing `✅`/`⚠️`/`❌`/`PASS`/`FAIL` glyphs and `key=value` structure, so colour remains a discardable decoration and all existing output assertions keep matching. `--json` bypasses the theme structurally rather than "deciding not to colour", and `dta --version` stays bare — it is the machine-parsed object of dta's own self-upgrade chain.
|
|
117
|
+
- The interactive confirmation on `dta upgrade` appears only when stdin is a TTY. Pipes, CI and Agent invocations keep the previous "run it and it installs" behaviour, so `scripts/release-readiness.mjs` and the contract evals needed no changes.
|
|
118
|
+
|
|
119
|
+
### Fixed
|
|
120
|
+
|
|
121
|
+
- `displayWidth` mis-measured the very glyphs dta prints: `✅` (U+2705) and `❌` (U+274C) counted as one column each because they sit outside the East-Asian-Wide ranges and need `Emoji_Presentation` to be identified. The replacement derives its 62 ranges from a per-code-point sweep and adds zero-width marks (`Mn`/`Me`/`Cf`, but not the spacing `Mc`), emoji modifiers, text-presentation pictographs that are themselves Wide, and lone regional indicators. It now agrees with `string-width@8` across all 260,096 code points in `0x0..0x3FFFF`.
|
|
122
|
+
- The upgrade confirmation could not settle when a TTY's input stream ended: `readline`'s `question()` promise never resolves in that case, so the process exited silently with no error and no non-zero code. It now races the prompt against the `close` event, and both interruption paths decline rather than inheriting the non-interactive default.
|
|
123
|
+
- `npm run release:check` now builds first. The contract runner imports 16 modules from `dist/` at load time, so the gate only ever worked when `dist/` happened to be current; the first newly added source file turned the whole release gate into an opaque `ERR_MODULE_NOT_FOUND` before a single check ran. `eval:contract` already built — `release:check` did not.
|
|
124
|
+
- `dta upgrade --version <older> --force` announced "已是最新版本" and then downgraded anyway; the check result now carries `relation` (`upgrade`/`same`/`downgrade`) instead of a single `outdated` flag. The interactive path also pins the exact resolved version as the install source, closing the window in which a moving registry tag could install one version while the run verified against another.
|
|
125
|
+
|
|
126
|
+
## 0.1.5-beta.5 - 2026-07-23
|
|
127
|
+
|
|
128
|
+
Long-term memory becomes a bundled standard capability: any DingTalk Agent can maintain living profiles for the **people** and **conversations (groups/DMs)** it works with over time, storage-decoupled behind a port so the model layer never touches a specific medium (PR #13). Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- `dingtalk-people-group-memory` joins the default bundle (`BUNDLED_SKILL_NAMES`). It is fully inert until storage is bound — zero writes, zero probes, and it must not claim "I remembered" — so bundling it by default has no side effect; binding is deferred to when the user actually asks. The skill is a three-layer design: `model.md` (Person/Conversation/Fact/Watermark, medium-agnostic — verifiably zero DingTalk vocabulary), `event-ingest.md` (message/todo/doc events → Facts, `evidenceId`-keyed idempotency), and `storage-port.md` (10 operations + 8 capability bits) with adapters for `dingtalk-doc` (narrative) and `aitable` (registry), plus a `local-md` contract.
|
|
133
|
+
- Section `kind` split (`narrative` vs `registry`): prose profiles live in DingTalk docs (read-whole, human-readable), while indexes/watermarks/tombstones live in AI Tables (query-by-key, real pagination, no 340-line truncation wall). The same model-layer operations route to either medium purely by capability bits — swapping the registry medium collapses a whole class of doc-only pathologies.
|
|
134
|
+
- `consolidation.md`: the one-year answer for append-only raw — monthly digests, a bounded O(1) working set, `working-on` decay, derived-section curation, and count-based completeness (write-side row counts reconciled on read, since the production medium truncates silently).
|
|
135
|
+
- `config-binding.md` + `guided-setup.md`: the user-configured storage address lives in `agent.bindings.json#memory` (`dingtalk-doc:<adoc-node>`) or `DTA_MEMORY_STORAGE`, resolved by the existing bootstrap `select()` chain — never hardcoded in the skill. A seven-step guided-creation flow walks a user from nothing to a valid, parse-verified adoc binding record. `COMPLETENESS.md` states honestly what is delivered (guided single-agent read/write, proven on real dws) versus contract-only (full autonomy, multi-agent, one-year compaction).
|
|
136
|
+
- The compose Skill gains a "long-term memory" section: bundled, no assembly-time action beyond writing a seed into the body if already bound; binding must happen under the runtime identity, not the developer identity.
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
|
|
140
|
+
- `dta --help` merges the `info` / `workspace doctor` / `schedule show` read-only-diagnostics into one line, keeping the default help at ≤20 lines after the driving layer (beta.4) added its `schedule` entry.
|
|
141
|
+
|
|
142
|
+
### Fixed
|
|
143
|
+
|
|
144
|
+
- `package.json#files`, the release-readiness required-skill list, and the `#20`/`#28` contract fixtures are updated for the four-skill default bundle; `package-lock.json` is realigned to the package version (beta.4 had bumped the manifest but not the lock).
|
|
145
|
+
|
|
146
|
+
## 0.1.5-beta.4 - 2026-07-23
|
|
147
|
+
|
|
148
|
+
Driving layer: the recurring drives that wake a digital employee become a version-controlled, provider-mapped declaration instead of imperative platform state, plus a smoke-whitelist bare-filename fix that had blocked live deployment (PR #16). Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
149
|
+
|
|
150
|
+
### Added
|
|
151
|
+
|
|
152
|
+
- Agent Projects declare their internalized cron in `dingtalk-agent.json#schedules`: a provider-neutral list (`name`, `cron`, `timezone`, `mode` of `ephemeral`/`work-item`, plus governance metadata `wake`/`completion`/`unit`/`evidence`/`supervision`). The manifest validator rejects non-5-field crons, `@macro` forms, unknown modes and duplicate names; `dta info` reads them back. The project source hash covers only definition + skills, so declaring or editing schedules never perturbs the deployment hash.
|
|
153
|
+
- `dta schedule show` lists the declared drives with each rhythm's data-derived completion predicate and statically checks that no two share a cron minute field (the precondition for collision-safe outward delivery). `dta schedule plan --workspace <name>` maps the declaration to a provider-specific reconcile plan — Multica to `autopilot` create commands (`ephemeral`→`run_only`, `work-item`→`create_issue`); an unsupported provider fails closed and records the declared rhythms as a gap rather than silently downgrading. Both are pure and network-free.
|
|
154
|
+
- `docs/schemas/project.schema.json` gains the `schedules` definition; the compose Skill's `drive-and-schedules.md` is the authoring method: an internalized cron is a level-triggered reconciler (state decides the work and the done), not an edge-triggered dispatcher, and every rhythm must answer five questions with a data-derived completion predicate at its heart.
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
|
|
158
|
+
- Architecture §3.1 makes driving an explicitly modeled layer: dingtalk-agent implements no trigger, but owns the driving contract — declare which rhythms an employee needs, verify per-provider capability at deploy time, and hold the behavior contract a tick must satisfy. Compose, Basic Behavior and the platform packages carry the three platform-independent constraints (timers are unreliable so completion is "did it happen", outward ticks have no lock so they must not share a minute, and the Agent never self-installs or hot-edits its own alarm).
|
|
159
|
+
- The multica-external ops Skill reconciles autopilots from `dta schedule plan` rather than hand-authoring them: list live first, create only what is missing, and never blind-create — `autopilot-create` is not idempotent and duplicates cause duplicate outward sends.
|
|
160
|
+
|
|
161
|
+
### Fixed
|
|
162
|
+
|
|
163
|
+
- The Multica load-smoke whitelist accepted `./result.md` and absolute workdir paths but rejected the same file referenced by a bare name (`result.md`) — which is exactly how the platform Agent writes it — so a smoke that loaded all Skills and produced the correct structured response still reported `providerReady=false` and blocked deployment. Only exact basenames are now accepted (`foo/result.md` and `../result.md` still fail closed); a contract fixture reproduces the bare-name trace and the assertion was verified to go red when the fix is reverted.
|
|
164
|
+
|
|
165
|
+
## 0.1.5-beta.3 - 2026-07-22
|
|
166
|
+
|
|
167
|
+
Agent delivery-package single-source layout and Multica Issue-Adapter receipt compatibility (PR #11). Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
168
|
+
|
|
169
|
+
### Changed
|
|
170
|
+
|
|
171
|
+
- Compose 0.13.2 keeps deployed `agent/AGENTS.md` role-only: shared behavior cases propagate through the versioned Basic directory tree instead of being copied into each Agent definition.
|
|
172
|
+
- Basic Behavior 0.12.0 adds a general batch-side-effect boundary distilled from a supervised DingTalk forwarding incident and the Aily behavior audit: when correctness depends on pagination, stable person-content binding, reconciliation or crash recovery, the Agent must upgrade from a model-driven tool loop to a frozen effect list plus deterministic runner and durable receipts. Without that runtime it may preview or run an explicitly supervised bounded batch, but cannot claim unattended execution. Repository guidance now also defines how future cases progress from evidence to one owner, a lean Skill entry, decision-family references, deterministic fixtures and versioned deployment without copying shared rules into each Agent.
|
|
173
|
+
- Agent delivery packages now have a single source of truth: new projects generate `agent/AGENTS.md` and `agent/skills/`, and Host exposure is materialized only into temporary isolated workspaces instead of being committed alongside the source. The project manifest gains `skillsRoot`; explicit paths and the legacy root layout keep working.
|
|
174
|
+
- Basic Behavior 0.11.11 makes IM history file-identifier recovery mandatory: rich-message recovery follows a fixed readback-before-gap-judgment order, and a fileId present in a history file card must go through `drive info`/read-only download instead of the Agent claiming it cannot read the file. A deterministic history-file-card fixture locks the behavior.
|
|
175
|
+
- Golden Path and load-evidence fixtures moved to the `agent/AGENTS.md` + `agent/skills` single-source layout; load evidence now verifies resolved instructions against the trusted `definitionInstruction` exactly, while the legacy implicit root-`AGENTS.md` rule remains accepted.
|
|
176
|
+
|
|
177
|
+
### Fixed
|
|
178
|
+
|
|
179
|
+
- The Multica deployment load-smoke gate no longer misjudges the platform's constrained Issue-Adapter receipts as arbitrary Shell. It accepts the combined here-doc write/comment/cleanup control-plane command only when content, filename and target Issue all match exactly, extracts the response evidence from that command, adds `result.md` to the approved result filenames (alongside `reply.md`/`result.json`), and allows `rm`/`rm -f` cleanup only for those three whitelisted files. DWS, network and any other Shell use still fail closed.
|
|
180
|
+
- Contract scenario 54's injected-timeout legs used a 1-second per-call provider budget, which a loaded machine could exhaust on an innocent preflight read (each fake-provider call spawns a Node process) before ever reaching the write the timeout was injected on — the pre-release `--full` run failed exactly this way while the isolated rerun passed. The runtime behaved correctly (read timeout → fail closed before any remote write); the eval budgets were raised to 4 seconds with the simulated hang raised to 8, and scenario 54's expectation texts in `evals.json` were reordered to match the runner's check order, which had drifted and mislabeled the failing assertion.
|
|
181
|
+
|
|
182
|
+
## 0.1.5-beta.2 - 2026-07-21
|
|
183
|
+
|
|
184
|
+
Multica native-Skill refactor and DingTalk IM context recovery (PR #9, #10). Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
|
185
|
+
|
|
186
|
+
### Changed
|
|
187
|
+
|
|
188
|
+
- Basic Behavior 0.11.10 makes DWS original-message recovery an executable priority gate: when the Host gives current actor/title/text/time but omits a rich-message href or quote, the Agent must run the bounded `chat search` → `message list` verification path before any local `find`/`glob`/`ls`; an empty workspace can no longer stand in for DingTalk IM evidence.
|
|
189
|
+
- Basic Behavior 0.11.9 closes DingTalk IM context recovery without coupling to a managed platform: when the Host projection is incomplete, DWS may recover the current conversation's raw Markdown href, file IDs and `quotedMessage`, but a title-based group candidate becomes trusted only after the current actor/text/time trigger is independently matched; ambiguous candidates fail closed.
|
|
190
|
+
- Basic Behavior 0.11.8 treats a stable DingTalk node URL/file ID in the current trusted message as the object to read: ordinary files are classified with `drive info`, downloaded read-only, and never replaced by Issue, workspace or old-task filename searches.
|
|
191
|
+
- Basic Behavior 0.11.7 makes previous-file recovery mandatory when a trusted conversation is readable: it resolves the recent IM fileId/dentryId/URL and reads that object directly instead of treating workspace, memory, knowledge or an old task's read list as conversation history.
|
|
192
|
+
- Basic Behavior 0.11.6 adds focused Chat-history enrichment: when the Host exposes a trusted ChatSession/conversation mapping, the Agent may use a bounded read-only DWS history window to resolve the current message's omitted referent or prior attachment, while the triggering message remains the only source of this Run's goal and authorization.
|
|
193
|
+
- Basic Behavior 0.11.5 turns a real Multica IM regression into a hard evidence-scope rule: a Run that lacks the previous quote/file projection may report only that Run-level gap, never claim the conversation did not receive the message; conversation-level absence requires an independent history readback.
|
|
194
|
+
- Basic Behavior 0.11.4 closes the IM file-read loop: a trusted URL/file ID is used directly, online docs use doc read, ordinary files use read-only drive download into the current task, and the Agent no longer asks for confirmation merely to perform that read.
|
|
195
|
+
- Basic Behavior now freezes the current Run's trusted time and rich-message projection before reasoning. Relative dates can no longer reuse a stale Session/UTC clock, and visible filenames, file IDs, URLs or quoted fields cannot be negated by an empty workspace scan or a missing content reader.
|
|
196
|
+
- Multica native Project Workspaces no longer require fake local memory/knowledge/artifacts routes; OpenCode Workspaces retain the complete semantic-storage gate.
|
|
197
|
+
- Multica Agent instructions are exactly the human-authored `AGENTS.md`. Definition/deployment hashes and the required Skill manifest remain in the deployment plan, operation and Receipt instead of being prepended to the System Prompt.
|
|
198
|
+
- Removed `dingtalk-agent-boot-multica`. Multica assigns only Basic and Role Skills, and the deployment Issue smoke directly asks the Host-native Skill tool to load that frozen set.
|
|
199
|
+
- Workspace inspection, platform registration, package contents and deterministic W4/W5 contracts enforce native Skill assignment and reject the obsolete Boot layer.
|
|
200
|
+
- Multica deploy 0.3.2 recovers exactly once when a persisted load-smoke Issue has no task after assignment. It posts one stable-ID Agent mention on that Issue only for the empty-run state and never duplicates an already queued, running, or terminal smoke task.
|
|
201
|
+
- Multica deploy load-smoke accepts the platform's two constrained result-file conventions, `reply.md` and `result.json`. Both remain fail-closed: the path must use an approved response filename without traversal, the payload must exactly match the marker and required Skill set, and any unapproved tool call still fails the gate.
|
|
202
|
+
- Eval 0.7.3 adds the managed Multica `workspace run` path, current DWS `list-direct` readback, capability-aware event-subscription fallback, and a required IM matrix for continuation, quote, file, document and correction cases.
|
|
203
|
+
- Compose 0.13.1 strengthens the readable Basic inheritance anchor: every task must load Basic through the Host-native Skill tool before analysis, reply, or Role Skill use. This introduces no Boot Skill or machine metadata in the System Prompt.
|
|
204
|
+
- `doctor.ready` now treats Claude Code/Codex/OpenCode discovery conflicts as client-specific observations rather than runtime blockers; canonical Skill absence, DWS/auth, CLI and Node failures remain fail-closed.
|
|
205
|
+
|
|
206
|
+
### Fixed
|
|
207
|
+
|
|
208
|
+
- Synced the robot-eval suite's `exact-basic-version` expectation to the canonical Basic Behavior version (0.11.8 → 0.11.10). Contract 43 asserts the load-probe version tracks `metadata.version`; the earlier Basic bumps left this fixture behind, so a full run failed until it was re-synced.
|
|
209
|
+
|
|
210
|
+
### Release boundary
|
|
211
|
+
|
|
212
|
+
- These changes require a new Multica deployment so existing Agents drop the old Boot assignment and receive the readable Definition. The first `dta deploy` after upgrade rewrites each managed Agent's System Prompt to the raw `AGENTS.md`, so it is a content update rather than a no-op.
|
|
213
|
+
|
|
5
214
|
## 0.1.5-beta.1 - 2026-07-20
|
|
6
215
|
|
|
7
216
|
Documentation and evaluation-tooling release. **No runtime code changes** — `bin/` and `src/` behavior is identical to 0.1.4; the only `bin/` edit is a header comment. Ships on the `beta` dist-tag; `latest` stays at 0.1.4.
|
package/README.en.md
CHANGED
|
@@ -2,26 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
# dingtalk-agent
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Let your coding agent turn an existing Agent into a DingTalk digital employee.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@xdxer/dingtalk-agent)
|
|
8
8
|
[](https://github.com/D1-2004/dingtalk-agent/actions/workflows/ci.yml)
|
|
9
9
|
[](https://nodejs.org/)
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
|
|
12
|
-
[
|
|
12
|
+
Evaluating? → [What it is](#what-it-is) · [What it does](#what-it-does) · [When to use it](#when-to-use-it) | Ready to build? → [Quick start](#quick-start)
|
|
13
13
|
|
|
14
14
|
[简体中文](README.md) · English
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+

|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## What it is
|
|
21
|
+
|
|
22
|
+
dta doesn't build the runtime substrate, but it owns the whole path of turning an Agent into a DingTalk digital employee.
|
|
23
|
+
|
|
24
|
+
What separates a digital employee from a chatbot is a DingTalk-issued organizational identity: it has a name in the directory, can be @-mentioned, works only in the groups and conversations it was authorized for, and everything it does is recorded under its name.
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
A working Agent still has to add a whole layer of engineering that has nothing to do with your business logic: identity and permissions, telling which message in a group is meant for it, not sending to the wrong person, and producing delivery evidence when it reports "done". Every new digital employee redoes all of that. dta turns it into a set of inheritable rules and one CLI that your coding agent installs and uses, so you don't have to study DingTalk's identity model, event model, and outbound limits yourself.
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
Works with: Claude Code · Codex · OpenCode · any coding agent | Managed platforms: Multica (supported) · DEAP (coming soon)
|
|
25
29
|
|
|
26
30
|
## Quick start
|
|
27
31
|
|
|
@@ -38,43 +42,24 @@ npm install --global --prefix "$HOME/.local" \
|
|
|
38
42
|
"$HOME/.local/bin/dta" doctor
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
`setup` installs the
|
|
42
|
-
|
|
43
|
-
**How far you get with nothing external**: composing, auditing, `workspace run/eval`, and the full contract suite need no DingTalk account and no managed platform — `doctor` marks what is missing as `partial` rather than failing. Only real outbound messaging, remote semantic state, and `deploy`/`promote` require DWS authentication and Multica.
|
|
44
|
-
|
|
45
|
-
## Why it exists
|
|
45
|
+
`setup` installs the shared-behavior, compose, and eval Skills, then checks DWS authentication and common Agent Hosts. Normal sessions do not require Workspace initialization.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
### Minimal runnable path
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
- **It stays in scope.** Identity, target, permission, authorization, and reply channel are never guessed from message text or model memory.
|
|
51
|
-
- **It does not overclaim.** Command success, platform visibility, message delivery, and human acceptance are four distinct completion levels, each evidenced separately.
|
|
52
|
-
- **It is reusable.** A new Agent inherits shared behavior and only adds role differences — no copied mega-prompt.
|
|
53
|
-
|
|
54
|
-
## What an Agent is made of
|
|
55
|
-
|
|
56
|
-
Four things: the **Definition** (`AGENTS.md` — who I am, where my duties stop), **shared behavior** (the `dingtalk-basic-behavior` Skill — when to respond, ask, stay silent, close out), **role capability** (`skills/<role>/SKILL.md`), and **storage routing** (`agent.bindings.json` — optional; the same configuration can come from host context, environment variables, or a Workspace manifest). The Agent Host, DWS, managed platform, and event source it depends on are all outside this project.
|
|
57
|
-
|
|
58
|
-
Full composition, dependencies, and boundaries: [Architecture](docs/ARCHITECTURE.md#2-一个-agent-由什么构成模型-a).
|
|
59
|
-
|
|
60
|
-
**File presence is not inheritance evidence** — `agent audit --verify-load` binds real load results to Definition/Skill hashes, Host and model versions, isolated probes, and raw run/export evidence:
|
|
49
|
+
Start with these three — no DingTalk account, no managed platform, and no side effects:
|
|
61
50
|
|
|
62
51
|
```bash
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
--verify-load --yes --json
|
|
52
|
+
cp -R examples/agents/release-manager my-agent && cd my-agent
|
|
53
|
+
dta bootstrap --json # Was the body recognized? Check definition.status and storage routes
|
|
54
|
+
dta agent audit --json # Expect partial — the role semantics are still template text, which is correct
|
|
67
55
|
```
|
|
68
56
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
**Behavior kernel** (event → may I respond, to whom, what am I allowed to do), **compose & audit** (turn a repo/folder/doc into a hashable Agent and prove the Skills really loaded), **delivery chain** (reach a managed platform under control, with readback at every step), **eval & evidence** (prove it works at the cheapest sufficient level before going live), **state & memory** (stay resumable after a crash), and **machine & distribution** (one command sets up a new machine).
|
|
57
|
+
`release-manager` is a complete sample of a release-manager digital employee: it picks up "can we ship this version?" in a group, checks the gates, summarizes the verdict, and requires human confirmation before moving on. Replace the role duties in `agent/AGENTS.md` with your own, run `agent audit` again, and the only gap left is the load probe — which needs an Agent Host, see the [Compose Skill](skills/core/dta-agent-compose/SKILL.md).
|
|
72
58
|
|
|
73
|
-
|
|
59
|
+
### Full delivery chain
|
|
74
60
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Each of the four stages has a gate: unfilled placeholders keep it `partial`; Skills that did not truly load cannot be ready; a missing named Eval blocks promote; nothing claims delivery or completion without evidence. Details: [Architecture](docs/ARCHITECTURE.md#8-从定义到上线).
|
|
61
|
+
<details>
|
|
62
|
+
<summary>The complete create → test → ship commands (worth reading once you have a managed platform binding)</summary>
|
|
78
63
|
|
|
79
64
|
```bash
|
|
80
65
|
# 1. Generate a zero-write plan, then commit it explicitly
|
|
@@ -84,8 +69,8 @@ dta agent enhance --project-name release-agent --role-skill release-manager \
|
|
|
84
69
|
|
|
85
70
|
# 2. Audit, run, and evaluate
|
|
86
71
|
dta agent audit --bindings agent.bindings.json --require-skill release-manager --json
|
|
87
|
-
dta workspace run local-dev --json
|
|
88
|
-
dta workspace eval local-dev --json
|
|
72
|
+
dta workspace run local-dev --prompt-file prompt.md --execute --yes --json
|
|
73
|
+
dta workspace eval local-dev --suite evals/suite.json --execute --yes --json
|
|
89
74
|
|
|
90
75
|
# 3. Cloud preflight, promotion, and observation
|
|
91
76
|
dta workspace inspect multica-dev --execute --yes --json
|
|
@@ -94,53 +79,100 @@ dta promote --source local-dev --target multica-dev --dry-run --json
|
|
|
94
79
|
dta observe --promotion-id <promotion-id> --input <observation.json> --dry-run --json
|
|
95
80
|
```
|
|
96
81
|
|
|
97
|
-
Plans are zero-write by default
|
|
82
|
+
Plans are zero-write by default; every remote write requires an explicit target, the current `planId`, and confirmation. `<plan-id>` comes from the preceding dry run's `.planId`; `local-dev` / `multica-dev` are Workspace names you declare in `dingtalk-agent.json#workspaces`. Each of the four stages has a gate: unfilled placeholders keep it `partial`; Skills that did not truly load cannot be ready; a missing named eval blocks promote; nothing claims delivery or completion without evidence. Details: [Architecture](docs/ARCHITECTURE.md#8-开发生命周期从定义到观测).
|
|
83
|
+
|
|
84
|
+
</details>
|
|
85
|
+
|
|
86
|
+
## What it does
|
|
87
|
+
|
|
88
|
+
Turning an Agent into a DingTalk digital employee takes six stages, and dta covers every one:
|
|
89
|
+
|
|
90
|
+
| Lifecycle stage | What dta does | With what |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| **① Body and employee skills** | An inheritable, verifiable shared behavior contract: when to speak, whether a message is even a task, who must approve an outbound action, how risk is graded, what counts as done, what to remember and forget. You write only the few dozen lines that differ by role | `dta-basic-behavior` · `agent enhance` · `examples/agents/` |
|
|
93
|
+
| **② Identity acquisition and event perception** | Normalize differently shaped raw events into a stable structure; freeze the reply target and execution identity into a snapshot message text cannot alter, making wrong-recipient structurally impossible; bind permissions and outbound ownership per field; one event yields exactly one Run, losing and duplicating nothing across crashes | `prepare` · `run` · Field config |
|
|
94
|
+
| **③ Managed-platform deployment** | See the plan before anything lands: frozen hashes for the body and the whole Skill tree plus a write budget; independent readback and a load smoke test after writing; re-running the same version writes nothing; failures roll back and shipped agents can be retired (today this lands on Multica) | `deploy` · `promote` · `--retire` |
|
|
95
|
+
| **④ Driving it to work inside DingTalk** | Outbound has only four atoms; before an action the gate blocks overreach and target drift, after it a platform readback is mandatory; no blind retries when the outcome is uncertain; a "done" report must carry re-verifiable evidence | `act` · Action Gate · `task checkpoint` |
|
|
96
|
+
| **⑤ Evaluation design** | Not a scoring tool but a method: how to pick the cheapest sufficient level, which evidence surfaces one verdict must collect, which failures may never be averaged away, how a real incident becomes a replayable case, and what blocks a release | `lab` · `workspace eval` · `dta-agent-eval` |
|
|
97
|
+
| **⑥ Observation and feedback** | Bind a production finding to the exact version that ran, desensitize it, and feed it back into evaluation material, without ever changing the Agent's behavior on its own | `observe` |
|
|
98
|
+
|
|
99
|
+
## When to use it
|
|
100
|
+
|
|
101
|
+
Use it when:
|
|
102
|
+
|
|
103
|
+
- you already have a working Agent and want it in DingTalk groups under an organizational identity, getting @-mentioned and assigned work;
|
|
104
|
+
- you run DingTalk automation and have been bitten by sending to the wrong person, or by exit code 0 being treated as success;
|
|
105
|
+
- you are building not one digital employee but a batch, and don't want shared behavior copied into several drifting prompts;
|
|
106
|
+
- your work spans days, waits for human confirmation, and can be called off midway — not one-shot Q&A;
|
|
107
|
+
- you need to prove to someone that what runs in production is the exact version you verified.
|
|
108
|
+
|
|
109
|
+
Skip it when:
|
|
110
|
+
|
|
111
|
+
- you just want a Q&A bot: one DingTalk robot webhook is enough, and this is overhead;
|
|
112
|
+
- you just want to call DingTalk APIs: use DWS directly — it already works, and dta is not a prerequisite;
|
|
113
|
+
- you are not on DingTalk: the only execution path is DWS and identity is issued by DingTalk, neither of which is swappable.
|
|
98
114
|
|
|
99
|
-
|
|
115
|
+
Not possible today: importing an Agent already deployed on another platform (data flows one way, local definition to managed platform, with no import command); triggers (webhooks, timers) are also out of scope.
|
|
100
116
|
|
|
101
|
-
|
|
117
|
+
## Where it stands today
|
|
118
|
+
|
|
119
|
+
| Area | Where it is |
|
|
102
120
|
|---|---|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
|
|
|
106
|
-
|
|
|
121
|
+
| First five of the six stages | In shape |
|
|
122
|
+
| Stage six (observation & metering) | The thinnest. Usage metering — interaction counts, tokens, cost, per-person/per-group breakdown — isn't built yet |
|
|
123
|
+
| Managed platform | Multica supported; DEAP coming soon; the platform SPI isn't merged into main yet |
|
|
124
|
+
| Agent Host | OpenCode complete; the Claude Code adapter isn't implemented |
|
|
125
|
+
| Completion evidence | The verify side is implemented and contract-locked; the issue side isn't wired to a public command |
|
|
126
|
+
| Importing an Agent from an external platform | No such command; data flows one way, local to platform |
|
|
127
|
+
| Regression net | 62 deterministic contracts, run in 18 seconds |
|
|
107
128
|
|
|
108
|
-
|
|
129
|
+
## How it works
|
|
109
130
|
|
|
110
|
-
|
|
131
|
+
> **Skills advise. The CLI gates. DWS acts.** Skills decide when and why to act; the CLI pins identity, target, budget, idempotency, and readback; DWS performs DingTalk capabilities.
|
|
111
132
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
These boundaries are structurally impossible to cross, not politely discouraged in a prompt: without an `@` in a group it stays silent; the CLI has no "send to" parameter, so the reply target can only come from the message that triggered it; a completion report must carry host-issued evidence that can be read back independently. All three are watched by deterministic contract evals — break them and the suite goes red.
|
|
134
|
+
|
|
135
|
+
**DWS is DingTalk's own command-line tool** (separate from this project, with its own `dws auth login`), covering roughly 20 product areas: messaging, docs, AI tables, calendar, approvals, and more. dta does not clone its command surface; every real DingTalk operation is ultimately executed by DWS.
|
|
136
|
+
|
|
137
|
+
## FAQ
|
|
138
|
+
|
|
139
|
+
**Is this yet another Agent framework?**
|
|
140
|
+
No. It provides no model, no tool loop, and no agent runtime. It gives your coding agent a set of Skills and one CLI to compose an existing Agent into a DingTalk digital employee.
|
|
117
141
|
|
|
118
|
-
|
|
142
|
+
**Does it conflict with Claude Code or Codex?**
|
|
143
|
+
No — it is built for them. `dta setup` installs the Skills into these coding agents; after that you instruct them in natural language. The CLI also works standalone.
|
|
144
|
+
|
|
145
|
+
**My Agent already runs on another platform — can I bring it in?**
|
|
146
|
+
The body (role definition and Skills) is portable: compose locally, then ship to a managed platform. But there is no command today that imports from an external platform, and Multica is the only managed platform supported.
|
|
147
|
+
|
|
148
|
+
**What do I need to try it once?**
|
|
149
|
+
No DingTalk account and no managed platform. Composing, auditing, `workspace run/eval`, and the full contract suite all run locally; `doctor` marks what's missing as `partial` instead of failing. Only real outbound messaging and shipping need DWS authentication.
|
|
150
|
+
|
|
151
|
+
**How much effort does it take?**
|
|
152
|
+
The main work of the first role is writing the role duties clearly, not writing code: the body is Markdown, and you edit from the examples. Adding a second role changes three files and zero kernel code.
|
|
119
153
|
|
|
120
154
|
## Support
|
|
121
155
|
|
|
122
|
-
A
|
|
156
|
+
A managed platform, an Agent Host, and the dta kernel are three separate things: the managed platform owns Workspace, Runtime, and observation, and binds a DingTalk-issued identity to the Agent (issuance stays with DingTalk); the Agent Host (a.k.a. Harness) loads definitions and Skills and isolates execution; the dta kernel is this project.
|
|
123
157
|
|
|
124
158
|
| Dimension | Current support |
|
|
125
159
|
|---|---|
|
|
126
|
-
| **Managed
|
|
127
|
-
| **Local runtime** | Direct/Mounted sessions in Claude Code, Codex, OpenCode, and similar Hosts; OpenCode is the most complete local
|
|
128
|
-
| **Cloud runtime** | Multica Workspace / Runtime / Agent with the same
|
|
129
|
-
| **Delivery identity** | Digital-employee/account identity or robot-app identity; neither
|
|
160
|
+
| **Managed platform** | Multica (DingTalk) supported; DEAP coming soon; onboarding a new platform takes the same path: author a platform Skill pack and register one entry |
|
|
161
|
+
| **Local runtime** | Direct/Mounted sessions in Claude Code, Codex, OpenCode, and similar Hosts; OpenCode is the most complete local reference |
|
|
162
|
+
| **Cloud runtime** | Multica Workspace / Runtime / Agent with the same definitions, Skills, gates, and evidence contract |
|
|
163
|
+
| **Delivery identity** | Digital-employee/account identity or robot-app identity, both issued by DingTalk; neither changes the role's duties or expands its authority |
|
|
130
164
|
|
|
131
|
-
|
|
165
|
+
DEAP may play two roles at once: its most important value to this project today is DingTalk-side identity/authorization and perception/human-interaction; whether it also embeds a runtime platform of its own is not yet settled. See the [DEAP platform note](skills/platforms/deap/PLATFORM.md). "Multi-platform" means the registry and onboarding contract are extensible; it does not claim that unopened platforms are deployed or Live-verified.
|
|
132
166
|
|
|
133
167
|
### Runtime modes
|
|
134
168
|
|
|
135
169
|
| Mode | Use | Boundary |
|
|
136
170
|
|---|---|---|
|
|
137
171
|
| **Direct Session** | Normal interactive work | Never guess an outbound target without a trusted event |
|
|
138
|
-
| **Mounted Session** | Mount local or DingTalk semantic content | Locks, idempotency, and
|
|
172
|
+
| **Mounted Session** | Mount local or DingTalk semantic content | Locks, idempotency, and receipts do not live in Markdown |
|
|
139
173
|
| **Prepared Run** | Reliable event-driven side effects | Actions go only through the typed Broker or `dta act` |
|
|
140
174
|
|
|
141
|
-
Prepared Runs expose four message atoms: `ack`, `reply`, `ask`, and `silence`. An acknowledgement is not task acceptance, and a reply is not human acceptance.
|
|
142
|
-
|
|
143
|
-
**Triggers are out of scope for this project**: `listen` is a replaceable local integration Adapter, and `dta deploy` never creates robots, webhooks, or timers.
|
|
175
|
+
Prepared Runs expose four message atoms: `ack`, `reply`, `ask`, and `silence`. An acknowledgement is not task acceptance, and a reply is not human acceptance. Triggers are out of scope: `listen` is a replaceable local integration Adapter, and `dta deploy` never creates robots, webhooks, or timers.
|
|
144
176
|
|
|
145
177
|
## Docs
|
|
146
178
|
|
|
@@ -148,12 +180,13 @@ Prepared Runs expose four message atoms: `ack`, `reply`, `ask`, and `silence`. A
|
|
|
148
180
|
|---|---|
|
|
149
181
|
| Understand the Agent architecture and how the repo is divided | [Architecture](docs/ARCHITECTURE.md) |
|
|
150
182
|
| Install, upgrade, or troubleshoot | [Installation](docs/INSTALLATION.md) |
|
|
183
|
+
| Take over an agent already running in production (runtime view) | [Agent in Production](docs/AGENT-IN-PRODUCTION.md) |
|
|
151
184
|
| Understand evaluation and evidence levels | [Self-test](docs/SELF-TEST.md) |
|
|
152
|
-
| Create or audit an Agent | [Compose Skill](skills/core/
|
|
153
|
-
| Test or debug a delivered Agent | [Eval Skill](skills/core/
|
|
154
|
-
| Read the shared behavior protocol (a contract written for models, not a tutorial) | [Basic Behavior Skill](skills/core/
|
|
185
|
+
| Create or audit an Agent | [Compose Skill](skills/core/dta-agent-compose/SKILL.md) |
|
|
186
|
+
| Test or debug a delivered Agent | [Eval Skill](skills/core/dta-agent-eval/SKILL.md) |
|
|
187
|
+
| Read the shared behavior protocol (a contract written for models, not a tutorial) | [Basic Behavior Skill](skills/core/dta-basic-behavior/SKILL.md) |
|
|
155
188
|
| Copy a complete example and edit from there | [Example Agents](examples/agents) |
|
|
156
|
-
|
|
|
189
|
+
| Which platforms and open-source projects we keep absorbing practices from | [Prior Art](docs/PRIOR-ART.md) |
|
|
157
190
|
|
|
158
191
|
Behavior assets come from observable contracts, counterexample-driven revision, and deployable verification. This project does not claim access to any product's hidden system prompt.
|
|
159
192
|
|