@llodev/pm-tasks-asana 1.7.0 → 1.8.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,13 @@
1
1
  # @llodev/pm-tasks-asana
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#50](https://github.com/llodev/skills/pull/50) [`889f99d`](https://github.com/llodev/skills/commit/889f99de02de68a8d92a9106ddfe1b9043a504ff) Thanks [@lloliveiradev](https://github.com/lloliveiradev)! - Number custom fields can declare a `unit` (`minutes|hours|days|points`); values are converted to the field's native unit before writing (e.g. 12 h → 720 min), fixing estimated-duration being stored in the wrong unit. Clarify that `subtaskDefaults.inheritParentFields` is an auto-copy floor, not a whitelist — Competência/Módulo/due date are filled per-task from actual scope and never left blank. SKILL.md + anti-patterns hardened.
8
+
9
+ skill-judge: pm-tasks-asana scored 85/100 vs baseline 83 (Δ +2); baseline ratcheted 83→85 (real, within-band improvement) so the CI skill-judge gate passes without the local SKIP_SKILL_JUDGE_GATE bypass.
10
+
3
11
  ## 1.7.0
4
12
 
5
13
  ### Minor Changes
package/SKILL.md CHANGED
@@ -15,7 +15,7 @@ description: >-
15
15
  @llodev/pm-tasks-core installed.
16
16
  license: MIT
17
17
  metadata:
18
- version: 1.7.0
18
+ version: 1.8.0
19
19
  tags:
20
20
  - agent-skill
21
21
  - asana
@@ -54,7 +54,7 @@ Asana tasks have:
54
54
 
55
55
  - **Name** (title, ≤80 chars for board view).
56
56
  - **Description** (rich text; prefer `**Section**` bold labels — `##` headings render inconsistently).
57
- - **Subtasks** — one level deep. Custom fields and assignee do NOT auto-propagate from parent; the adapter sets them explicitly per `subtaskDefaults.inheritParentFields` in `.asana.json`.
57
+ - **Subtasks** — one level deep. Custom fields and assignee do NOT auto-propagate from parent. `subtaskDefaults.inheritParentFields` lists the fields **auto-copied** from the parent (a floor, not a whitelist); every subtask still gets its own domain fields (e.g. Competência, Módulo) and due date filled from what that subtask actually touches — never left blank, never inherited unless its ID is listed.
58
58
  - **Sections** — group tasks within a project.
59
59
  - **Custom fields** — per-project; API always uses option GIDs, never display names.
60
60
  - **Multi-assignee** — Asana allows multiple followers; primary assignee is a single field. Use `task.assignee.add` to add followers.
@@ -67,6 +67,7 @@ Apply the generic card from core's [`../pm-tasks-core/references/generic-card.md
67
67
  - Sections of the generic card → bold `**Section**` labels inside `description` (not `##`).
68
68
  - "Implementation Checklist" + "Verification Checklist" → subtasks (flatten any nested bullets; Asana supports one level only).
69
69
  - Labels → custom field options (resolved via `.asana.json` `customFields[]`).
70
+ - Number custom fields with a `unit` (`.asana.json` `customFields[].unit`) → convert the source value to the field's native unit before writing. E.g. an effort of "12 h" into a `minutes` field is `720`, not `12`.
70
71
  - Due date → `due_on` (YYYY-MM-DD).
71
72
  - Assignee → `assignee` GID resolved from `.asana.json` `members[]` or `me` at publish time.
72
73
 
@@ -84,7 +85,7 @@ Strict order: 5.1 read `.asana.json` (full file) → 5.2.5 resolve assignee + cu
84
85
  MCP publish sequence:
85
86
 
86
87
  1. **Parent task** — `create_tasks` with `name`, `notes` (description), `projects: [projectGid]`, `memberships: [{ project, section }]`, `assignee` (resolved GID), `due_on`, `custom_fields` (JSON string of `{fieldGid: optionGid}`).
