@llodev/pm-tasks-asana 1.3.0 → 1.4.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,68 @@
1
1
  # @llodev/pm-tasks-asana
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - v1.5.0 — Adapters TypeScript migration, @llodev/pm-tasks-testkit, 7th canonical verb `task.move`, E2E canary.
8
+
9
+ **Core (`@llodev/pm-tasks-core` 1.4.0 → 1.5.0)** — adds the 7th canonical verb `task.move` to the public contract.
10
+
11
+ - 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.
12
+ - `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`).
13
+ - Schema regex updated to recognize `task.move` as canonical (no namespace prefix required).
14
+ - `pm-tasks-core/schemas/adapter-manifest.schema.json` + `references/contract.md` + `references/crud-vocabulary.md` + `references/autonomous-mode.md` updated.
15
+ - Contract-check (`scripts/checks/contract-check.mjs`) `CANONICAL_VERBS` Set updated; regression test added.
16
+ - Additive only — existing consumers calling the original 6 verbs continue to work unchanged.
17
+
18
+ **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.
19
+
20
+ - Source moved from `scripts/init.mjs` to `src/bin/init.ts` (strict TS).
21
+ - 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.
22
+ - `package.json` exports map points at compiled `dist/`; `bin` field exposes `npx @llodev/pm-tasks-<tool> init`.
23
+ - i18n parity tests migrated from `node:test` to Vitest 2.x (2/2 tests per adapter).
24
+ - Both adapters now declare `task.move` in their `manifest.json` `verbs` array (7 canonical verbs) and document the MCP mapping in `references/operations.md`:
25
+ - Trello: `mcp__trello__move_card({ cardId, idList })` resolving `"wip"`/`"done"`/`"open"` from `lists.<alias>` in `.trello.json`.
26
+ - Asana: `mcp__claude_ai_Asana__update_tasks` with `memberships: [{ project, section }]` resolving via `defaults.<state>SectionAlias` in `.asana.json`.
27
+ - Trello autonomous overlay (`pm-tasks-trello/references/autonomous.md`) updated to invoke canonical `task.move` at task start and before task close.
28
+ - Backwards compatibility: consumers keep importing `@llodev/pm-tasks-core/init-lib` via the subpath; resolution now hits the v1.5.0 dist.
29
+
30
+ **Testkit (`@llodev/pm-tasks-testkit` 0.0.0 → 0.1.0)** — new package, first release.
31
+
32
+ - 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`.
33
+ - `createFakeAdapter({ idGenerator?, clock? })` returns an adapter-shaped object with all 7 verbs plus introspection (`getTask`, `getAllTasks`, `reset`).
34
+ - `peerDependencies`: `@llodev/pm-tasks-core ^1.4.0`.
35
+ - Useful for testing custom skills/adapters without hitting real MCP servers; 14/14 vitest tests cover each fake's behavior and idempotency.
36
+
37
+ **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.
38
+
39
+ **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.
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies []:
44
+ - @llodev/pm-tasks-core@1.5.0
45
+
46
+ ## 1.3.1
47
+
48
+ ### Patch Changes
49
+
50
+ - chore: reorganize repo structure
51
+
52
+ Pure chore release. Zero runtime change. Splits across:
53
+
54
+ - Reorganized root `scripts/` into `checks/`, `snapshots/`, `shell/` subfolders.
55
+ - Dropped `SKILL.{pt-BR,es-ES}.md` translations (agents read canonical EN-only per agentskills.io spec).
56
+ - Moved localized READMEs to `docs/i18n/` in root + each package (anticipates 5+ locales without cluttering package roots).
57
+ - Updated validators (`validate-localized-paths.mjs`) and tarball snapshot for new paths.
58
+
59
+ 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.
60
+
61
+ Meta package `@llodev/pm-tasks` not bumped — no tarball content changes, only peerDeps inheritance.
62
+
63
+ - Updated dependencies []:
64
+ - @llodev/pm-tasks-core@1.3.2
65
+
3
66
  ## 1.3.0
4
67
 
5
68
  ### Minor Changes
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
2
  <p align="center">
3
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/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/README.es-ES.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/spain.svg" width="30" alt="Español"></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>&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>
6
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
package/SKILL.md CHANGED
@@ -9,13 +9,13 @@ description: >-
9
9
  --auto sentinel. Asana hierarchy: workspace > project > section > parent task
10
10
  > subtasks (one level), with custom fields and multi-assignee support. Modes:
11
11
  paste-ready (no MCP needed), MCP publish (via claude.ai Asana MCP), autonomous
12
- (write-through with allowlist). Implements 6 CRUD verbs (task.create,
13
- checklist.check, task.close, task.due-date.set, task.assignee.add,
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
14
  task.comment.add) from pm-tasks/pm-tasks-core/references/contract.md. Requires
15
15
  @llodev/pm-tasks-core installed.
16
16
  license: MIT
17
17
  metadata:
18
- version: 1.3.0
18
+ version: 1.4.0
19
19
  tags:
20
20
  - agent-skill
21
21
  - asana
@@ -34,14 +34,6 @@ compatibility:
34
34
  - roo-code
35
35
  ---
36
36
 
37
- <!-- readme-selector:start -->
38
- <p align="center">
39
- <a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/SKILL.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/usa.svg" width="30" alt="English"></a>&nbsp;&nbsp;
40
- <a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/SKILL.pt-BR.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/brazil.svg" width="30" alt="Português"></a>&nbsp;&nbsp;
41
- <a href="https://github.com/llodev/skills/blob/main/pm-tasks/pm-tasks-asana/SKILL.es-ES.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/spain.svg" width="30" alt="Español"></a>
42
- </p>
43
- <!-- readme-selector:end -->
44
-
45
37
  # pm-tasks-asana
46
38
 
47
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.
@@ -111,14 +103,14 @@ Mandatory when the controller is executing a plan with multiple tasks autonomous
111
103
 
112
104
  Asana-specific verb mapping:
113
105
 
114
- | Transition | MCP call(s) |
115
- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
116
- | Task start | `mcp__asana__update_tasks { task: <gid>, add_projects: [{ project_id, section_id: <wipSectionGid> }] }` |
117
- | Step complete (subtask) | `mcp__asana__update_tasks { task: <subtaskGid>, completed: true }` |
118
- | Task complete (full) | `mcp__asana__add_comment { task_id: <parentGid>, text: "🤖 [agent] Task complete. Commit: <SHA>. <branch>." }` then `mcp__asana__update_tasks { task: <parentGid>, completed: true, add_projects: [{ project_id, section_id: <doneSectionGid> }] }` |
119
- | Task failed | `mcp__asana__add_comment` with failure mode + `mcp__asana__update_tasks { task: <gid>, add_followers: ["<escalateToAliasGid>"] }` for human escalation. Do NOT close. |
106
+ | Transition | Canonical verb + MCP call(s) |
107
+ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
108
+ | Task start | `task.move(cardId, "wip")` → `mcp__claude_ai_Asana__update_tasks { task: <gid>, memberships: [{ project: <projectGid>, section: <wipSectionGid> }] }` |
109
+ | Step complete (subtask) | `checklist.check` → `mcp__claude_ai_Asana__update_tasks { task: <subtaskGid>, completed: true }` |
110
+ | 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 }` |
111
+ | 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`. |
120
112
 
121
- Resolve `<wipSectionGid>` / `<doneSectionGid>` from `.asana.json` `sections[]` by alias (`wip`, `done`, or `closeSectionAlias` from `defaults`). Both must already be in `autonomous.scope.sections` — otherwise the verb returns `OUT_OF_SCOPE`.
113
+ 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`.
122
114
 
