@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.
@@ -0,0 +1,62 @@
1
+ # Asana ingestion anti-patterns
2
+
3
+ Apply when Phase 4 / Phase 5 / Phase 5b target Asana. Authoritative formatting + publish detail lives in [`../SKILL.md`](../SKILL.md).
4
+
5
+ ---
6
+
7
+ ## Paste health and fallbacks
8
+
9
+ | Healthy paste | If it degrades → fallback |
10
+ | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
11
+ | Prefer `**Section**` in task descriptions when `##` headings are unreliable; **only one** nesting level for subtasks. | Swap heading hierarchy for bold labels; split deep trees into sibling tasks. See [`../SKILL.md`](../SKILL.md) §Asana model. |
12
+
13
+ **Switching tools mid-thread:** re-load the new tool's adapter; do not carry Asana rules into Trello / Jira / Linear (see **Cross-tool** below).
14
+
15
+ ---
16
+
17
+ ## Asana
18
+
19
+ **NEVER** rely on `## Heading` hierarchy alone in descriptions for teams that proved **headings don't render**. **Why:** Asana rich-text inconsistency across clients; bold section labels (`**Deliverables**`) are safer fallback per [`../SKILL.md`](../SKILL.md) §Asana model.
20
+
21
+ **NEVER** model **multiple nesting levels** of subtasks beyond what Asana supports (one level of subtasks natively). **Why:** falsely implies hierarchy; flatten or split tasks.
22
+
23
+ **NEVER** put **Out of scope** or **Next step** into published Asana descriptions. **Why:** deferred work stays in the plan file, not in the task body.
24
+
25
+ **NEVER** call `create_tasks` / `create_task_preview_v4` before the user confirms the Phase 5 preview. **Why:** creates real workspace objects without approval.
26
+
27
+ **NEVER** use `create_task_preview_v4` as the default path for a full phase card with many checklist lines. **Why:** inline subtasks cap at 5; use parent + batched `create_tasks` with `parent` instead.
28
+
29
+ **NEVER** pass custom field **display names** (e.g. `"Discovery"`, `"Medium"`) in `custom_fields` to MCP — only **field GID → option GID** pairs resolved from `.asana.json`. **Why:** the API returns 400; display names drift between Asana UI edits and the config file.
30
+
31
+ **NEVER** guess `project.id`, `section.id`, or custom field GIDs when `.asana.json` exists. **Why:** stale or invented GIDs silently create tasks in the wrong project or column; always read the file or refresh via `get_project`.
32
+
33
+ **NEVER** send `custom_fields` as an **object** on `create_tasks` — it must be a **JSON string**; object form is only valid for `update_tasks`. **Why:** the tool schemas differ; wrong format causes silent failure or a 400 error.
34
+
35
+ **NEVER** set `section_id` without also setting `project_id` / `default_project`. **Why:** Asana API requires project context for section placement.
36
+
37
+ ---
38
+
39
+ ## Cross-tool
40
+
41
+ **NEVER** apply Asana's quirks to another adapter after switching targets mid-chat. **Why:** the user said "actually use Trello" — re-load that adapter and apply only its rules.
42
+
43
+ ---
44
+
45
+ ## UI is the source of truth for activity attribution
46
+
47
+ The MCP's `mcp__asana__get_task` returns user-authored comments but does NOT return activity stories (creation, section moves, assignee changes, custom-field edits, follower changes). Programmatic verification of attribution is therefore incomplete by design.
48
+
49
+ When auditing whether an agent action was correctly attributed to the agent account (not the human account), open the task in the Asana UI and inspect the activity feed. Do not infer attribution from the MCP response.
50
+
51
+ ## Subtasks do NOT inherit custom fields automatically
52
+
53
+ Asana itself does not propagate `custom_fields` from a parent task to its subtasks at create time, regardless of project-level defaults. The adapter MUST replicate the parent's selected `inheritParentFields` (declared in `.asana.json` under `subtaskDefaults`) when creating each subtask:
54
+
55
+ ```javascript
56
+ await createSubtasks({
57
+ parent: parentGid,
58
+ custom_fields: pick(parent.custom_fields, config.subtaskDefaults.inheritParentFields),
59
+ });
60
+ ```
61
+
62
+ Failing to do this leaves subtasks with empty custom fields even when the parent had them set.
@@ -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,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,280 @@
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
+ const argv = process.argv.slice(2);
104
+ if (argv.includes("--doctor")) {
105
+ const { runDoctor } = await import("../doctor-cli.js");
106
+ await runDoctor({ tool: "asana", argv });
107
+ return;
108
+ }
109
+ registerI18nRoot("asana", path.join(ROOT, "i18n"));
110
+ const locale = await promptLocale("core", { defaultLocale: "en-US" });
111
+ const coreStrings = await loadStrings("core", locale);
112
+ const asanaStrings = await loadStrings("asana", locale);
113
+ console.log(`\n${asanaStrings.header}\n`);
114
+ const { path: outPath } = await promptScope("asana", { strings: coreStrings });
115
+ const probe = await probeMCP({
116
+ tool: "asana",
117
+ probeCommand: async () => {
118
+ const api = await asanaProbe();
119
+ await api.getMe();
120
+ return api;
121
+ },
122
+ });
123
+ if (probe.unauthenticated) {
124
+ printInstructions([asanaStrings.patMissingTitle, asanaStrings.patMissingBody]);
125
+ return;
126
+ }
127
+ if (!probe.mcpAvailable) {
128
+ printInstructions([asanaStrings.mcpMissingTitle, asanaStrings.mcpMissingBody]);
129
+ return;
130
+ }
131
+ const api = probe.result;
132
+ const me = await api.getMe();
133
+ const workspaces = await api.getWorkspaces();
134
+ const pickedWorkspaces = await multiSelect(asanaStrings.workspacePrompt, workspaces.map((w) => ({ label: `${w.name} (${w.gid})`, value: w })), { strings: coreStrings });
135
+ if (!pickedWorkspaces.length) {
136
+ console.error(asanaStrings.noWorkspace);
137
+ process.exit(1);
138
+ }
139
+ const workspace = pickedWorkspaces[0];
140
+ const projects = await api.getProjects(workspace.gid);
141
+ const pickedProjects = await multiSelect(interpolate(asanaStrings.projectsPrompt, { workspace: workspace.name }), projects.map((p) => ({ label: `${p.name} (${p.gid})`, value: p })), { strings: coreStrings });
142
+ if (!pickedProjects.length) {
143
+ console.error(asanaStrings.noProject);
144
+ process.exit(1);
145
+ }
146
+ const out = {
147
+ $schema: "https://llodev.github.io/skills/schemas/pm-tasks-asana.json",
148
+ version: "1",
149
+ locale,
150
+ workspace: { id: workspace.gid, name: workspace.name },
151
+ projects: [],
152
+ sections: [],
153
+ customFields: [],
154
+ members: [{ id: me.gid, name: me.name, email: me.email, alias: "me" }],
155
+ defaults: {},
156
+ };
157
+ const inheritFieldIds = new Set();
158
+ for (const p of pickedProjects) {
159
+ const alias = aliasOf(p.name);
160
+ out.projects.push({ id: p.gid, name: p.name, alias });
161
+ const sections = await api.getSections(p.gid);
162
+ const pickedSections = await multiSelect(interpolate(asanaStrings.sectionsPrompt, { project: p.name }), sections.map((s) => ({ label: s.name, value: s })), { strings: coreStrings });
163
+ for (const s of pickedSections) {
164
+ out.sections.push({
165
+ projectAlias: alias,
166
+ id: s.gid,
167
+ name: s.name,
168
+ alias: aliasOf(s.name),
169
+ });
170
+ }
171
+ const cfSettings = await api.getCustomFields(p.gid);
172
+ const fields = cfSettings
173
+ .map((cs) => cs.custom_field)
174
+ .filter((f) => f !== null);
175
+ if (fields.length) {
176
+ const pickedFields = await multiSelect(interpolate(asanaStrings.customFieldsPrompt, { project: p.name }), fields.map((f) => ({ label: `${f.name} [${f.resource_subtype}]`, value: f })), { strings: coreStrings });
177
+ for (const f of pickedFields) {
178
+ const entry = {
179
+ projectAlias: alias,
180
+ id: f.gid,
181
+ name: f.name,
182
+ type: mapResourceType(f.resource_subtype),
183
+ alias: aliasOf(f.name),
184
+ };
185
+ if (Array.isArray(f.enum_options) && f.enum_options.length) {
186
+ entry.options = f.enum_options.map((opt) => ({
187
+ id: opt.gid,
188
+ name: opt.name,
189
+ alias: aliasOf(opt.name),
190
+ }));
191
+ }
192
+ out.customFields.push(entry);
193
+ }
194
+ if (pickedFields.length) {
195
+ const inheritPicked = await multiSelect(asanaStrings.inheritPrompt, pickedFields.map((f) => ({ label: f.name, value: f })), { strings: coreStrings });
196
+ for (const f of inheritPicked)
197
+ inheritFieldIds.add(f.gid);
198
+ }
199
+ }
200
+ try {
201
+ const memberships = await api.getMembers(p.gid);
202
+ const users = memberships.map((m) => m.user).filter((u) => u !== null);
203
+ for (const u of users) {
204
+ if (u.gid === me.gid)
205
+ continue;
206
+ if (out.members.find((m) => m.id === u.gid))
207
+ continue;
208
+ out.members.push({ id: u.gid, name: u.name, alias: aliasOf(u.name) });
209
+ }
210
+ }
211
+ catch (_e) {
212
+ // Project membership listing may require additional scopes; skip silently.
213
+ }
214
+ }
215
+ if (out.projects.length === 1) {
216
+ out.defaults.projectAlias = out.projects[0].alias;
217
+ out.defaults.assigneeAlias = "me";
218
+ const sectionChoices = out.sections.map((s) => ({
219
+ label: `${s.name} (${s.alias})`,
220
+ value: s,
221
+ }));
222
+ if (sectionChoices.length) {
223
+ const open = await promptPick(asanaStrings.openSectionPrompt, sectionChoices, {
224
+ defaultIndex: 0,
225
+ allowSkip: true,
226
+ strings: coreStrings,
227
+ });
228
+ if (open)
229
+ out.defaults.sectionAlias = open.alias;
230
+ const close = await promptPick(asanaStrings.closeSectionPrompt, sectionChoices, {
231
+ defaultIndex: sectionChoices.length - 1,
232
+ allowSkip: true,
233
+ strings: coreStrings,
234
+ });
235
+ if (close)
236
+ out.defaults.closeSectionAlias = close.alias;
237
+ }
238
+ }
239
+ await collectEscalationMember(out, { coreStrings, asanaStrings });
240
+ if (inheritFieldIds.size) {
241
+ out.subtaskDefaults = {
242
+ inheritParentFields: [...inheritFieldIds],
243
+ inheritAssignee: true,
244
+ };
245
+ }
246
+ const wantAuto = await promptYesNo(coreStrings.autonomousPromptQuestion, {
247
+ strings: coreStrings,
248
+ });
249
+ if (wantAuto) {
250
+ out.autonomous = {
251
+ enabled: false,
252
+ allow: ["task.create", "checklist.check", "task.close", "task.comment.add"],
253
+ scope: {
254
+ projects: out.projects.map((p) => p.id),
255
+ sections: out.sections.map((s) => s.id),
256
+ },
257
+ rateLimit: { writesPerMinute: 30, commentsPerMinute: 10 },
258
+ auditLog: "~/.local/share/llodev/pm-tasks/asana/audit.log",
259
+ };
260
+ printInstructions([coreStrings.autonomousAddedTitle, coreStrings.autonomousReviewBody]);
261
+ }
262
+ const schema = await loadSchema();
263
+ const valid = await validateConfig(out, schema);
264
+ if (!valid.ok) {
265
+ console.error(`${coreStrings.errInvalidConfig}:`, JSON.stringify(valid.errors, null, 2));
266
+ process.exit(1);
267
+ }
268
+ await writeConfig(outPath, out);
269
+ printInstructions([
270
+ interpolate(coreStrings.configWritten, { path: outPath }),
271
+ asanaStrings.tryItTitle,
272
+ asanaStrings.tokenReminderTitle,
273
+ asanaStrings.tokenReminderBody,
274
+ ]);
275
+ }
276
+ run().catch((e) => {
277
+ console.error(e);
278
+ process.exit(1);
279
+ });
280
+ //# 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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"}
@@ -0,0 +1,6 @@
1
+ export interface RunDoctorOpts {
2
+ tool: string;
3
+ argv: string[];
4
+ }
5
+ export declare function runDoctor({ argv }: RunDoctorOpts): Promise<void>;
6
+ //# sourceMappingURL=doctor-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-cli.d.ts","sourceRoot":"","sources":["../src/doctor-cli.ts"],"names":[],"mappings":"AAiIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAsB,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CtE"}
@@ -0,0 +1,166 @@
1
+ // pm-tasks-asana doctor-cli — adapter-specific health checks + runner
2
+ import { readFile } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import path from "node:path";
5
+ import { resolveDataDir } from "@llodev/pm-tasks-core/audit";
6
+ import { runChecks } from "@llodev/pm-tasks-core/doctor";
7
+ import { renderReport } from "@llodev/pm-tasks-core/bin/doctor";
8
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
+ // ---------------------------------------------------------------------------
10
+ // Asana-specific checks (C-ASN-1..3)
11
+ // ---------------------------------------------------------------------------
12
+ async function asanaFetch(urlPath, pat) {
13
+ try {
14
+ const res = await globalThis.fetch(`https://app.asana.com/api/1.0${urlPath}`, {
15
+ headers: { Authorization: `Bearer ${pat}` },
16
+ });
17
+ return { status: res.status, ok: res.ok };
18
+ }
19
+ catch (e) {
20
+ throw new Error(`network error: ${e.message}`);
21
+ }
22
+ }
23
+ const C_ASN_1 = {
24
+ id: "C-ASN-1",
25
+ label: "Asana REST /users/me returns 200",
26
+ severity: "error",
27
+ async run(_ctx) {
28
+ const pat = process.env.LLODEV_PM_TASKS_ASANA_PAT;
29
+ if (!pat) {
30
+ return {
31
+ ok: true,
32
+ message: "LLODEV_PM_TASKS_ASANA_PAT env var missing — skipping auth probe",
33
+ };
34
+ }
35
+ try {
36
+ const res = await asanaFetch("/users/me", pat);
37
+ if (res.ok) {
38
+ return { ok: true, message: "/users/me returned 200" };
39
+ }
40
+ return {
41
+ ok: false,
42
+ message: `/users/me returned HTTP ${res.status}`,
43
+ fixHint: "Re-generate your Asana personal access token.",
44
+ };
45
+ }
46
+ catch (e) {
47
+ return { ok: false, message: e.message };
48
+ }
49
+ },
50
+ };
51
+ const C_ASN_2 = {
52
+ id: "C-ASN-2",
53
+ label: "Configured projects resolve",
54
+ severity: "error",
55
+ async run(ctx) {
56
+ const pat = process.env.LLODEV_PM_TASKS_ASANA_PAT;
57
+ if (!pat) {
58
+ return {
59
+ ok: true,
60
+ message: "LLODEV_PM_TASKS_ASANA_PAT env var missing — skipping project probe",
61
+ };
62
+ }
63
+ const cfg = ctx.config;
64
+ const projects = cfg["projects"] ?? [];
65
+ const failures = [];
66
+ for (const proj of projects) {
67
+ const id = String(proj["id"]);
68
+ try {
69
+ const res = await asanaFetch(`/projects/${id}?opt_fields=gid`, pat);
70
+ if (!res.ok)
71
+ failures.push(`${id} (HTTP ${res.status})`);
72
+ }
73
+ catch (e) {
74
+ failures.push(`${id} (${e.message})`);
75
+ }
76
+ }
77
+ if (failures.length === 0) {
78
+ return { ok: true, message: `all ${projects.length} project(s) resolve` };
79
+ }
80
+ return {
81
+ ok: false,
82
+ message: `unresolvable projects: ${failures.join(", ")}`,
83
+ fixHint: "Verify the project GID still exists or remove from config.",
84
+ };
85
+ },
86
+ };
87
+ const C_ASN_3 = {
88
+ id: "C-ASN-3",
89
+ label: "Configured sections reachable",
90
+ severity: "error",
91
+ async run(ctx) {
92
+ const pat = process.env.LLODEV_PM_TASKS_ASANA_PAT;
93
+ if (!pat) {
94
+ return {
95
+ ok: true,
96
+ message: "LLODEV_PM_TASKS_ASANA_PAT env var missing — skipping section probe",
97
+ };
98
+ }
99
+ const cfg = ctx.config;
100
+ const sections = cfg["sections"] ?? [];
101
+ const failures = [];
102
+ for (const sec of sections) {
103
+ const id = String(sec["id"]);
104
+ try {
105
+ const res = await asanaFetch(`/sections/${id}?opt_fields=gid`, pat);
106
+ if (!res.ok)
107
+ failures.push(`${id} (HTTP ${res.status})`);
108
+ }
109
+ catch (e) {
110
+ failures.push(`${id} (${e.message})`);
111
+ }
112
+ }
113
+ if (failures.length === 0) {
114
+ return { ok: true, message: `all ${sections.length} section(s) reachable` };
115
+ }
116
+ return {
117
+ ok: false,
118
+ message: `unreachable sections: ${failures.join(", ")}`,
119
+ fixHint: "Verify the section GID still exists or remove from config.",
120
+ };
121
+ },
122
+ };
123
+ const ADAPTER_CHECKS = [C_ASN_1, C_ASN_2, C_ASN_3];
124
+ export async function runDoctor({ argv }) {
125
+ const jsonMode = argv.includes("--json");
126
+ const fixHintsOnly = argv.includes("--fix-hints-only");
127
+ // --config override
128
+ const configIdx = argv.indexOf("--config");
129
+ let configPath;
130
+ if (configIdx !== -1 && argv[configIdx + 1]) {
131
+ configPath = argv[configIdx + 1];
132
+ }
133
+ else {
134
+ configPath = path.resolve(process.cwd(), ".asana.json");
135
+ }
136
+ let config;
137
+ try {
138
+ const raw = await readFile(configPath, "utf8");
139
+ config = JSON.parse(raw);
140
+ }
141
+ catch {
142
+ config = {};
143
+ }
144
+ const schemaRaw = await readFile(path.join(ROOT, "schemas", "config.json"), "utf8");
145
+ const manifestRaw = await readFile(path.join(ROOT, "manifest.json"), "utf8");
146
+ const schema = JSON.parse(schemaRaw);
147
+ const manifest = JSON.parse(manifestRaw);
148
+ const ctx = {
149
+ tool: "asana",
150
+ configPath,
151
+ config,
152
+ manifest,
153
+ schema,
154
+ auditLogPath: path.join(resolveDataDir("asana"), "audit.log"),
155
+ auditRotationMaxBytes: 10 * 1024 * 1024,
156
+ };
157
+ const report = await runChecks(ctx, ADAPTER_CHECKS);
158
+ const opts = {
159
+ format: jsonMode ? "json" : "md",
160
+ fixHintsOnly,
161
+ };
162
+ console.log(renderReport(report, opts));
163
+ const hasError = report.results.some((r) => !r.result.ok && r.check.severity === "error");
164
+ process.exit(hasError ? 1 : 0);
165
+ }
166
+ //# sourceMappingURL=doctor-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-cli.js","sourceRoot":"","sources":["../src/doctor-cli.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAwC,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,YAAY,EAAmB,MAAM,kCAAkC,CAAC;AAEjF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAE9E,8EAA8E;AAC9E,qCAAqC;AACrC,8EAA8E;AAE9E,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,gCAAgC,OAAO,EAAE,EAAE;YAC5E,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,GAAG,EAAE,EAAE;SAC5C,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,kBAAmB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAgB;IAC3B,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,kCAAkC;IACzC,QAAQ,EAAE,OAAO;IACjB,KAAK,CAAC,GAAG,CAAC,IAAI;QACZ,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAClD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,iEAAiE;aAC3E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAC/C,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;YACzD,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,2BAA2B,GAAG,CAAC,MAAM,EAAE;gBAChD,OAAO,EAAE,+CAA+C;aACzD,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,OAAO,GAAgB;IAC3B,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,6BAA6B;IACpC,QAAQ,EAAE,OAAO;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAClD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,oEAAoE;aAC9E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAiC,CAAC;QAClD,MAAM,QAAQ,GAAI,GAAG,CAAC,UAAU,CAAgD,IAAI,EAAE,CAAC;QACvF,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC;gBACpE,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,KAAM,CAAW,CAAC,OAAO,GAAG,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,qBAAqB,EAAE,CAAC;QAC5E,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,0BAA0B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACxD,OAAO,EAAE,4DAA4D;SACtE,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,OAAO,GAAgB;IAC3B,EAAE,EAAE,SAAS;IACb,KAAK,EAAE,+BAA+B;IACtC,QAAQ,EAAE,OAAO;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAClD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,OAAO,EAAE,oEAAoE;aAC9E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAiC,CAAC;QAClD,MAAM,QAAQ,GAAI,GAAG,CAAC,UAAU,CAAgD,IAAI,EAAE,CAAC;QACvF,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC;gBACpE,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,KAAM,CAAW,CAAC,OAAO,GAAG,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,uBAAuB,EAAE,CAAC;QAC9E,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,yBAAyB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACvD,OAAO,EAAE,4DAA4D;SACtE,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,cAAc,GAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAWlE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAE,IAAI,EAAiB;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAEvD,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,UAAkB,CAAC;IACvB,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5C,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;IACpF,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAY,CAAC;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAsC,CAAC;IAE9E,MAAM,GAAG,GAAkB;QACzB,IAAI,EAAE,OAAO;QACb,UAAU;QACV,MAAM;QACN,QAAQ;QACR,MAAM;QACN,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;QAC7D,qBAAqB,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KACxC,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAEpD,MAAM,IAAI,GAAe;QACvB,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QAChC,YAAY;KACb,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC1F,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,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"}