87
- 2. **Subtasks** — `create_tasks` per subtask with `parent: parentGid`, `name`, `assignee` (inherited or per-subtask), `custom_fields` matching `subtaskDefaults.inheritParentFields`.
88
+ 2. **Subtasks** — `create_tasks` per subtask with `parent: parentGid`, `name`, `assignee` (inherited or per-subtask), `custom_fields` = the parent values for the fields in `subtaskDefaults.inheritParentFields` (auto-copy floor) **plus** each subtask's own domain fields (Competência, Módulo) and due date resolved from what it actually touches. Never leave a domain/date field blank because it is absent from `inheritParentFields`.
88
89
  3. **Tags** (optional) — `addTag` per tag GID.
89
90
  4. **Confirm** — list parent + subtasks with permalinks.
90
91
 
@@ -48,6 +48,12 @@ The MCP's `mcp__asana__get_task` returns user-authored comments but does NOT ret
48
48
 
49
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
50
 
51
+ ## Number custom fields are written in their native unit
52
+
53
+ **NEVER** write a raw human number into a `number` custom field that declares a `unit` without converting to that native unit first. Example: a "Duração estimada" field with `unit: "minutes"` receiving an effort of 12 hours must be written as `720`, not `12` (which would mean 12 minutes). **Why:** Asana stores the number verbatim; the wrong unit silently under/over-states effort and corrupts capacity math.
54
+
55
+ ---
56
+
51
57
  ## Subtasks do NOT inherit custom fields automatically
52
58
 
53
59
  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:
@@ -60,3 +66,5 @@ await createSubtasks({
60
66
  ```
61
67
 
62
68
  Failing to do this leaves subtasks with empty custom fields even when the parent had them set.
69
+
70
+ **NEVER** treat `inheritParentFields` as the complete field set for a task or subtask — it is the **auto-copy floor**, not a whitelist. Competência, Módulo, and due date must be filled on every task/subtask from what it actually touches (a single task may span more than one competência/módulo). Leaving them blank because they are absent from `inheritParentFields` is the exact failure that loses tracking. **Why:** the config only names what is copied automatically; everything else is still required, and a silently blank field reads as "no scope" to whoever runs the board. When a value is genuinely unknown (e.g. due date), ask instead of leaving it blank.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llodev/pm-tasks-asana",
3
- "version": "1.7.0",
3
+ "version": "1.8.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
6
  "homepage": "https://github.com/llodev/skills/tree/main/skills/pm-tasks-asana",
@@ -51,7 +51,7 @@
51
51
  "dependencies": {
52
52
  "ajv": "^8.17.1",
53
53
  "ajv-formats": "^3.0.1",
54
- "@llodev/pm-tasks-core": "^1.12.0"
54
+ "@llodev/pm-tasks-core": "^1.13.0"
55
55
  },
56
56
  "publishConfig": {
57
57
  "access": "public"
@@ -63,6 +63,11 @@
63
63
  "type": "string",
64
64
  "enum": ["text", "number", "enum", "multi_enum", "date", "people"]
65
65
  },
66
+ "unit": {
67
+ "type": "string",
68
+ "enum": ["minutes", "hours", "days", "points"],
69
+ "description": "Native unit a number field is stored in. When the source value uses a different unit, convert to this unit before writing (e.g. hours→minutes ×60). Only meaningful for type:\"number\"."
70
+ },
66
71
  "alias": { "type": "string", "pattern": "^[a-z0-9-]+$" },
67
72
  "options": {
68
73
  "type": "array",
@@ -87,7 +92,7 @@
87
92
  "inheritParentFields": {
88
93
  "type": "array",
89
94
  "items": { "type": "string", "minLength": 4 },
90
- "description": "Custom field IDs whose values flow from parent to subtask at create time."
95
+ "description": "Custom field IDs auto-copied parent->subtask at create time (a floor, NOT a whitelist). Fields not listed are still set per-task from the card's actual scope and must never be left blank just because they are absent here."
91
96
  },
92
97
  "inheritAssignee": { "type": "boolean" }
93
98
  }