123
115
  **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.
124
116
 
@@ -126,14 +118,15 @@ Resolve `<wipSectionGid>` / `<doneSectionGid>` from `.asana.json` `sections[]` b
126
118
 
127
119
  For verbs other than `task.create`, jump directly to the operation. Verb → MCP tool mapping:
128
120
 
129
- | Core verb | Asana MCP tool | Notes |
130
- | ------------------- | ------------------------------ | --------------------------------------------------------------------- |
131
- | `task.create` | `create_tasks` | parent + subtasks per Phase 5 |
132
- | `checklist.check` | `update_tasks` | for subtasks: `completed: true`; emulates checklist via subtask model |
133
- | `task.close` | `update_tasks` | `completed: true` on parent |
134
- | `task.due-date.set` | `update_tasks` | `due_on: "YYYY-MM-DD"` |
135
- | `task.assignee.add` | `update_tasks` + `addFollower` | primary assignee replaces; additional are followers |
136
- | `task.comment.add` | `add_comment` (story) | adds a comment story to the task; apply attribution prefix if enabled |
121
+ | Core verb | Asana MCP tool | Notes |
122
+ | ------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
123
+ | `task.create` | `create_tasks` | parent + subtasks per Phase 5 |
124
+ | `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. |
125
+ | `checklist.check` | `update_tasks` | for subtasks: `completed: true`; emulates checklist via subtask model |
126
+ | `task.close` | `update_tasks` | `completed: true` on parent |
127
+ | `task.due-date.set` | `update_tasks` | `due_on: "YYYY-MM-DD"` |
128
+ | `task.assignee.add` | `update_tasks` + `addFollower` | primary assignee replaces; additional are followers |
129
+ | `task.comment.add` | `add_comment` (story) | adds a comment story to the task; apply attribution prefix if enabled |
137
130
 
138
131
  `<task-ref>` resolution: accept Asana permalinks (`https://app.asana.com/0/<project>/<task>`), bare GIDs, or aliases from `.asana.json` `taskAliases[]`.
