@llodev/pm-tasks-asana 0.0.0-pr-22-9002a06
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 +282 -0
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/SKILL.md +198 -0
- package/anti-patterns/asana.md +62 -0
- package/dist/adapter.d.ts +19 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +18 -0
- package/dist/adapter.js.map +1 -0
- package/dist/bin/init.d.ts +3 -0
- package/dist/bin/init.d.ts.map +1 -0
- package/dist/bin/init.js +280 -0
- package/dist/bin/init.js.map +1 -0
- package/dist/doctor-cli.d.ts +6 -0
- package/dist/doctor-cli.d.ts.map +1 -0
- package/dist/doctor-cli.js +166 -0
- package/dist/doctor-cli.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/transport-asana.d.ts +44 -0
- package/dist/transport-asana.d.ts.map +1 -0
- package/dist/transport-asana.js +254 -0
- package/dist/transport-asana.js.map +1 -0
- package/docs/i18n/README.es-ES.md +100 -0
- package/docs/i18n/README.pt-BR.md +100 -0
- package/i18n/en-US.json +24 -0
- package/i18n/es-ES.json +24 -0
- package/i18n/pt-BR.json +24 -0
- package/manifest.json +12 -0
- package/package.json +67 -0
- package/references/operations.md +62 -0
- package/schemas/config.json +173 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# @llodev/pm-tasks-asana
|
|
2
|
+
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#20](https://github.com/llodev/skills/pull/20) [`78106ab`](https://github.com/llodev/skills/commit/78106ab42ed317ba865906d25701ade4532396ec) Thanks [@lloliveiradev](https://github.com/lloliveiradev)! - **pm-tasks v1.9.0 — Headless runtime + Plan-execution mode (Option E)**
|
|
8
|
+
|
|
9
|
+
Three coordinated minor bumps shipping the agent-agnostic headless runtime
|
|
10
|
+
and the F15 plan-execution mode. Skill-driven flows are unchanged; this
|
|
11
|
+
release adds a programmatic entry point and a new mode the calling agent
|
|
12
|
+
can opt into when it has a plan file to execute.
|
|
13
|
+
|
|
14
|
+
**`@llodev/pm-tasks-core@1.8.0 → 1.9.0`** (minor)
|
|
15
|
+
|
|
16
|
+
- New: `@llodev/pm-tasks-core/runtime` subpath exposes `createCoreRuntime`,
|
|
17
|
+
the `Transport` interface, 7 verb handlers, `RuntimeContext`, and the
|
|
18
|
+
full set of request/response types. Pure: no MCP imports, no transport
|
|
19
|
+
implementation — adapters provide the wiring.
|
|
20
|
+
- New: `@llodev/pm-tasks-core/plan-execution` module exports
|
|
21
|
+
`requireConfig` + `ConfigRequiredError`, `discoverPlanTasks` +
|
|
22
|
+
`resolvePlanRef` + `parseH3Titles` + `filenameToSlug` (discovery
|
|
23
|
+
helpers — `PlanRef` accepts `string[]` titles, a `.md` path with H3
|
|
24
|
+
parsing, or a bare slug), `onTaskStart` + `onTaskComplete` (boundary
|
|
25
|
+
hooks with best-effort dispatch, `ALREADY_IN_STATE` → skipped
|
|
26
|
+
classification, process-local idempotency memo keyed by
|
|
27
|
+
`${taskId}|${commitSha}`), and `__resetHookCacheForTests` (test escape
|
|
28
|
+
hatch).
|
|
29
|
+
- New: `pm-tasks-core/references/plan-execution.md` documents the full
|
|
30
|
+
contract (triggers, discovery semantics, hook classification table,
|
|
31
|
+
failure modes, `ConfigRequiredError` shape).
|
|
32
|
+
- New: `pm-tasks-core/references/agent-agnostic-lint.md` + a stand-alone
|
|
33
|
+
`scripts/checks/agent-agnostic-lint.mjs` that bans `superpowers`,
|
|
34
|
+
`sdd`, `Claude Code`, `Claude-only`, `Claude assumes` in SKILL body
|
|
35
|
+
content while allowlisting `claude-code` in `compatibility.agents`
|
|
36
|
+
frontmatter, vendor product names (`claude.ai Asana`,
|
|
37
|
+
`claude-ai-asana-mcp`), and other context-aware exemptions.
|
|
38
|
+
- Internal: tarball size budget raised 14.1 → 18.5 kB across Phase 4
|
|
39
|
+
and Phase 5 (covering the plan-execution module + hook helpers + full
|
|
40
|
+
JSDoc on every exported symbol).
|
|
41
|
+
|
|
42
|
+
**`@llodev/pm-tasks-asana@1.5.0 → 1.6.0`** (minor)
|
|
43
|
+
|
|
44
|
+
- New: `@llodev/pm-tasks-asana/adapter` subpath exposes
|
|
45
|
+
`createAdapter({ configPath, mcp, session?, language? })` returning a
|
|
46
|
+
`Runtime`. The `mcp: McpCaller` callback is the caller's only
|
|
47
|
+
obligation — receives a fully-qualified `mcp__claude_ai_Asana__*` tool
|
|
48
|
+
name + args object, returns the MCP server's raw response.
|
|
49
|
+
- New: `pm-tasks-asana/src/transport-asana.ts` implements the
|
|
50
|
+
`Transport` interface against `mcp__claude_ai_Asana__*` tools.
|
|
51
|
+
Asana-specific deltas: `closeListOrSectionId` ignored at the transport
|
|
52
|
+
layer (Asana has no list-on-close concept), ISO-8601 → `YYYY-MM-DD`
|
|
53
|
+
conversion via `isoToDueOn` helper for `taskDueDateSet`,
|
|
54
|
+
`INVALID_REQUEST` short-circuit BEFORE the MCP call on malformed
|
|
55
|
+
`dueAt`, single-assignee model for `taskAssigneeAdd`.
|
|
56
|
+
- SKILL.md routing table gained a Plan-execution row; Phase 7 narrative
|
|
57
|
+
section forward-references the new `references/plan-execution.md`
|
|
58
|
+
doc in `pm-tasks-core`.
|
|
59
|
+
|
|
60
|
+
**`@llodev/pm-tasks-trello@1.5.0 → 1.6.0`** (minor)
|
|
61
|
+
|
|
62
|
+
- New: `@llodev/pm-tasks-trello/adapter` subpath exposes
|
|
63
|
+
`createAdapter({ configPath, mcp, session?, language? })` returning a
|
|
64
|
+
`Runtime`. Same shape and contract as the Asana adapter.
|
|
65
|
+
- New: `pm-tasks-trello/src/transport-trello.ts` implements the
|
|
66
|
+
`Transport` interface against `mcp__trello__*` tools. Trello-specific
|
|
67
|
+
behavior: `taskClose` archives the card AND optionally moves it to
|
|
68
|
+
`closeListOrSectionId` when provided (Trello's "Done" list pattern).
|
|
69
|
+
- SKILL.md routing table gained a Plan-execution row mirroring the
|
|
70
|
+
Asana adapter; identical Phase 7 narrative section.
|
|
71
|
+
|
|
72
|
+
**Skill-judge gate**
|
|
73
|
+
|
|
74
|
+
Modified `pm-tasks-asana/SKILL.md` and `pm-tasks-trello/SKILL.md`
|
|
75
|
+
(Phase 4.3) added the Plan-execution mode routing row + Phase 7 section.
|
|
76
|
+
Measured drift sits within the documented noise band ([-2, +2]); the
|
|
77
|
+
agent-agnostic-lint rule shipped in this release codifies the
|
|
78
|
+
allowlist that earlier scoring assumed. If drift is within tolerance,
|
|
79
|
+
bypass with `SKIP_SKILL_JUDGE_GATE=1 make release-version`.
|
|
80
|
+
|
|
81
|
+
**Breaking changes**
|
|
82
|
+
|
|
83
|
+
None. All Phase 1-5 additions are pure surface area additions:
|
|
84
|
+
|
|
85
|
+
- `/runtime` and `/adapter` subpaths are NEW exports (no prior consumers)
|
|
86
|
+
- `/plan-execution` helpers are NEW exports
|
|
87
|
+
- Existing skill-driven flows + the 7-verb CRUD contract on the autonomous
|
|
88
|
+
path are unchanged
|
|
89
|
+
|
|
90
|
+
**Migration**
|
|
91
|
+
|
|
92
|
+
No migration needed. Existing consumers continue to import from the
|
|
93
|
+
package root. New code can opt into the runtime by importing from
|
|
94
|
+
`@llodev/pm-tasks-{trello,asana}/adapter` or the helpers from
|
|
95
|
+
`@llodev/pm-tasks-core/runtime` and `@llodev/pm-tasks-core/plan-execution`.
|
|
96
|
+
|
|
97
|
+
### Patch Changes
|
|
98
|
+
|
|
99
|
+
- Updated dependencies [[`78106ab`](https://github.com/llodev/skills/commit/78106ab42ed317ba865906d25701ade4532396ec)]:
|
|
100
|
+
- @llodev/pm-tasks-core@1.9.0
|
|
101
|
+
|
|
102
|
+
## 1.5.0
|
|
103
|
+
|
|
104
|
+
### Minor Changes
|
|
105
|
+
|
|
106
|
+
- 1200b4e: v1.8.0 — Observability v1. pm-tasks-core-doctor CLI validates workspace config / autonomous allowlist / audit writability / (when probes are injected) MCP & network reach BEFORE the first publish attempt fails noisily. Adapter init bins expose `--doctor` for per-tool checks (C-TRL-1..3 + C-ASN-1..3, gated by auth env). Smart audit-log rotation (size + age + multi-tool, atomic, idempotent, gzipped archives, keep-N) replaces the rudimentary shell script; new `rotate-audit.mjs` CLI emits structured JSON status. Pre-release gate now blocks on doctor errors. Closes roadmap §2.4 O1 + O3.
|
|
107
|
+
|
|
108
|
+
### Patch Changes
|
|
109
|
+
|
|
110
|
+
- Updated dependencies [1200b4e]
|
|
111
|
+
- @llodev/pm-tasks-core@1.8.0
|
|
112
|
+
|
|
113
|
+
## 1.4.0
|
|
114
|
+
|
|
115
|
+
### Minor Changes
|
|
116
|
+
|
|
117
|
+
- v1.5.0 — Adapters TypeScript migration, @llodev/pm-tasks-testkit, 7th canonical verb `task.move`, E2E canary.
|
|
118
|
+
|
|
119
|
+
**Core (`@llodev/pm-tasks-core` 1.4.0 → 1.5.0)** — adds the 7th canonical verb `task.move` to the public contract.
|
|
120
|
+
|
|
121
|
+
- New verb `task.move({ cardId, targetList })` formalizes the WIP transition that the autonomous-mode lifecycle has always required but no canonical verb expressed. `targetList` accepts the enum `"open" | "wip" | "done"` plus raw list IDs.
|
|
122
|
+
- `task.move` is INDEPENDENT of `task.close`: move only repositions, close moves AND sets the completion flag. Useful in adapters where the visual transition and the closed-flag are separate operations (Asana section change vs. `completed: true`).
|
|
123
|
+
- Schema regex updated to recognize `task.move` as canonical (no namespace prefix required).
|
|
124
|
+
- `pm-tasks-core/schemas/adapter-manifest.schema.json` + `references/contract.md` + `references/crud-vocabulary.md` + `references/autonomous-mode.md` updated.
|
|
125
|
+
- Contract-check (`scripts/checks/contract-check.mjs`) `CANONICAL_VERBS` Set updated; regression test added.
|
|
126
|
+
- Additive only — existing consumers calling the original 6 verbs continue to work unchanged.
|
|
127
|
+
|
|
128
|
+
**Adapters (`@llodev/pm-tasks-asana` 1.3.1 → 1.4.0, `@llodev/pm-tasks-trello` 1.3.1 → 1.4.0)** — full TypeScript migration mirroring core's v1.4.0 pattern.
|
|
129
|
+
|
|
130
|
+
- Source moved from `scripts/init.mjs` to `src/bin/init.ts` (strict TS).
|
|
131
|
+
- Build pipeline: `tsc` produces `dist/bin/init.{js,d.ts,js.map,d.ts.map}`. `dist/bin/init.js` is `chmod +x` so the bin works on install.
|
|
132
|
+
- `package.json` exports map points at compiled `dist/`; `bin` field exposes `npx @llodev/pm-tasks-<tool> init`.
|
|
133
|
+
- i18n parity tests migrated from `node:test` to Vitest 2.x (2/2 tests per adapter).
|
|
134
|
+
- Both adapters now declare `task.move` in their `manifest.json` `verbs` array (7 canonical verbs) and document the MCP mapping in `references/operations.md`:
|
|
135
|
+
- Trello: `mcp__trello__move_card({ cardId, idList })` resolving `"wip"`/`"done"`/`"open"` from `lists.<alias>` in `.trello.json`.
|
|
136
|
+
- Asana: `mcp__claude_ai_Asana__update_tasks` with `memberships: [{ project, section }]` resolving via `defaults.<state>SectionAlias` in `.asana.json`.
|
|
137
|
+
- Trello autonomous overlay (`pm-tasks-trello/references/autonomous.md`) updated to invoke canonical `task.move` at task start and before task close.
|
|
138
|
+
- Backwards compatibility: consumers keep importing `@llodev/pm-tasks-core/init-lib` via the subpath; resolution now hits the v1.5.0 dist.
|
|
139
|
+
|
|
140
|
+
**Testkit (`@llodev/pm-tasks-testkit` 0.0.0 → 0.1.0)** — new package, first release.
|
|
141
|
+
|
|
142
|
+
- Pure TypeScript library. 7 in-memory fakes covering every canonical verb: `task.create`, `task.move`, `task.close`, `task.comment.add`, `task.due-date.set`, `task.assignee.add`, `checklist.check`.
|
|
143
|
+
- `createFakeAdapter({ idGenerator?, clock? })` returns an adapter-shaped object with all 7 verbs plus introspection (`getTask`, `getAllTasks`, `reset`).
|
|
144
|
+
- `peerDependencies`: `@llodev/pm-tasks-core ^1.4.0`.
|
|
145
|
+
- Useful for testing custom skills/adapters without hitting real MCP servers; 14/14 vitest tests cover each fake's behavior and idempotency.
|
|
146
|
+
|
|
147
|
+
**Pipeline hardening — E2E canary** — `scripts/checks/canary-e2e.mjs` packs all 4 packages, npm-installs them in a clean sandbox, and exercises core/asana/trello/testkit smoke checks. Wired into `make e2e`, a new `.github/workflows/e2e.yml` (PR + manual dispatch), and as a gate in `release.yml`. Runs in ~3.4 s; catches tarball drift the snapshot test alone misses.
|
|
148
|
+
|
|
149
|
+
**Skill-judge:** non-functional change (TS migration of adapter source + additive task.move documentation in SKILL.md verb lists). Expect Δ ≈ 0; ratchet baseline with updated `capturedAt` per v1.5.0 release per NOISE_BAND policy.
|
|
150
|
+
|
|
151
|
+
### Patch Changes
|
|
152
|
+
|
|
153
|
+
- Updated dependencies []:
|
|
154
|
+
- @llodev/pm-tasks-core@1.5.0
|
|
155
|
+
|
|
156
|
+
## 1.3.1
|
|
157
|
+
|
|
158
|
+
### Patch Changes
|
|
159
|
+
|
|
160
|
+
- chore: reorganize repo structure
|
|
161
|
+
|
|
162
|
+
Pure chore release. Zero runtime change. Splits across:
|
|
163
|
+
|
|
164
|
+
- Reorganized root `scripts/` into `checks/`, `snapshots/`, `shell/` subfolders.
|
|
165
|
+
- Dropped `SKILL.{pt-BR,es-ES}.md` translations (agents read canonical EN-only per agentskills.io spec).
|
|
166
|
+
- Moved localized READMEs to `docs/i18n/` in root + each package (anticipates 5+ locales without cluttering package roots).
|
|
167
|
+
- Updated validators (`validate-localized-paths.mjs`) and tarball snapshot for new paths.
|
|
168
|
+
|
|
169
|
+
Skill-judge: bypassed with `SKIP_SKILL_JUDGE_GATE=1` — only SKILL.md change was decorative readme-selector block removal; expected delta = 0 (cosmetic-only). Per NOISE_BAND policy [-2, +2] bypass allowed.
|
|
170
|
+
|
|
171
|
+
Meta package `@llodev/pm-tasks` not bumped — no tarball content changes, only peerDeps inheritance.
|
|
172
|
+
|
|
173
|
+
- Updated dependencies []:
|
|
174
|
+
- @llodev/pm-tasks-core@1.3.2
|
|
175
|
+
|
|
176
|
+
## 1.3.0
|
|
177
|
+
|
|
178
|
+
### Minor Changes
|
|
179
|
+
|
|
180
|
+
- Introduce adapter `manifest.json` + custom-verbs extension API. Each adapter now declares which canonical verbs it implements plus any tool-specific verbs under a `<tool>.*` namespace. `contract-check.mjs` validates the manifest against `adapter-manifest.schema.json`, enforces the `<tool>.<verb>` namespace prefix, and cross-checks each declared verb against the adapter's `SKILL.md`. The same gate now permits additive-only changes to `contract.md` as non-major (deletions still require major). No runtime behaviour changes for existing consumers.
|
|
181
|
+
|
|
182
|
+
### Patch Changes
|
|
183
|
+
|
|
184
|
+
- Updated dependencies []:
|
|
185
|
+
- @llodev/pm-tasks-core@1.3.0
|
|
186
|
+
|
|
187
|
+
## 1.2.1
|
|
188
|
+
|
|
189
|
+
### Patch Changes
|
|
190
|
+
|
|
191
|
+
- [`9f14fe0`](https://github.com/llodev/skills/commit/9f14fe099d8e44fdc01aeb96cdde24aa4fa14527) - CI: release workflow now runs `validate` + `contract:check` + `pre-release` (skill-judge gate) before publish, and a new `scripts/tarball-snapshot.test.mjs` (wired into `pnpm validate`) detects regressions in each package's `files` field. npm publishes use `NPM_CONFIG_PROVENANCE=true` for supply-chain attestation (requires `id-token: write` permission in the workflow). No runtime changes.
|
|
192
|
+
|
|
193
|
+
- Updated dependencies [[`9f14fe0`](https://github.com/llodev/skills/commit/9f14fe099d8e44fdc01aeb96cdde24aa4fa14527)]:
|
|
194
|
+
- @llodev/pm-tasks-core@1.2.1
|
|
195
|
+
|
|
196
|
+
## 1.2.0
|
|
197
|
+
|
|
198
|
+
### Minor Changes
|
|
199
|
+
|
|
200
|
+
- [`d8da409`](https://github.com/llodev/skills/commit/d8da409a0a08a481264f8bf64e7bf6a501a16793) - Add opt-in runtime attribution: agents can now stamp `commentPrefix`,
|
|
201
|
+
`autonomousCommentPrefix` and `descriptionFooter` on every `task.create` and
|
|
202
|
+
`task.comment.add`, with strings sourced from `pm-tasks-core/i18n` — fully
|
|
203
|
+
locale-aware. Disabled by default; enable via `attribution.enabled: true` in
|
|
204
|
+
config.json. Closes the v1.0 "Phase C" design item that was deferred from v1.1.
|
|
205
|
+
|
|
206
|
+
Skill-judge gate: measured drift is within the documented noise band
|
|
207
|
+
([-2, +2]). Asana: 83 → 84 (Δ +1). Trello: 80 → 81 (Δ +1). No baseline
|
|
208
|
+
ratchet required; gate bypassed via `SKIP_SKILL_JUDGE_GATE=1`.
|
|
209
|
+
|
|
210
|
+
### Patch Changes
|
|
211
|
+
|
|
212
|
+
- Updated dependencies [[`d8da409`](https://github.com/llodev/skills/commit/d8da409a0a08a481264f8bf64e7bf6a501a16793)]:
|
|
213
|
+
- @llodev/pm-tasks-core@1.2.0
|
|
214
|
+
|
|
215
|
+
## 1.1.2
|
|
216
|
+
|
|
217
|
+
### Patch Changes
|
|
218
|
+
|
|
219
|
+
- Document recurring gotchas observed during v1.0.x dogfood: Asana subtasks not inheriting custom fields, MCP `get_task` missing activity stories (UI is the source of truth), Trello query-string concat bug class, `create_card` ignoring `idMembers`, and `add_member_to_card` false-error returns.
|
|
220
|
+
|
|
221
|
+
## 1.1.1
|
|
222
|
+
|
|
223
|
+
### Patch Changes
|
|
224
|
+
|
|
225
|
+
- Ship pt-BR and es-ES translations of SKILL.md and README.md alongside the existing English originals. Adapters keep en-US as the canonical version; localized files follow the `<basename>.<lang-code>.md` convention. The package tarballs now include the localized files via the `files` field.
|
|
226
|
+
|
|
227
|
+
- Updated dependencies []:
|
|
228
|
+
- @llodev/pm-tasks-core@1.1.1
|
|
229
|
+
|
|
230
|
+
## 1.1.0
|
|
231
|
+
|
|
232
|
+
### Minor Changes
|
|
233
|
+
|
|
234
|
+
- Localize init prompts in en-US, pt-BR, es-ES. The first prompt of `npx @llodev/pm-tasks-{asana,trello} init` is now a language picker, and every subsequent prompt is rendered in the chosen locale. The selected locale is recorded as `locale` at the root of the config JSON. New helpers in `@llodev/pm-tasks-core/init-lib`: `promptLocale`, `loadStrings`, `interpolate`, `listLocales`, `registerI18nRoot`. JSON Schemas updated to accept `locale` as an enum. No breaking changes — existing configs without `locale` continue to validate and adapters keep emitting en-US prompts if the strings table is omitted.
|
|
235
|
+
|
|
236
|
+
### Patch Changes
|
|
237
|
+
|
|
238
|
+
- Updated dependencies []:
|
|
239
|
+
- @llodev/pm-tasks-core@1.1.0
|
|
240
|
+
|
|
241
|
+
## 1.0.2
|
|
242
|
+
|
|
243
|
+
### Patch Changes
|
|
244
|
+
|
|
245
|
+
- Allow `defaults.escalateToAlias` (and `defaults.assigneeAlias` on Trello) in the config schemas. The v1.0.1 init scripts emit these keys, but the JSON Schemas still had `additionalProperties: false` rejecting them — making `npx @llodev/pm-tasks-{asana,trello} init` fail at the validate step with "must NOT have additional properties". Trello init also now emits `assigneeAlias: "me"` for parity with Asana.
|
|
246
|
+
|
|
247
|
+
## 1.0.1
|
|
248
|
+
|
|
249
|
+
### Patch Changes
|
|
250
|
+
|
|
251
|
+
- Fix `npx @llodev/pm-tasks-asana init` silently doing nothing. Two bugs collapsed the init flow: (a) the `bin` entry was named `pm-tasks-asana-init` (not matching the package name), so npx never resolved the binary; (b) the script's `import.meta.url === file://${process.argv[1]}` guard failed under npx's symlinked bin shim, so even when invoked the `run()` entry-point was skipped. The bin is now `pm-tasks-asana` and the entry-point runs unconditionally.
|
|
252
|
+
- Cross-platform global config path. The init prompt now honors `LLODEV_PM_TASKS_CONFIG_HOME` first, then `XDG_CONFIG_HOME` (macOS/Linux), then `%APPDATA%` (Windows), then `~/.config` as the last fallback. The prompt prints the absolute path before asking, so the destination is always visible.
|
|
253
|
+
- Slug aliases are now Unicode-aware (via `@llodev/pm-tasks-core@1.0.1`): `"Em execução"` → `"em-execucao"`, `"Média"` → `"media"` (was `"em-execu-o"` / `"m-dia"`).
|
|
254
|
+
- Drop the language-specific regex for inferring the "closed" section. The init now explicitly asks: "Which section is the default for newly-created tasks?" and "Which section means 'closed / done'?" with sensible defaults (first / last picked) and a skip option.
|
|
255
|
+
- Add an explicit escalation prompt. After the member list is collected, the init asks: "Pick the escalation contact (will receive escalation comments + add_member on critical cards)" and stores it as `defaults.escalateToAlias`. The chosen member is re-aliased to `"owner"` if no other member already holds that alias.
|
|
256
|
+
- Fallback for empty membership lists: if the PAT's scope didn't return any project members beyond `me`, the init now offers a manual entry (gid + name + alias) so single-collaborator projects can still wire an escalation contact.
|
|
257
|
+
- `multiSelect`: empty input now means "select all" instead of "select none".
|
|
258
|
+
- README clarifies the per-OS defaults and the env override.
|
|
259
|
+
|
|
260
|
+
## 1.0.0
|
|
261
|
+
|
|
262
|
+
### Major Changes
|
|
263
|
+
|
|
264
|
+
- [`a571ab1`](https://github.com/llodev/skills/commit/a571ab1537ea7d3fe61c7b89c5be0f08d01f3838) - First stable release of the pm-tasks-\* family.
|
|
265
|
+
|
|
266
|
+
- `@llodev/pm-tasks-core` — Phases 1–3 extraction pipeline (input → sections → generic card), 6 CRUD verbs (`task.create`, `checklist.check`, `task.close`, `task.due-date.set`, `task.assignee.add`, `task.comment.add`), autonomous-mode contract (allowlist + scope + rate-limit + audit log), shared init UX library.
|
|
267
|
+
- `@llodev/pm-tasks-trello` — Trello adapter on the canonical generic card. Paste-friendly output, MCP-driven publish, autonomous mode against a board allowlist.
|
|
268
|
+
- `@llodev/pm-tasks-asana` — Asana adapter with workspace/project/section + custom-field + subtask-inheritance support. Paste, MCP-driven publish, autonomous mode.
|
|
269
|
+
|
|
270
|
+
Architecture, contract, and CRUD vocabulary documented in `docs/specs/2026-06-11-pm-tasks-design.md` and `docs/plans/2026-06-11-pm-tasks-v1.md`.
|
|
271
|
+
|
|
272
|
+
### Patch Changes
|
|
273
|
+
|
|
274
|
+
- Updated dependencies [[`a571ab1`](https://github.com/llodev/skills/commit/a571ab1537ea7d3fe61c7b89c5be0f08d01f3838)]:
|
|
275
|
+
- @llodev/pm-tasks-core@1.0.0
|
|
276
|
+
|
|
277
|
+
## 0.1.0 (unreleased)
|
|
278
|
+
|
|
279
|
+
- Initial extraction from `plan-to-task-cards` Phase 5b (Asana).
|
|
280
|
+
- 6 CRUD verbs (create, checklist.check, close, due-date.set, assignee.add, comment.add).
|
|
281
|
+
- Parent task + subtasks model with custom-field inheritance.
|
|
282
|
+
- Autonomous mode behind `[autonomous]` sentinel + allowlist.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LLDev Information Solutions
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!-- readme-selector:start -->
|
|
2
|
+
<p align="center">
|
|
3
|
+
<a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/README.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/usa.svg" width="30" alt="English"></a>
|
|
4
|
+
<a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/docs/i18n/README.pt-BR.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/brazil.svg" width="30" alt="Português"></a>
|
|
5
|
+
<a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/docs/i18n/README.es-ES.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/spain.svg" width="30" alt="Español"></a>
|
|
6
|
+
</p>
|
|
7
|
+
<!-- readme-selector:end -->
|
|
8
|
+
|
|
9
|
+
# @llodev/pm-tasks-asana
|
|
10
|
+
|
|
11
|
+
> Asana adapter for the `@llodev/pm-tasks-*` family — turn implementation plans into Asana parent tasks + subtasks and operate them via paste, MCP publish, or autonomous write-through.
|
|
12
|
+
|
|
13
|
+
[](https://www.npmjs.com/package/@llodev/pm-tasks-asana)
|
|
14
|
+
[](LICENSE)
|
|
15
|
+
[](https://nodejs.org)
|
|
16
|
+
[](https://agentskills.io)
|
|
17
|
+
|
|
18
|
+
What you get:
|
|
19
|
+
|
|
20
|
+
- **Paste-ready output** — agent renders a generic card; you paste into Asana manually.
|
|
21
|
+
- **MCP publish** via the `claude.ai Asana` MCP server (OAuth, no PATs in JSON). Parent task + flat subtasks + custom fields + section placement in one batch.
|
|
22
|
+
- **CRUD operations** on existing tasks: `checklist.check`, `task.close`, `task.comment.add`, `task.due-date.set`, `task.assignee.add`.
|
|
23
|
+
- **Autonomous mode** — `[autonomous]` / `--auto` sentinel for write-through under allowlist + scope + rate limits. Multi-task loops mirror state to Asana in real time.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# npm (with skillpm or Claude Code marketplace)
|
|
29
|
+
npm i @llodev/pm-tasks-core @llodev/pm-tasks-asana
|
|
30
|
+
|
|
31
|
+
# Vercel CLI (install core manually too)
|
|
32
|
+
npx skills add llodev/skills/pm-tasks/pm-tasks-core
|
|
33
|
+
npx skills add llodev/skills/pm-tasks/pm-tasks-asana
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Setup the MCP
|
|
37
|
+
|
|
38
|
+
Asana uses OAuth via the `claude.ai Asana` MCP. If you've already connected your Asana account in Cursor or Claude Code settings, you're done.
|
|
39
|
+
|
|
40
|
+
For any MCP-capable agent (Claude Code, Cursor, Codex, Windsurf, Cline, Roo Code):
|
|
41
|
+
|
|
42
|
+
1. Open the agent's MCP settings.
|
|
43
|
+
2. Enable / register `claude.ai Asana` (or your agent's equivalent Asana MCP).
|
|
44
|
+
3. Approve the OAuth flow in your browser.
|
|
45
|
+
|
|
46
|
+
In Claude Code, verify with `claude mcp list` — `claude.ai Asana` should appear as authenticated.
|
|
47
|
+
|
|
48
|
+
## Setup the config
|
|
49
|
+
|
|
50
|
+
The `init` script runs **outside** the MCP, so it needs a Personal Access Token to enumerate your workspaces / projects / sections / custom fields. Generate one at https://app.asana.com/0/my-apps, then:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
export LLODEV_PM_TASKS_ASANA_PAT=...
|
|
54
|
+
npx @llodev/pm-tasks-asana init
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Walk through the prompts. Pick where the config should live:
|
|
58
|
+
|
|
59
|
+
- **local** → `./.asana.json` (recommended for project-scoped configs, can be committed).
|
|
60
|
+
- **global** → a platform default, customizable. Defaults:
|
|
61
|
+
- macOS / Linux (XDG): `$XDG_CONFIG_HOME/llodev/pm-tasks/asana.json`, falling back to `~/.config/llodev/pm-tasks/asana.json`.
|
|
62
|
+
- Windows: `%APPDATA%\llodev\pm-tasks\asana.json`.
|
|
63
|
+
- Override on any OS with `LLODEV_PM_TASKS_CONFIG_HOME=/your/path` — the file lands at `$LLODEV_PM_TASKS_CONFIG_HOME/asana.json`.
|
|
64
|
+
|
|
65
|
+
The `init` prompt prints the absolute path it will write to, so you always see exactly where the file goes.
|
|
66
|
+
|
|
67
|
+
> [!IMPORTANT]
|
|
68
|
+
> The PAT is **only** used by `init`. The MCP itself uses OAuth — never put tokens in the JSON.
|
|
69
|
+
|
|
70
|
+
## Use
|
|
71
|
+
|
|
72
|
+
| Prompt example | What the agent does |
|
|
73
|
+
| ---------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
74
|
+
| `"publish this plan as Asana tasks"` | Phase 5 publish — parent + subtasks + custom fields in one batch |
|
|
75
|
+
| `"check subtask 3 on task X in Asana"` | Phase 6 CRUD — `checklist.check` on the subtask |
|
|
76
|
+
| `"close task Y"` | Phase 6 CRUD — `task.close` (moves to close section + sets completed) |
|
|
77
|
+
| `"comment on task X: shipped"` | Phase 6 CRUD — `task.comment.add` |
|
|
78
|
+
| `"[autonomous] create task in asana from plan @docs/plans/X.md"` | Phase 5b autonomous (requires `autonomous.enabled: true`) |
|
|
79
|
+
|
|
80
|
+
## Asana-specific notes
|
|
81
|
+
|
|
82
|
+
> [!NOTE]
|
|
83
|
+
> **Subtasks are one level deep** — the adapter flattens nested checklists into a single subtask layer.
|
|
84
|
+
|
|
85
|
+
> [!WARNING]
|
|
86
|
+
> **Custom fields do NOT inherit by default** — list field IDs in `subtaskDefaults.inheritParentFields` so the adapter copies them from parent to subtasks at create time.
|
|
87
|
+
|
|
88
|
+
- **Assignee is a single field** — use `task.assignee.add` to add followers; the primary assignee replaces on conflict.
|
|
89
|
+
- **MCP `get_task` doesn't return activity stories** — the Asana UI activity feed is the source of truth for attribution audits. See [`anti-patterns/asana.md`](./anti-patterns/asana.md).
|
|
90
|
+
|
|
91
|
+
## Documentation
|
|
92
|
+
|
|
93
|
+
- [`SKILL.md`](./SKILL.md) — phase routing + CRUD vocabulary.
|
|
94
|
+
- [`schemas/config.json`](./schemas/config.json) — `.asana.json` JSON Schema.
|
|
95
|
+
- [`anti-patterns/asana.md`](./anti-patterns/asana.md) — recurring gotchas.
|
|
96
|
+
- [`../pm-tasks-core/references/autonomous-mode.md`](../pm-tasks-core/references/autonomous-mode.md) — autonomous-mode contract.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT — see [LICENSE](./LICENSE).
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pm-tasks-asana
|
|
3
|
+
description: >-
|
|
4
|
+
Asana adapter for the @llodev/pm-tasks-* family. Use when the user mentions
|
|
5
|
+
Asana, asks to "create Asana task", "publish to Asana", "post to Asana",
|
|
6
|
+
"publish", "add comment in Asana", or uses --publish-asana; OR for CRUD on
|
|
7
|
+
existing tasks (check subtask, close task, change due-date, assign person,
|
|
8
|
+
comment); OR when invoked autonomously by another agent with [autonomous] /
|
|
9
|
+
--auto sentinel. Asana hierarchy: workspace > project > section > parent task
|
|
10
|
+
> subtasks (one level), with custom fields and multi-assignee support. Modes:
|
|
11
|
+
paste-ready (no MCP needed), MCP publish (via claude.ai Asana MCP), autonomous
|
|
12
|
+
(write-through with allowlist). Implements 7 CRUD verbs (task.create,
|
|
13
|
+
task.move, checklist.check, task.close, task.due-date.set, task.assignee.add,
|
|
14
|
+
task.comment.add) from pm-tasks/pm-tasks-core/references/contract.md. Requires
|
|
15
|
+
@llodev/pm-tasks-core installed.
|
|
16
|
+
license: MIT
|
|
17
|
+
metadata:
|
|
18
|
+
version: 1.6.0
|
|
19
|
+
tags:
|
|
20
|
+
- agent-skill
|
|
21
|
+
- asana
|
|
22
|
+
- plan-to-tasks
|
|
23
|
+
- pm-tools
|
|
24
|
+
family: pm-tasks
|
|
25
|
+
role: adapter
|
|
26
|
+
tool: asana
|
|
27
|
+
compatibility:
|
|
28
|
+
agents:
|
|
29
|
+
- claude-code
|
|
30
|
+
- cursor
|
|
31
|
+
- codex
|
|
32
|
+
- windsurf
|
|
33
|
+
- cline
|
|
34
|
+
- roo-code
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# pm-tasks-asana
|
|
38
|
+
|
|
39
|
+
Adapter for Asana within the `@llodev/pm-tasks-*` family. Use the core skill's extraction phases, then apply Asana formatting and optionally publish/operate via the `claude.ai Asana` MCP server.
|
|
40
|
+
|
|
41
|
+
## Routing
|
|
42
|
+
|
|
43
|
+
| Mode | Trigger | Path |
|
|
44
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| Paste-only | "format as Asana task" without MCP intent | Phase 3 (core) → Phase 4 (this skill, format only) → output paste blocks |
|
|
46
|
+
| MCP publish | "publish to Asana", "create on Asana", "--publish-asana" | Phase 3 → Phase 4 → Phase 5 (publish via MCP) |
|
|
47
|
+
| Autonomous | `[autonomous]` or `--auto` in prompt OR `LLODEV_PM_TASKS_AUTONOMOUS=1` | Phase 3 → Phase 4 → Phase 5b (write-through, no preview) |
|
|
48
|
+
| CRUD ops | "check subtask N on task X", "close task Y", "assign Alice to task Z", "comment on task X" | Phase 6 (operations, direct verb dispatch) |
|
|
49
|
+
| Plan-execution | Plan file path in prompt (`docs/plans/*.md`), OR `--plan-exec` flag, OR plan reference paired with `.asana.json` | Phase 7 (discover existing cards via `discoverPlanTasks`; calling agent dispatches per-task verbs at task boundaries) |
|
|
50
|
+
|
|
51
|
+
## Asana model
|
|
52
|
+
|
|
53
|
+
Asana tasks have:
|
|
54
|
+
|
|
55
|
+
- **Name** (title, ≤80 chars for board view).
|
|
56
|
+
- **Description** (rich text; prefer `**Section**` bold labels — `##` headings render inconsistently).
|
|
57
|
+
- **Subtasks** — one level deep. Custom fields and assignee do NOT auto-propagate from parent; the adapter sets them explicitly per `subtaskDefaults.inheritParentFields` in `.asana.json`.
|
|
58
|
+
- **Sections** — group tasks within a project.
|
|
59
|
+
- **Custom fields** — per-project; API always uses option GIDs, never display names.
|
|
60
|
+
- **Multi-assignee** — Asana allows multiple followers; primary assignee is a single field. Use `task.assignee.add` to add followers.
|
|
61
|
+
|
|
62
|
+
## Phase 4 — Asana formatting
|
|
63
|
+
|
|
64
|
+
Apply the generic card from core's [`../pm-tasks-core/references/generic-card.md`](../pm-tasks-core/references/generic-card.md). Then map to Asana:
|
|
65
|
+
|
|
66
|
+
- Title → task `name`.
|
|
67
|
+
- Sections of the generic card → bold `**Section**` labels inside `description` (not `##`).
|
|
68
|
+
- "Implementation Checklist" + "Verification Checklist" → subtasks (flatten any nested bullets; Asana supports one level only).
|
|
69
|
+
- Labels → custom field options (resolved via `.asana.json` `customFields[]`).
|
|
70
|
+
- Due date → `due_on` (YYYY-MM-DD).
|
|
71
|
+
- Assignee → `assignee` GID resolved from `.asana.json` `members[]` or `me` at publish time.
|
|
72
|
+
|
|
73
|
+
## Phase 5 — MCP publish
|
|
74
|
+
|
|
75
|
+
**Prerequisites:** Asana MCP server (`claude.ai Asana`) connected in your agent. The MCP handles OAuth; the adapter never sees tokens. Configuration steps differ per agent — register the same Asana MCP endpoint your agent supports:
|
|
76
|
+
|
|
77
|
+
- **Claude Code**: `claude mcp add asana -s project -- npx -y claude-ai-asana-mcp` (or follow Anthropic's setup for the hosted `claude.ai Asana` connector).
|
|
78
|
+
- **Cursor / Windsurf / Cline / Roo Code**: add an entry to that agent's MCP settings JSON pointing at the same `claude-ai-asana-mcp` command (envelope identical to the Trello example in `pm-tasks-trello/references/mcp-config.md`).
|
|
79
|
+
- **Codex**: TOML entry under `[mcp_servers.asana]` in `~/.codex/config.toml`.
|
|
80
|
+
- **Other MCP-capable agents**: consult that agent's MCP docs; the server command and OAuth flow are constant.
|
|
81
|
+
|
|
82
|
+
Strict order: 5.1 read `.asana.json` (full file) → 5.2.5 resolve assignee + custom fields + per-subtask field map → 5.2 preview & approval → 5.3 publish via MCP → 5.4 error handling.
|
|
83
|
+
|
|
84
|
+
MCP publish sequence:
|
|
85
|
+
|
|
86
|
+
1. **Parent task** — `create_tasks` with `name`, `notes` (description), `projects: [projectGid]`, `memberships: [{ project, section }]`, `assignee` (resolved GID), `due_on`, `custom_fields` (JSON string of `{fieldGid: optionGid}`).
|
|
87
|
+
2. **Subtasks** — `create_tasks` per subtask with `parent: parentGid`, `name`, `assignee` (inherited or per-subtask), `custom_fields` matching `subtaskDefaults.inheritParentFields`.
|
|
88
|
+
3. **Tags** (optional) — `addTag` per tag GID.
|
|
89
|
+
4. **Confirm** — list parent + subtasks with permalinks.
|
|
90
|
+
|
|
91
|
+
### Attribution (opt-in)
|
|
92
|
+
|
|
93
|
+
Before calling the MCP create tool, read `config.attribution`. If `enabled === true`, prefix the comment with the `commentPrefix` returned by `getAttribution()` and append the `descriptionFooter` to the end of `description`. In autonomous mode (`[autonomous]` sentinel), the `commentPrefix` automatically becomes the `autonomousCommentPrefix`. See [references/attribution.md in pm-tasks-core](../pm-tasks-core/references/attribution.md) (added in v1.2.0).
|
|
94
|
+
|
|
95
|
+
## Phase 5b — Autonomous
|
|
96
|
+
|
|
97
|
+
Skip 5.2 preview & approval. Apply autonomous-mode contract from [`../pm-tasks-core/references/autonomous-mode.md`](../pm-tasks-core/references/autonomous-mode.md). Audit log entries per [`../pm-tasks-core/references/audit-log-format.md`](../pm-tasks-core/references/audit-log-format.md).
|
|
98
|
+
|
|
99
|
+
Asana-specific autonomous scope: `autonomous.scope.projects[]` + `autonomous.scope.sections[]` must include the target GIDs. Any custom-field write must be in `autonomous.allow` (`task.create` covers create-time field set; ongoing field changes are out of scope for v1.x).
|
|
100
|
+
|
|
101
|
+
### Continuous operation in multi-task loops
|
|
102
|
+
|
|
103
|
+
Mandatory when the controller is executing a plan with multiple tasks autonomously. Mirror each task transition on the corresponding Asana task in real time — NEVER batch state updates at end-of-loop. See [`../pm-tasks-core/references/autonomous-mode.md`](../pm-tasks-core/references/autonomous-mode.md) § **Continuous operation across multi-task loops** for the full contract and anti-patterns.
|
|
104
|
+
|
|
105
|
+
Asana-specific verb mapping:
|
|
106
|
+
|
|
107
|
+
| Transition | Canonical verb + MCP call(s) |
|
|
108
|
+
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| Task start | `task.move(cardId, "wip")` → `mcp__claude_ai_Asana__update_tasks { task: <gid>, memberships: [{ project: <projectGid>, section: <wipSectionGid> }] }` |
|
|
110
|
+
| Step complete (subtask) | `checklist.check` → `mcp__claude_ai_Asana__update_tasks { task: <subtaskGid>, completed: true }` |
|
|
111
|
+
| Task complete (full) | `task.move(cardId, "done")` → `mcp__claude_ai_Asana__update_tasks { task: <parentGid>, memberships: [{ project: <projectGid>, section: <doneSectionGid> }] }` then `task.comment.add` → `mcp__claude_ai_Asana__add_comment { task_id: <parentGid>, text: "🤖 [agent] Task complete. Commit: <SHA>. <branch>." }` then `task.close` → `mcp__claude_ai_Asana__update_tasks { task: <parentGid>, completed: true }` |
|
|
112
|
+
| Task failed | `task.comment.add` → `mcp__claude_ai_Asana__add_comment` with failure mode + `mcp__claude_ai_Asana__update_tasks { task: <gid>, add_followers: ["<escalateToAliasGid>"] }` for human escalation. Do NOT call `task.move(_, "done")` or `task.close`. |
|
|
113
|
+
|
|
114
|
+
Resolve `<wipSectionGid>` / `<doneSectionGid>` from `.asana.json` using `defaults.wipSectionAlias` / `defaults.doneSectionAlias` to look up the matching entry in `sections[]` by alias. Both must already be in `autonomous.scope.sections` — otherwise the verb returns `OUT_OF_SCOPE`.
|
|
115
|
+
|
|
116
|
+
**Asana caveat (per [`anti-patterns/asana.md`](./anti-patterns/asana.md)):** the MCP `get_task` doesn't return activity stories, so verifying the lifecycle programmatically is incomplete. The UI activity feed IS the human's audit log — keep it dense and accurate.
|
|
117
|
+
|
|
118
|
+
## Phase 6 — CRUD operations (existing tasks)
|
|
119
|
+
|
|
120
|
+
For verbs other than `task.create`, jump directly to the operation. Verb → MCP tool mapping:
|
|
121
|
+
|
|
122
|
+
| Core verb | Asana MCP tool | Notes |
|
|
123
|
+
| ------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `task.create` | `create_tasks` | parent + subtasks per Phase 5 |
|
|
125
|
+
| `task.move` | `update_tasks` | `memberships: [{ project, section: <resolvedGid> }]`. Resolve `"wip"` / `"done"` / `"open"` via `defaults.wipSectionAlias` / `defaults.doneSectionAlias` / `defaults.openSectionAlias` in `.asana.json`. Raw section GIDs pass through. |
|
|
126
|
+
| `checklist.check` | `update_tasks` | for subtasks: `completed: true`; emulates checklist via subtask model |
|
|
127
|
+
| `task.close` | `update_tasks` | `completed: true` on parent |
|
|
128
|
+
| `task.due-date.set` | `update_tasks` | `due_on: "YYYY-MM-DD"` |
|
|
129
|
+
| `task.assignee.add` | `update_tasks` + `addFollower` | primary assignee replaces; additional are followers |
|
|
130
|
+
| `task.comment.add` | `add_comment` (story) | adds a comment story to the task; apply attribution prefix if enabled |
|
|
131
|
+
|
|
132
|
+
`<task-ref>` resolution: accept Asana permalinks (`https://app.asana.com/0/<project>/<task>`), bare GIDs, or aliases from `.asana.json` `taskAliases[]`.
|
|
133
|
+
|
|
134
|
+
## Phase 7 — Plan-execution mode
|
|
135
|
+
|
|
136
|
+
When the calling agent passes a plan reference (a path to a markdown plan file, a plan slug, or an explicit list of expected task titles), this skill loads `.asana.json` via `requireConfig` and uses `discoverPlanTasks` (from `@llodev/pm-tasks-core`) to triage which tasks in the plan already exist as cards in scope. The skill returns the triage report `{ found, missing, ambiguous }` — the **calling agent** decides how to act on each bucket (create missing cards via Phase 4 + 5; disambiguate by picking the right ambiguous card; proceed with existing).
|
|
137
|
+
|
|
138
|
+
The skill does **not** assume any particular implementation strategy. It does not drive the calling agent's task loop, does not depend on any specific orchestration framework, and does not require any markup beyond what is already documented for `task.create` and the autonomous-mode contract. When the calling agent finishes a task and asks the skill to record progress, it invokes the standard verbs (`task.move`, `checklist.check`, `task.comment.add`, `task.close`) directly — the same path used by Phase 5b autonomous mode.
|
|
139
|
+
|
|
140
|
+
Full contract: triggers, discovery semantics, `ConfigRequiredError` handling, failure modes table, and the hook contract for Phase 5 are documented in [`pm-tasks/pm-tasks-core/references/plan-execution.md`](../pm-tasks-core/references/plan-execution.md) (added in v1.9.0).
|
|
141
|
+
|
|
142
|
+
## Result envelope
|
|
143
|
+
|
|
144
|
+
Every verb returns the core contract shape (see [`../pm-tasks-core/references/contract.md`](../pm-tasks-core/references/contract.md) §Result envelope):
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"ok": true,
|
|
149
|
+
"verb": "task.create",
|
|
150
|
+
"tool": "asana",
|
|
151
|
+
"ref": { "id": "<gid>", "url": "https://app.asana.com/0/<project>/<gid>", "alias": "<optional>" },
|
|
152
|
+
"details": {
|
|
153
|
+
/* Asana-specific (see table below) */
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Asana-specific `details` per verb:
|
|
159
|
+
|
|
160
|
+
| Verb | `details` fields |
|
|
161
|
+
| ------------------- | ------------------------------------------------------------------------ |
|
|
162
|
+
| `task.create` | `{ parentGid, subtaskGids[], projectGid, sectionGid?, customFields[]? }` |
|
|
163
|
+
| `task.move` | `{ taskGid, sectionGid, targetList }` |
|
|
164
|
+
| `checklist.check` | `{ subtaskGid, completed: true }` |
|
|
165
|
+
| `task.close` | `{ parentGid, completed: true }` |
|
|
166
|
+
| `task.due-date.set` | `{ taskGid, due_on }` |
|
|
167
|
+
| `task.assignee.add` | `{ taskGid, assignee, followers[]? }` (primary vs follower split) |
|
|
168
|
+
| `task.comment.add` | `{ taskGid, storyGid }` |
|
|
169
|
+
|
|
170
|
+
On failure: `{ ok: false, verb, tool, error: { code, message, retriable } }`. Common codes: `FORBIDDEN_VERB`, `OUT_OF_SCOPE`, `NOT_FOUND`, `RATE_LIMITED`, `PARTIAL_CREATE` (subtask failed mid-create — see [`../pm-tasks-core/references/contract.md`](../pm-tasks-core/references/contract.md) §Partial-create recovery).
|
|
171
|
+
|
|
172
|
+
## Anti-patterns
|
|
173
|
+
|
|
174
|
+
See [`anti-patterns/asana.md`](anti-patterns/asana.md) — paste health, custom-field rules, GID requirements, partial-create handling.
|
|
175
|
+
|
|
176
|
+
## Standalone fallback
|
|
177
|
+
|
|
178
|
+
If `@llodev/pm-tasks-core` is not installed: ask the user for minimum input (title + subtask names) and produce a paste-ready Asana task body from this content alone. Quality is degraded — no scope/audience/fidelity inference. Print: _"Install `@llodev/pm-tasks-core` for the full flow."_
|
|
179
|
+
|
|
180
|
+
## Config
|
|
181
|
+
|
|
182
|
+
Lookup order: `<git-root>/.asana.json` → `~/.config/llodev/pm-tasks/asana.json` → abort with init instructions. Schema: [`schemas/config.json`](schemas/config.json). Secrets NEVER in JSON — Asana MCP holds OAuth; `init` uses `LLODEV_PM_TASKS_ASANA_PAT` env var only.
|
|
183
|
+
|
|
184
|
+
## Init
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
npx @llodev/pm-tasks-asana init
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
See [`../pm-tasks-core/references/init-ux.md`](../pm-tasks-core/references/init-ux.md) for the shared flow. Asana init reads workspaces / projects / sections / custom fields via the Asana REST API using a Personal Access Token (env `LLODEV_PM_TASKS_ASANA_PAT`).
|
|
191
|
+
|
|
192
|
+
Pass `--doctor` to run workspace health checks before prompting:
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
npx @llodev/pm-tasks-asana init --doctor
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Runs core checks (C-FS-1..3, C-CFG-1..4) plus Asana-specific probes (C-ASN-1..3, gated on `LLODEV_PM_TASKS_ASANA_PAT`). Full check matrix in [`pm-tasks/pm-tasks-core/references/doctor.md`](../pm-tasks-core/references/doctor.md).
|