@llodev/pm-tasks-asana 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,115 @@
1
1
  # @llodev/pm-tasks-asana
2
2
 
3
+ ## 1.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#41](https://github.com/llodev/skills/pull/41) [`dc31cdf`](https://github.com/llodev/skills/commit/dc31cdffe7dad3338f07190cdec43d71c9eb6f8b) Thanks [@lloliveiradev](https://github.com/lloliveiradev)! - Refresh published package metadata for the flattened `skills/` + `packages/` repository layout. `homepage` and `repository.directory` now point at the new paths, so npm and registry "Repository"/"Homepage" links resolve instead of 404ing against the removed `pm-tasks/*` and `django/*` folders. Documentation-only for consumers — no API, runtime, or behavior changes.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`dc31cdf`](https://github.com/llodev/skills/commit/dc31cdffe7dad3338f07190cdec43d71c9eb6f8b)]:
12
+ - @llodev/pm-tasks-core@1.12.0
13
+
14
+ ## 1.6.0
15
+
16
+ ### Minor Changes
17
+
18
+ - [#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)**
19
+
20
+ Three coordinated minor bumps shipping the agent-agnostic headless runtime
21
+ and the F15 plan-execution mode. Skill-driven flows are unchanged; this
22
+ release adds a programmatic entry point and a new mode the calling agent
23
+ can opt into when it has a plan file to execute.
24
+
25
+ **`@llodev/pm-tasks-core@1.8.0 → 1.9.0`** (minor)
26
+
27
+ - New: `@llodev/pm-tasks-core/runtime` subpath exposes `createCoreRuntime`,
28
+ the `Transport` interface, 7 verb handlers, `RuntimeContext`, and the
29
+ full set of request/response types. Pure: no MCP imports, no transport
30
+ implementation — adapters provide the wiring.
31
+ - New: `@llodev/pm-tasks-core/plan-execution` module exports
32
+ `requireConfig` + `ConfigRequiredError`, `discoverPlanTasks` +
33
+ `resolvePlanRef` + `parseH3Titles` + `filenameToSlug` (discovery
34
+ helpers — `PlanRef` accepts `string[]` titles, a `.md` path with H3
35
+ parsing, or a bare slug), `onTaskStart` + `onTaskComplete` (boundary
36
+ hooks with best-effort dispatch, `ALREADY_IN_STATE` → skipped
37
+ classification, process-local idempotency memo keyed by
38
+ `${taskId}|${commitSha}`), and `__resetHookCacheForTests` (test escape
39
+ hatch).
40
+ - New: `pm-tasks-core/references/plan-execution.md` documents the full
41
+ contract (triggers, discovery semantics, hook classification table,
42
+ failure modes, `ConfigRequiredError` shape).
43
+ - New: `pm-tasks-core/references/agent-agnostic-lint.md` + a stand-alone
44
+ `scripts/checks/agent-agnostic-lint.mjs` that bans `superpowers`,
45
+ `sdd`, `Claude Code`, `Claude-only`, `Claude assumes` in SKILL body
46
+ content while allowlisting `claude-code` in `compatibility.agents`
47
+ frontmatter, vendor product names (`claude.ai Asana`,
48
+ `claude-ai-asana-mcp`), and other context-aware exemptions.
49
+ - Internal: tarball size budget raised 14.1 → 18.5 kB across Phase 4
50
+ and Phase 5 (covering the plan-execution module + hook helpers + full
51
+ JSDoc on every exported symbol).
52
+
53
+ **`@llodev/pm-tasks-asana@1.5.0 → 1.6.0`** (minor)
54
+
55
+ - New: `@llodev/pm-tasks-asana/adapter` subpath exposes
56
+ `createAdapter({ configPath, mcp, session?, language? })` returning a
57
+ `Runtime`. The `mcp: McpCaller` callback is the caller's only
58
+ obligation — receives a fully-qualified `mcp__claude_ai_Asana__*` tool
59
+ name + args object, returns the MCP server's raw response.
60
+ - New: `pm-tasks-asana/src/transport-asana.ts` implements the
61
+ `Transport` interface against `mcp__claude_ai_Asana__*` tools.
62
+ Asana-specific deltas: `closeListOrSectionId` ignored at the transport
63
+ layer (Asana has no list-on-close concept), ISO-8601 → `YYYY-MM-DD`
64
+ conversion via `isoToDueOn` helper for `taskDueDateSet`,
65
+ `INVALID_REQUEST` short-circuit BEFORE the MCP call on malformed
66
+ `dueAt`, single-assignee model for `taskAssigneeAdd`.
67
+ - SKILL.md routing table gained a Plan-execution row; Phase 7 narrative
68
+ section forward-references the new `references/plan-execution.md`
69
+ doc in `pm-tasks-core`.
70
+
71
+ **`@llodev/pm-tasks-trello@1.5.0 → 1.6.0`** (minor)
72
+
73
+ - New: `@llodev/pm-tasks-trello/adapter` subpath exposes
74
+ `createAdapter({ configPath, mcp, session?, language? })` returning a
75
+ `Runtime`. Same shape and contract as the Asana adapter.
76
+ - New: `pm-tasks-trello/src/transport-trello.ts` implements the
77
+ `Transport` interface against `mcp__trello__*` tools. Trello-specific
78
+ behavior: `taskClose` archives the card AND optionally moves it to
79
+ `closeListOrSectionId` when provided (Trello's "Done" list pattern).
80
+ - SKILL.md routing table gained a Plan-execution row mirroring the
81
+ Asana adapter; identical Phase 7 narrative section.
82
+
83
+ **Skill-judge gate**
84
+
85
+ Modified `pm-tasks-asana/SKILL.md` and `pm-tasks-trello/SKILL.md`
86
+ (Phase 4.3) added the Plan-execution mode routing row + Phase 7 section.
87
+ Measured drift sits within the documented noise band ([-2, +2]); the
88
+ agent-agnostic-lint rule shipped in this release codifies the
89
+ allowlist that earlier scoring assumed. If drift is within tolerance,
90
+ bypass with `SKIP_SKILL_JUDGE_GATE=1 make release-version`.
91
+
92
+ **Breaking changes**
93
+
94
+ None. All Phase 1-5 additions are pure surface area additions:
95
+
96
+ - `/runtime` and `/adapter` subpaths are NEW exports (no prior consumers)
97
+ - `/plan-execution` helpers are NEW exports
98
+ - Existing skill-driven flows + the 7-verb CRUD contract on the autonomous
99
+ path are unchanged
100
+
101
+ **Migration**
102
+
103
+ No migration needed. Existing consumers continue to import from the
104
+ package root. New code can opt into the runtime by importing from
105
+ `@llodev/pm-tasks-{trello,asana}/adapter` or the helpers from
106
+ `@llodev/pm-tasks-core/runtime` and `@llodev/pm-tasks-core/plan-execution`.
107
+
108
+ ### Patch Changes
109
+
110
+ - Updated dependencies [[`78106ab`](https://github.com/llodev/skills/commit/78106ab42ed317ba865906d25701ade4532396ec)]:
111
+ - @llodev/pm-tasks-core@1.9.0
112
+
3
113
  ## 1.5.0
4
114
 
5
115
  ### Minor Changes
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
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>&nbsp;&nbsp;
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>&nbsp;&nbsp;
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>
3
+ <a href="https://github.com/llodev/skills/blob/main/skills/pm-tasks-asana/README.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/usa.svg" width="30" alt="English"></a>&nbsp;&nbsp;
4
+ <a href="https://github.com/llodev/skills/blob/main/skills/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>&nbsp;&nbsp;
5
+ <a href="https://github.com/llodev/skills/blob/main/skills/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
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
@@ -29,8 +29,8 @@ What you get:
29
29
  npm i @llodev/pm-tasks-core @llodev/pm-tasks-asana
30
30
 
31
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
32
+ npx skills add llodev/skills/skills/pm-tasks-core
33
+ npx skills add llodev/skills/skills/pm-tasks-asana
34
34
  ```
35
35
 
36
36
  ## Setup the MCP
package/SKILL.md CHANGED
@@ -11,11 +11,11 @@ description: >-
11
11
  paste-ready (no MCP needed), MCP publish (via claude.ai Asana MCP), autonomous
12
12
  (write-through with allowlist). Implements 7 CRUD verbs (task.create,
13
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
14
+ task.comment.add) from skills/pm-tasks-core/references/contract.md. Requires
15
15
  @llodev/pm-tasks-core installed.
16
16
  license: MIT
17
17
  metadata:
18
- version: 1.5.0
18
+ version: 1.7.0
19
19
  tags:
20
20
  - agent-skill
21
21
  - asana
@@ -40,12 +40,13 @@ Adapter for Asana within the `@llodev/pm-tasks-*` family. Use the core skill's e
40
40
 
41
41
  ## Routing
42
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) |
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) |
49
50
 
50
51
  ## Asana model
51
52
 
@@ -130,6 +131,14 @@ For verbs other than `task.create`, jump directly to the operation. Verb → MCP
130
131
 
131
132
  `<task-ref>` resolution: accept Asana permalinks (`https://app.asana.com/0/<project>/<task>`), bare GIDs, or aliases from `.asana.json` `taskAliases[]`.
132
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 [`skills/pm-tasks-core/references/plan-execution.md`](../pm-tasks-core/references/plan-execution.md) (added in v1.9.0).
141
+
133
142
  ## Result envelope
134
143
 
135
144
  Every verb returns the core contract shape (see [`../pm-tasks-core/references/contract.md`](../pm-tasks-core/references/contract.md) §Result envelope):
@@ -140,9 +149,7 @@ Every verb returns the core contract shape (see [`../pm-tasks-core/references/co
140
149
  "verb": "task.create",
141
150
  "tool": "asana",
142
151
  "ref": { "id": "<gid>", "url": "https://app.asana.com/0/<project>/<gid>", "alias": "<optional>" },
143
- "details": {
144
- /* Asana-specific (see table below) */
145
- }
152
+ "details": {/* Asana-specific (see table below) */}
146
153
  }
147
154
  ```
148
155
 
@@ -186,4 +193,4 @@ Pass `--doctor` to run workspace health checks before prompting:
186
193
  npx @llodev/pm-tasks-asana init --doctor
187
194
  ```
188
195
 
189
- 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).
196
+ 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 [`skills/pm-tasks-core/references/doctor.md`](../pm-tasks-core/references/doctor.md).
@@ -0,0 +1,19 @@
1
+ import { type Runtime } from "@llodev/pm-tasks-core/runtime";
2
+ import { type McpCaller } from "./transport-asana.js";
3
+ export interface CreateAdapterOptions {
4
+ /** Absolute or cwd-relative path to .asana.json config file. */
5
+ configPath: string;
6
+ /** Caller-supplied MCP dispatcher (proxies to `mcp__claude_ai_Asana__*` tools at runtime). */
7
+ mcp: McpCaller;
8
+ /** Optional session id for audit-log correlation. Defaults to generateSession() when omitted. */
9
+ session?: string;
10
+ /** Optional locale hint (forwarded from .asana.json locale field for narration). */
11
+ language?: string;
12
+ }
13
+ /**
14
+ * Construct a ready-to-use Asana adapter Runtime. Loads config from configPath,
15
+ * wires the Asana MCP transport from the caller-supplied McpCaller, and returns
16
+ * the same Runtime shape as createCoreRuntime.
17
+ */
18
+ export declare function createAdapter(opts: CreateAdapterOptions): Promise<Runtime>;
19
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,GAAG,EAAE,SAAS,CAAC;IACf,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAShF"}
@@ -0,0 +1,18 @@
1
+ import { createCoreRuntime } from "@llodev/pm-tasks-core/runtime";
2
+ import { createAsanaTransport } from "./transport-asana.js";
3
+ /**
4
+ * Construct a ready-to-use Asana adapter Runtime. Loads config from configPath,
5
+ * wires the Asana MCP transport from the caller-supplied McpCaller, and returns
6
+ * the same Runtime shape as createCoreRuntime.
7
+ */
8
+ export async function createAdapter(opts) {
9
+ const transport = createAsanaTransport({ mcp: opts.mcp });
10
+ return createCoreRuntime({
11
+ tool: "asana",
12
+ configPath: opts.configPath,
13
+ transport,
14
+ session: opts.session,
15
+ language: opts.language,
16
+ });
17
+ }
18
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAgB,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAkB,MAAM,sBAAsB,CAAC;AAa5E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA0B;IAC5D,MAAM,SAAS,GAAG,oBAAoB,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1D,OAAO,iBAAiB,CAAC;QACvB,IAAI,EAAE,OAAO;QACb,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS;QACT,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { createAsanaTransport } from "./transport-asana.js";
2
+ export type { McpCaller, CreateAsanaTransportOptions } from "./transport-asana.js";
3
+ export { createAdapter } from "./adapter.js";
4
+ export type { CreateAdapterOptions } from "./adapter.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { createAsanaTransport } from "./transport-asana.js";
2
+ export { createAdapter } from "./adapter.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Asana MCP transport — implements the @llodev/pm-tasks-core Transport
3
+ * interface by dispatching every canonical verb through
4
+ * `mcp__claude_ai_Asana__*` tool calls. The MCP dispatcher is injected
5
+ * (caller-supplied callback, matching the established `probeMCP` pattern in
6
+ * pm-tasks-core/src/init-lib.ts) so this module stays:
7
+ *
8
+ * - testable — tests inject a recording stub
9
+ * - side-effect free — `import` does not throw, log, or call anything
10
+ * - decoupled at build — no `mcp__*` symbols are referenced at compile time
11
+ *
12
+ * Verb mappings follow `pm-tasks-asana/references/operations.md` verbatim.
13
+ * Idempotency fetches stay at the handler / Phase 5 hook layer per the
14
+ * Phase 2 contract; this transport is a thin dispatcher that classifies
15
+ * MCP errors into TransportErrorCode and wraps each result in a typed
16
+ * TransportResult<T> envelope.
17
+ *
18
+ * Asana-specific deltas vs the Trello transport:
19
+ * - Five of seven verbs route through `update_tasks` (Asana's general
20
+ * batch update endpoint) — the `updates: [{ task, ...fields }]` shape
21
+ * is uniform across move / checklist.check / close / due-date / assignee.
22
+ * - `taskClose` is single-call: the visual "move to Done" is a separate
23
+ * caller-driven `task.move` per operations.md L12. `closeListOrSectionId`
24
+ * is IGNORED at the transport layer; the response data omits
25
+ * `movedToListOrSectionId` entirely.
26
+ * - `taskDueDateSet` converts ISO 8601 → `YYYY-MM-DD` via `.slice(0,10)`
27
+ * because Asana's `due_on` field rejects full timestamps. Malformed
28
+ * input short-circuits to `INVALID_REQUEST` BEFORE the MCP call.
29
+ * - `taskAssigneeAdd` sets the single primary `assignee` field; multi-
30
+ * followers semantics are deferred to handler / Phase 5 hooks per
31
+ * operations.md L14 simplification.
32
+ */
33
+ import type { Transport } from "@llodev/pm-tasks-core/runtime";
34
+ /**
35
+ * MCP-call dispatcher. The agent runtime that loads this transport
36
+ * provides a function that proxies to the real `mcp__claude_ai_Asana__*`
37
+ * tools. Tests inject a recording stub.
38
+ */
39
+ export type McpCaller = (toolName: string, args: Record<string, unknown>) => Promise<unknown>;
40
+ export interface CreateAsanaTransportOptions {
41
+ mcp: McpCaller;
42
+ }
43
+ export declare function createAsanaTransport(opts: CreateAsanaTransportOptions): Transport;
44
+ //# sourceMappingURL=transport-asana.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-asana.d.ts","sourceRoot":"","sources":["../src/transport-asana.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,SAAS,EAiBV,MAAM,+BAA+B,CAAC;AAEvC;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9F,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,SAAS,CAAC;CAChB;AA0DD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,2BAA2B,GAAG,SAAS,CAsLjF"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Asana MCP transport — implements the @llodev/pm-tasks-core Transport
3
+ * interface by dispatching every canonical verb through
4
+ * `mcp__claude_ai_Asana__*` tool calls. The MCP dispatcher is injected
5
+ * (caller-supplied callback, matching the established `probeMCP` pattern in
6
+ * pm-tasks-core/src/init-lib.ts) so this module stays:
7
+ *
8
+ * - testable — tests inject a recording stub
9
+ * - side-effect free — `import` does not throw, log, or call anything
10
+ * - decoupled at build — no `mcp__*` symbols are referenced at compile time
11
+ *
12
+ * Verb mappings follow `pm-tasks-asana/references/operations.md` verbatim.
13
+ * Idempotency fetches stay at the handler / Phase 5 hook layer per the
14
+ * Phase 2 contract; this transport is a thin dispatcher that classifies
15
+ * MCP errors into TransportErrorCode and wraps each result in a typed
16
+ * TransportResult<T> envelope.
17
+ *
18
+ * Asana-specific deltas vs the Trello transport:
19
+ * - Five of seven verbs route through `update_tasks` (Asana's general
20
+ * batch update endpoint) — the `updates: [{ task, ...fields }]` shape
21
+ * is uniform across move / checklist.check / close / due-date / assignee.
22
+ * - `taskClose` is single-call: the visual "move to Done" is a separate
23
+ * caller-driven `task.move` per operations.md L12. `closeListOrSectionId`
24
+ * is IGNORED at the transport layer; the response data omits
25
+ * `movedToListOrSectionId` entirely.
26
+ * - `taskDueDateSet` converts ISO 8601 → `YYYY-MM-DD` via `.slice(0,10)`
27
+ * because Asana's `due_on` field rejects full timestamps. Malformed
28
+ * input short-circuits to `INVALID_REQUEST` BEFORE the MCP call.
29
+ * - `taskAssigneeAdd` sets the single primary `assignee` field; multi-
30
+ * followers semantics are deferred to handler / Phase 5 hooks per
31
+ * operations.md L14 simplification.
32
+ */
33
+ // ---------------------------------------------------------------------------
34
+ // Internal helpers
35
+ // ---------------------------------------------------------------------------
36
+ function isObjectWith(value, key) {
37
+ return typeof value === "object" && value !== null && key in value;
38
+ }
39
+ function classifyError(e) {
40
+ if (!(e instanceof Error))
41
+ return { code: "MCP_ERROR", details: { message: String(e) } };
42
+ const msg = e.message.toLowerCase();
43
+ if (msg.includes("not found") || msg.includes("404")) {
44
+ return { code: "NOT_FOUND", details: { message: e.message } };
45
+ }
46
+ if (msg.includes("401") ||
47
+ msg.includes("403") ||
48
+ msg.includes("unauthorized") ||
49
+ msg.includes("forbidden")) {
50
+ return { code: "AUTH_ERROR", details: { message: e.message } };
51
+ }
52
+ if (msg.includes("429") || msg.includes("rate limit")) {
53
+ return { code: "RATE_LIMITED", details: { message: e.message } };
54
+ }
55
+ return { code: "MCP_ERROR", details: { message: e.message } };
56
+ }
57
+ function shapeError(verb) {
58
+ return {
59
+ ok: false,
60
+ code: "MCP_ERROR",
61
+ details: { message: "Asana MCP returned unexpected response shape", verb },
62
+ };
63
+ }
64
+ /**
65
+ * Validate ISO 8601 prefix `YYYY-MM-DD` and return the date portion.
66
+ * Returns null when the input is empty or doesn't start with that shape.
67
+ * Asana's `due_on` field accepts only `YYYY-MM-DD`, not full timestamps.
68
+ */
69
+ function isoToDueOn(input) {
70
+ if (typeof input !== "string" || input.length < 10)
71
+ return null;
72
+ const head = input.slice(0, 10);
73
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(head))
74
+ return null;
75
+ return head;
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // Factory
79
+ // ---------------------------------------------------------------------------
80
+ export function createAsanaTransport(opts) {
81
+ const { mcp } = opts;
82
+ return {
83
+ // -------------------------------------------------------------------
84
+ // 1. task.create → mcp__claude_ai_Asana__create_tasks
85
+ // -------------------------------------------------------------------
86
+ async taskCreate(req) {
87
+ const notes = req.clientToken
88
+ ? `[ct:${req.clientToken}] ${req.description ?? ""}`.trim()
89
+ : req.description;
90
+ const taskPayload = {
91
+ name: req.name,
92
+ memberships: [{ project: req.boardOrProjectId, section: req.listOrSectionId }],
93
+ };
94
+ if (notes !== undefined)
95
+ taskPayload.notes = notes;
96
+ try {
97
+ const resp = await mcp("mcp__claude_ai_Asana__create_tasks", { tasks: [taskPayload] });
98
+ if (!isObjectWith(resp, "tasks") || !Array.isArray(resp.tasks) || resp.tasks.length === 0) {
99
+ return shapeError("task.create");
100
+ }
101
+ const first = resp.tasks[0];
102
+ if (!isObjectWith(first, "gid") || typeof first.gid !== "string") {
103
+ return shapeError("task.create");
104
+ }
105
+ let url;
106
+ if (isObjectWith(first, "permalink_url") && typeof first.permalink_url === "string") {
107
+ url = first.permalink_url;
108
+ }
109
+ return { ok: true, data: { id: first.gid, ...(url !== undefined ? { url } : {}) } };
110
+ }
111
+ catch (e) {
112
+ const { code, details } = classifyError(e);
113
+ return { ok: false, code, details };
114
+ }
115
+ },
116
+ // -------------------------------------------------------------------
117
+ // 2. task.move → mcp__claude_ai_Asana__update_tasks
118
+ // -------------------------------------------------------------------
119
+ async taskMove(req) {
120
+ try {
121
+ await mcp("mcp__claude_ai_Asana__update_tasks", {
122
+ updates: [
123
+ {
124
+ task: req.taskId,
125
+ memberships: [{ project: "", section: req.targetListOrSectionId }],
126
+ },
127
+ ],
128
+ });
129
+ return {
130
+ ok: true,
131
+ data: {
132
+ previousListOrSectionId: null,
133
+ newListOrSectionId: req.targetListOrSectionId,
134
+ },
135
+ };
136
+ }
137
+ catch (e) {
138
+ const { code, details } = classifyError(e);
139
+ return { ok: false, code, details };
140
+ }
141
+ },
142
+ // -------------------------------------------------------------------
143
+ // 3. checklist.check → mcp__claude_ai_Asana__update_tasks (subtask)
144
+ // -------------------------------------------------------------------
145
+ async checklistCheck(req) {
146
+ try {
147
+ await mcp("mcp__claude_ai_Asana__update_tasks", {
148
+ updates: [{ task: req.itemId, completed: req.targetState === "complete" }],
149
+ });
150
+ const previousState = req.targetState === "complete" ? "incomplete" : "complete";
151
+ return {
152
+ ok: true,
153
+ data: { previousState, newState: req.targetState },
154
+ };
155
+ }
156
+ catch (e) {
157
+ const { code, details } = classifyError(e);
158
+ return { ok: false, code, details };
159
+ }
160
+ },
161
+ // -------------------------------------------------------------------
162
+ // 4. task.close → mcp__claude_ai_Asana__update_tasks (single-call)
163
+ // closeListOrSectionId is IGNORED for Asana — visual move is a
164
+ // separate caller-driven task.move per operations.md L12.
165
+ // -------------------------------------------------------------------
166
+ async taskClose(req) {
167
+ try {
168
+ await mcp("mcp__claude_ai_Asana__update_tasks", {
169
+ updates: [{ task: req.taskId, completed: true }],
170
+ });
171
+ return { ok: true, data: { closed: true } };
172
+ }
173
+ catch (e) {
174
+ const { code, details } = classifyError(e);
175
+ return { ok: false, code, details };
176
+ }
177
+ },
178
+ // -------------------------------------------------------------------
179
+ // 5. task.due-date.set → mcp__claude_ai_Asana__update_tasks
180
+ // Converts ISO 8601 → YYYY-MM-DD (Asana's due_on shape).
181
+ // Malformed input short-circuits to INVALID_REQUEST.
182
+ // -------------------------------------------------------------------
183
+ async taskDueDateSet(req) {
184
+ const dueOn = isoToDueOn(req.dueAt);
185
+ if (dueOn === null) {
186
+ return {
187
+ ok: false,
188
+ code: "INVALID_REQUEST",
189
+ details: { message: "dueAt must be ISO 8601", verb: "taskDueDateSet" },
190
+ };
191
+ }
192
+ try {
193
+ await mcp("mcp__claude_ai_Asana__update_tasks", {
194
+ updates: [{ task: req.taskId, due_on: dueOn }],
195
+ });
196
+ return {
197
+ ok: true,
198
+ data: { previousDueAt: null, newDueAt: req.dueAt },
199
+ };
200
+ }
201
+ catch (e) {
202
+ const { code, details } = classifyError(e);
203
+ return { ok: false, code, details };
204
+ }
205
+ },
206
+ // -------------------------------------------------------------------
207
+ // 6. task.assignee.add → mcp__claude_ai_Asana__update_tasks
208
+ // Single-assignee model at this layer; multi-followers deferred
209
+ // to handler / Phase 5 hooks per operations.md L14.
210
+ // -------------------------------------------------------------------
211
+ async taskAssigneeAdd(req) {
212
+ try {
213
+ await mcp("mcp__claude_ai_Asana__update_tasks", {
214
+ updates: [{ task: req.taskId, assignee: req.userId }],
215
+ });
216
+ return {
217
+ ok: true,
218
+ data: { added: true, currentAssigneeIds: [req.userId] },
219
+ };
220
+ }
221
+ catch (e) {
222
+ const { code, details } = classifyError(e);
223
+ return { ok: false, code, details };
224
+ }
225
+ },
226
+ // -------------------------------------------------------------------
227
+ // 7. task.comment.add → mcp__claude_ai_Asana__add_comment
228
+ // -------------------------------------------------------------------
229
+ async taskCommentAdd(req) {
230
+ const text = req.clientToken ? `[ct:${req.clientToken}] ${req.text}` : req.text;
231
+ try {
232
+ const resp = await mcp("mcp__claude_ai_Asana__add_comment", {
233
+ task: req.taskId,
234
+ text,
235
+ });
236
+ if (!isObjectWith(resp, "gid") || typeof resp.gid !== "string") {
237
+ return shapeError("task.comment.add");
238
+ }
239
+ const postedAt = isObjectWith(resp, "created_at") && typeof resp.created_at === "string"
240
+ ? resp.created_at
241
+ : new Date().toISOString();
242
+ return {
243
+ ok: true,
244
+ data: { commentId: resp.gid, postedAt },
245
+ };
246
+ }
247
+ catch (e) {
248
+ const { code, details } = classifyError(e);
249
+ return { ok: false, code, details };
250
+ }
251
+ },
252
+ };
253
+ }
254
+ //# sourceMappingURL=transport-asana.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-asana.js","sourceRoot":"","sources":["../src/transport-asana.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
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>&nbsp;&nbsp;
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>&nbsp;&nbsp;
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>
3
+ <a href="https://github.com/llodev/skills/blob/main/skills/pm-tasks-asana/README.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/usa.svg" width="30" alt="English"></a>&nbsp;&nbsp;
4
+ <a href="https://github.com/llodev/skills/blob/main/skills/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>&nbsp;&nbsp;
5
+ <a href="https://github.com/llodev/skills/blob/main/skills/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
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
@@ -29,8 +29,8 @@ Lo que obtienes:
29
29
  npm i @llodev/pm-tasks-core @llodev/pm-tasks-asana
30
30
 
31
31
  # Vercel CLI (instala el core manualmente también)
32
- npx skills add llodev/skills/pm-tasks/pm-tasks-core
33
- npx skills add llodev/skills/pm-tasks/pm-tasks-asana
32
+ npx skills add llodev/skills/skills/pm-tasks-core
33
+ npx skills add llodev/skills/skills/pm-tasks-asana
34
34
  ```
35
35
 
36
36
  ## Setup del MCP
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
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>&nbsp;&nbsp;
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>&nbsp;&nbsp;
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>
3
+ <a href="https://github.com/llodev/skills/blob/main/skills/pm-tasks-asana/README.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/usa.svg" width="30" alt="English"></a>&nbsp;&nbsp;
4
+ <a href="https://github.com/llodev/skills/blob/main/skills/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>&nbsp;&nbsp;
5
+ <a href="https://github.com/llodev/skills/blob/main/skills/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
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
@@ -29,8 +29,8 @@ O que você ganha:
29
29
  npm i @llodev/pm-tasks-core @llodev/pm-tasks-asana
30
30
 
31
31
  # Vercel CLI (instale o core manualmente também)
32
- npx skills add llodev/skills/pm-tasks/pm-tasks-core
33
- npx skills add llodev/skills/pm-tasks/pm-tasks-asana
32
+ npx skills add llodev/skills/skills/pm-tasks-core
33
+ npx skills add llodev/skills/skills/pm-tasks-asana
34
34
  ```
35
35
 
36
36
  ## Setup do MCP
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@llodev/pm-tasks-asana",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Asana adapter for the @llodev/pm-tasks-* family. Use when the user mentions Asana (create Asana task, publish to Asana, post to Asana, add comment in Asana, --publish-asana, close task, check subtask) or wants to publish a plan as Asana tasks with subtasks. Modes: paste-ready (no MCP needed), MCP publish (via claude.ai Asana MCP), autonomous (sentinel [autonomous] / --auto). Implements 6 CRUD verbs from @llodev/pm-tasks-core/references/contract.md mapped to Asana (parent task + subtasks, custom fields, sections, multi-assignee). REQUIRES: @llodev/pm-tasks-core installed (skillpm / Claude Code marketplace cascade auto; Vercel CLI users install manually).",
5
5
  "license": "MIT",
6
- "homepage": "https://github.com/llodev/skills/tree/main/pm-tasks/pm-tasks-asana",
6
+ "homepage": "https://github.com/llodev/skills/tree/main/skills/pm-tasks-asana",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "https://github.com/llodev/skills.git",
10
- "directory": "pm-tasks/pm-tasks-asana"
10
+ "directory": "skills/pm-tasks-asana"
11
11
  },
12
12
  "main": "./dist/bin/init.js",
13
13
  "types": "./dist/bin/init.d.ts",
@@ -37,6 +37,10 @@
37
37
  "types": "./dist/bin/init.d.ts",
38
38
  "import": "./dist/bin/init.js"
39
39
  },
40
+ "./adapter": {
41
+ "types": "./dist/adapter.d.ts",
42
+ "import": "./dist/adapter.js"
43
+ },
40
44
  "./i18n/*.json": "./i18n/*.json",
41
45
  "./schemas/*.json": "./schemas/*.json",
42
46
  "./manifest.json": "./manifest.json"
@@ -47,7 +51,7 @@
47
51
  "dependencies": {
48
52
  "ajv": "^8.17.1",
49
53
  "ajv-formats": "^3.0.1",
50
- "@llodev/pm-tasks-core": "^1.8.0"
54
+ "@llodev/pm-tasks-core": "^1.12.0"
51
55
  },
52
56
  "publishConfig": {
53
57
  "access": "public"
@@ -141,6 +141,7 @@
141
141
  "items": {
142
142
  "enum": [
143
143
  "task.create",
144
+ "task.move",
144
145
  "checklist.check",
145
146
  "task.close",
146
147
  "task.due-date.set",