139
132
 
@@ -158,6 +151,7 @@ Asana-specific `details` per verb:
158
151
  | Verb | `details` fields |
159
152
  | ------------------- | ------------------------------------------------------------------------ |
160
153
  | `task.create` | `{ parentGid, subtaskGids[], projectGid, sectionGid?, customFields[]? }` |
154
+ | `task.move` | `{ taskGid, sectionGid, targetList }` |
161
155
  | `checklist.check` | `{ subtaskGid, completed: true }` |
162
156
  | `task.close` | `{ parentGid, completed: true }` |
163
157
  | `task.due-date.set` | `{ taskGid, due_on }` |
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/bin/init.ts"],"names":[],"mappings":""}
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env node
2
+ // pm-tasks-asana init — interactive config bootstrapper
3
+ import { readFile } from "node:fs/promises";
4
+ import { fileURLToPath } from "node:url";
5
+ import path from "node:path";
6
+ import { promptScope, promptYesNo, multiSelect, promptPick, aliasOf, writeConfig, validateConfig, probeMCP, printInstructions, promptLocale, loadStrings, registerI18nRoot, interpolate, } from "@llodev/pm-tasks-core/init-lib";
7
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
8
+ async function loadSchema() {
9
+ const raw = await readFile(path.join(ROOT, "schemas", "config.json"), "utf8");
10
+ return JSON.parse(raw);
11
+ }
12
+ // ---------------------------------------------------------------------------
13
+ // Helpers
14
+ // ---------------------------------------------------------------------------
15
+ async function asanaProbe() {
16
+ // The MCP runs in a different process. To probe within this script, call the
17
+ // Asana REST API directly with a Personal Access Token.
18
+ // Used only to enumerate workspaces / projects / sections / custom fields / members.
19
+ const TOKEN = process.env.LLODEV_PM_TASKS_ASANA_PAT;
20
+ if (!TOKEN)
21
+ throw new Error("auth: LLODEV_PM_TASKS_ASANA_PAT missing");
22
+ const j = async (p) => {
23
+ const r = await fetch(`https://app.asana.com/api/1.0${p}`, {
24
+ headers: { Authorization: `Bearer ${TOKEN}` },
25
+ });
26
+ if (!r.ok)
27
+ throw new Error(`HTTP ${r.status}`);
28
+ const body = (await r.json());
29
+ return body.data;
30
+ };
31
+ return {
32
+ getMe: () => j("/users/me?opt_fields=gid,name,email"),
33
+ getWorkspaces: () => j("/workspaces?opt_fields=name"),
34
+ getProjects: (workspaceGid) => j(`/projects?workspace=${workspaceGid}&opt_fields=name&limit=100`),
35
+ getSections: (projectGid) => j(`/projects/${projectGid}/sections?opt_fields=name&limit=100`),
36
+ getCustomFields: (projectGid) => j(`/projects/${projectGid}/custom_field_settings?opt_fields=custom_field.name,custom_field.gid,custom_field.resource_subtype,custom_field.enum_options.name,custom_field.enum_options.gid&limit=100`),
37
+ getMembers: (projectGid) => j(`/projects/${projectGid}/members?opt_fields=user.name,user.gid&limit=100`),
38
+ };
39
+ }
40
+ async function promptManualMember(asanaStrings) {
41
+ const { createInterface } = await import("node:readline/promises");
42
+ const { stdin: input, stdout: output } = await import("node:process");
43
+ const r = createInterface({ input, output });
44
+ try {
45
+ const gid = (await r.question(asanaStrings.manualMemberGid)).trim();
46
+ if (!gid)
47
+ return null;
48
+ const name = (await r.question(asanaStrings.manualMemberName)).trim() || "owner";
49
+ const alias = (await r.question(asanaStrings.manualMemberAlias)).trim() || "owner";
50
+ return { id: gid, name, alias };
51
+ }
52
+ finally {
53
+ r.close();
54
+ }
55
+ }
56
+ async function collectEscalationMember(out, { coreStrings, asanaStrings }) {
57
+ const candidates = out.members.filter((m) => m.alias !== "me");
58
+ if (candidates.length) {
59
+ const choices = candidates.map((m) => ({ label: `${m.name} (${m.alias})`, value: m }));
60
+ const picked = await promptPick(asanaStrings.escalationPrompt, choices, {
61
+ defaultIndex: 0,
62
+ allowSkip: true,
63
+ strings: coreStrings,
64
+ });
65
+ if (picked) {
66
+ if (picked.alias !== "owner") {
67
+ if (!out.members.find((m) => m.alias === "owner"))
68
+ picked.alias = "owner";
69
+ }
70
+ out.defaults.escalateToAlias = picked.alias;
71
+ }
72
+ return;
73
+ }
74
+ const add = await promptYesNo(asanaStrings.noMembersPrompt, { strings: coreStrings });
75
+ if (!add)
76
+ return;
77
+ const manual = await promptManualMember(asanaStrings);
78
+ if (!manual)
79
+ return;
80
+ out.members.push(manual);
81
+ out.defaults.escalateToAlias = manual.alias;
82
+ }
83
+ function mapResourceType(subtype) {
84
+ switch (subtype) {
85
+ case "enum":
86
+ return "enum";
87
+ case "multi_enum":
88
+ return "multi_enum";
89
+ case "number":
90
+ return "number";
91
+ case "date":
92
+ return "date";
93
+ case "people":
94
+ return "people";
95
+ default:
96
+ return "text";
97
+ }
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // Main
101
+ // ---------------------------------------------------------------------------
102
+ async function run() {
103
+ registerI18nRoot("asana", path.join(ROOT, "i18n"));
104
+ const locale = await promptLocale("core", { defaultLocale: "en-US" });
105
+ const coreStrings = await loadStrings("core", locale);
106
+ const asanaStrings = await loadStrings("asana", locale);
107
+ console.log(`\n${asanaStrings.header}\n`);
108
+ const { path: outPath } = await promptScope("asana", { strings: coreStrings });
109
+ const probe = await probeMCP({
110
+ tool: "asana",
111
+ probeCommand: async () => {
112
+ const api = await asanaProbe();
113
+ await api.getMe();
114
+ return api;
115
+ },
116
+ });
117
+ if (probe.unauthenticated) {
118
+ printInstructions([asanaStrings.patMissingTitle, asanaStrings.patMissingBody]);
119
+ return;
120
+ }
121
+ if (!probe.mcpAvailable) {
122
+ printInstructions([asanaStrings.mcpMissingTitle, asanaStrings.mcpMissingBody]);
123
+ return;
124
+ }
125
+ const api = probe.result;
126
+ const me = await api.getMe();
127
+ const workspaces = await api.getWorkspaces();
128
+ const pickedWorkspaces = await multiSelect(asanaStrings.workspacePrompt, workspaces.map((w) => ({ label: `${w.name} (${w.gid})`, value: w })), { strings: coreStrings });
129
+ if (!pickedWorkspaces.length) {
130
+ console.error(asanaStrings.noWorkspace);
131
+ process.exit(1);
132
+ }
133
+ const workspace = pickedWorkspaces[0];
134
+ const projects = await api.getProjects(workspace.gid);
135
+ const pickedProjects = await multiSelect(interpolate(asanaStrings.projectsPrompt, { workspace: workspace.name }), projects.map((p) => ({ label: `${p.name} (${p.gid})`, value: p })), { strings: coreStrings });
136
+ if (!pickedProjects.length) {
137
+ console.error(asanaStrings.noProject);
138
+ process.exit(1);
139
+ }
140
+ const out = {
141
+ $schema: "https://llodev.github.io/skills/schemas/pm-tasks-asana.json",
142
+ version: "1",
143
+ locale,
144
+ workspace: { id: workspace.gid, name: workspace.name },
145
+ projects: [],
146
+ sections: [],
147
+ customFields: [],
148
+ members: [{ id: me.gid, name: me.name, email: me.email, alias: "me" }],
149
+ defaults: {},
150
+ };
151
+ const inheritFieldIds = new Set();
152
+ for (const p of pickedProjects) {
153
+ const alias = aliasOf(p.name);
154
+ out.projects.push({ id: p.gid, name: p.name, alias });
155
+ const sections = await api.getSections(p.gid);
156
+ const pickedSections = await multiSelect(interpolate(asanaStrings.sectionsPrompt, { project: p.name }), sections.map((s) => ({ label: s.name, value: s })), { strings: coreStrings });
157
+ for (const s of pickedSections) {
158
+ out.sections.push({
159
+ projectAlias: alias,
160
+ id: s.gid,
161
+ name: s.name,
162
+ alias: aliasOf(s.name),
163
+ });
164
+ }
165
+ const cfSettings = await api.getCustomFields(p.gid);
166
+ const fields = cfSettings
167
+ .map((cs) => cs.custom_field)
168
+ .filter((f) => f !== null);
169
+ if (fields.length) {
170
+ const pickedFields = await multiSelect(interpolate(asanaStrings.customFieldsPrompt, { project: p.name }), fields.map((f) => ({ label: `${f.name} [${f.resource_subtype}]`, value: f })), { strings: coreStrings });
171
+ for (const f of pickedFields) {
172
+ const entry = {
173
+ projectAlias: alias,
174
+ id: f.gid,
175
+ name: f.name,
176
+ type: mapResourceType(f.resource_subtype),
177
+ alias: aliasOf(f.name),
178
+ };
179
+ if (Array.isArray(f.enum_options) && f.enum_options.length) {
180
+ entry.options = f.enum_options.map((opt) => ({
181
+ id: opt.gid,
182
+ name: opt.name,
183
+ alias: aliasOf(opt.name),
184
+ }));
185
+ }
186
+ out.customFields.push(entry);
187
+ }
188
+ if (pickedFields.length) {
189
+ const inheritPicked = await multiSelect(asanaStrings.inheritPrompt, pickedFields.map((f) => ({ label: f.name, value: f })), { strings: coreStrings });
190
+ for (const f of inheritPicked)
191
+ inheritFieldIds.add(f.gid);
192
+ }
193
+ }
194
+ try {
195
+ const memberships = await api.getMembers(p.gid);
196
+ const users = memberships.map((m) => m.user).filter((u) => u !== null);
197
+ for (const u of users) {
198
+ if (u.gid === me.gid)
199
+ continue;
200
+ if (out.members.find((m) => m.id === u.gid))
201
+ continue;
202
+ out.members.push({ id: u.gid, name: u.name, alias: aliasOf(u.name) });
203
+ }
204
+ }
205
+ catch (_e) {
206
+ // Project membership listing may require additional scopes; skip silently.
207
+ }
208
+ }
209
+ if (out.projects.length === 1) {
210
+ out.defaults.projectAlias = out.projects[0].alias;
211
+ out.defaults.assigneeAlias = "me";
212
+ const sectionChoices = out.sections.map((s) => ({
213
+ label: `${s.name} (${s.alias})`,
214
+ value: s,
215
+ }));
216
+ if (sectionChoices.length) {
217
+ const open = await promptPick(asanaStrings.openSectionPrompt, sectionChoices, {
218
+ defaultIndex: 0,
219
+ allowSkip: true,
220
+ strings: coreStrings,
221
+ });
222
+ if (open)
223
+ out.defaults.sectionAlias = open.alias;
224
+ const close = await promptPick(asanaStrings.closeSectionPrompt, sectionChoices, {
225
+ defaultIndex: sectionChoices.length - 1,
226
+ allowSkip: true,
227
+ strings: coreStrings,
228
+ });
229
+ if (close)
230
+ out.defaults.closeSectionAlias = close.alias;
231
+ }
232
+ }
233
+ await collectEscalationMember(out, { coreStrings, asanaStrings });
234
+ if (inheritFieldIds.size) {
235
+ out.subtaskDefaults = {
236
+ inheritParentFields: [...inheritFieldIds],
237
+ inheritAssignee: true,
238
+ };
239
+ }
240
+ const wantAuto = await promptYesNo(coreStrings.autonomousPromptQuestion, {
241
+ strings: coreStrings,
242
+ });
243
+ if (wantAuto) {
244
+ out.autonomous = {
245
+ enabled: false,
246
+ allow: ["task.create", "checklist.check", "task.close", "task.comment.add"],
247
+ scope: {
248
+ projects: out.projects.map((p) => p.id),
249
+ sections: out.sections.map((s) => s.id),
250
+ },
251
+ rateLimit: { writesPerMinute: 30, commentsPerMinute: 10 },
252
+ auditLog: "~/.local/share/llodev/pm-tasks/asana/audit.log",
253
+ };
254
+ printInstructions([coreStrings.autonomousAddedTitle, coreStrings.autonomousReviewBody]);
255
+ }
256
+ const schema = await loadSchema();
257
+ const valid = await validateConfig(out, schema);
258
+ if (!valid.ok) {
259
+ console.error(`${coreStrings.errInvalidConfig}:`, JSON.stringify(valid.errors, null, 2));
260
+ process.exit(1);
261
+ }
262
+ await writeConfig(outPath, out);
263
+ printInstructions([
264
+ interpolate(coreStrings.configWritten, { path: outPath }),
265
+ asanaStrings.tryItTitle,
266
+ asanaStrings.tokenReminderTitle,
267
+ asanaStrings.tokenReminderBody,
268
+ ]);
269
+ }
270
+ run().catch((e) => {
271
+ console.error(e);
272
+ process.exit(1);
273
+ });
274
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/bin/init.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
2
  <p align="center">
3
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/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/README.es-ES.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/spain.svg" width="30" alt="Español"></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>&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>
6
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
@@ -11,7 +11,7 @@
11
11
  > Adapter para Asana de la familia `@llodev/pm-tasks-*` — convierte planes de implementación en parent tasks + subtasks de Asana y los opera mediante paste, MCP publish o autonomous write-through.
12
12
 
13
13
  [![npm](https://img.shields.io/npm/v/@llodev/pm-tasks-asana?label=npm&color=cb3837&logo=npm)](https://www.npmjs.com/package/@llodev/pm-tasks-asana)
14
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
15
15
  [![Node.js >= 20](https://img.shields.io/badge/node-%3E%3D20-43853d?logo=node.js&logoColor=white)](https://nodejs.org)
16
16
  [![Agent Skills spec](https://img.shields.io/badge/Agent_Skills-spec-7c5cff)](https://agentskills.io)
17
17
 
@@ -86,15 +86,15 @@ El prompt de `init` imprime la ruta absoluta donde va a escribir, así siempre v
86
86
  > **Los custom fields NO se heredan por defecto** — lista los IDs de field en `subtaskDefaults.inheritParentFields` para que el adapter los copie del parent a las subtasks en el momento del create.
87
87
 
88
88
  - **Assignee es un campo único** — usa `task.assignee.add` para añadir followers; el assignee principal se reemplaza en caso de conflicto.
89
- - **El `get_task` del MCP no devuelve activity stories** — el activity feed de la UI de Asana es la fuente de verdad para auditorías de atribución. Mira [`anti-patterns/asana.md`](./anti-patterns/asana.md).
89
+ - **El `get_task` del MCP no devuelve activity stories** — el activity feed de la UI de Asana es la fuente de verdad para auditorías de atribución. Mira [`anti-patterns/asana.md`](../../anti-patterns/asana.md).
90
90
 
91
91
  ## Documentación
92
92
 
93
- - [`SKILL.md`](./SKILL.md) — enrutado de phases + vocabulario CRUD.
94
- - [`schemas/config.json`](./schemas/config.json) — JSON Schema de `.asana.json`.
95
- - [`anti-patterns/asana.md`](./anti-patterns/asana.md) — gotchas recurrentes.
96
- - [`../pm-tasks-core/references/autonomous-mode.md`](../pm-tasks-core/references/autonomous-mode.md) — contrato de autonomous mode.
93
+ - [`SKILL.md`](../../SKILL.md) — enrutado de phases + vocabulario CRUD.
94
+ - [`schemas/config.json`](../../schemas/config.json) — JSON Schema de `.asana.json`.
95
+ - [`anti-patterns/asana.md`](../../anti-patterns/asana.md) — gotchas recurrentes.
96
+ - [`../pm-tasks-core/references/autonomous-mode.md`](../../../pm-tasks-core/references/autonomous-mode.md) — contrato de autonomous mode.
97
97
 
98
98
  ## Licencia
99
99
 
100
- MIT — mira [LICENSE](./LICENSE).
100
+ MIT — mira [LICENSE](../../LICENSE).
@@ -1,8 +1,8 @@
1
1
  <!-- readme-selector:start -->
2
2
  <p align="center">
3
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/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/README.es-ES.md"><img src="https://raw.githubusercontent.com/lloliveiradev/public-assets/main/images/spain.svg" width="30" alt="Español"></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>&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>
6
6
  </p>
7
7
  <!-- readme-selector:end -->
8
8
 
@@ -11,7 +11,7 @@
11
11
  > Adapter para Asana da família `@llodev/pm-tasks-*` — transforma planos de implementação em parent tasks + subtasks no Asana e opera via paste, MCP publish ou autonomous write-through.
12
12
 
13
13
  [![npm](https://img.shields.io/npm/v/@llodev/pm-tasks-asana?label=npm&color=cb3837&logo=npm)](https://www.npmjs.com/package/@llodev/pm-tasks-asana)
14
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE)
15
15
  [![Node.js >= 20](https://img.shields.io/badge/node-%3E%3D20-43853d?logo=node.js&logoColor=white)](https://nodejs.org)
16
16
  [![Agent Skills spec](https://img.shields.io/badge/Agent_Skills-spec-7c5cff)](https://agentskills.io)
17
17
 
@@ -86,15 +86,15 @@ O prompt de `init` imprime o caminho absoluto onde vai escrever, então você se
86
86
  > **Custom fields NÃO são herdados por default** — liste os IDs de field em `subtaskDefaults.inheritParentFields` para que o adapter copie do parent para as subtasks no momento do create.
87
87
 
88
88
  - **Assignee é um campo único** — use `task.assignee.add` para adicionar followers; o assignee primário é substituído em caso de conflito.
89
- - **O `get_task` do MCP não retorna activity stories** — o activity feed da UI do Asana é a fonte de verdade para auditorias de atribuição. Veja [`anti-patterns/asana.md`](./anti-patterns/asana.md).
89
+ - **O `get_task` do MCP não retorna activity stories** — o activity feed da UI do Asana é a fonte de verdade para auditorias de atribuição. Veja [`anti-patterns/asana.md`](../../anti-patterns/asana.md).
90
90
 
91
91
  ## Documentação
92
92
 
93
- - [`SKILL.md`](./SKILL.md) — roteamento de phases + vocabulário CRUD.
94
- - [`schemas/config.json`](./schemas/config.json) — JSON Schema do `.asana.json`.
95
- - [`anti-patterns/asana.md`](./anti-patterns/asana.md) — pegadinhas recorrentes.
96
- - [`../pm-tasks-core/references/autonomous-mode.md`](../pm-tasks-core/references/autonomous-mode.md) — contrato do autonomous mode.
93
+ - [`SKILL.md`](../../SKILL.md) — roteamento de phases + vocabulário CRUD.
94
+ - [`schemas/config.json`](../../schemas/config.json) — JSON Schema do `.asana.json`.
95
+ - [`anti-patterns/asana.md`](../../anti-patterns/asana.md) — pegadinhas recorrentes.
96
+ - [`../pm-tasks-core/references/autonomous-mode.md`](../../../pm-tasks-core/references/autonomous-mode.md) — contrato do autonomous mode.
97
97
 
98
98
  ## Licença
99
99
 
100
- MIT — veja [LICENSE](./LICENSE).
100
+ MIT — veja [LICENSE](../../LICENSE).
package/manifest.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "tool": "asana",
3
3
  "verbs": [
4
4
  "task.create",
5
+ "task.move",
5
6
  "task.close",
6
7
  "task.due-date.set",
7
8
  "task.assignee.add",