td-ai-tools 1.4.0 → 1.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "td-ai-tools",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Install agent skills and packs into your project",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -27,9 +27,11 @@ other repo installed).
27
27
  ## Input: the expected Basecamp item shape
28
28
 
29
29
  This skill is designed for Basecamp items whose **titles carry a trailing `[Nh]`
30
- estimate suffix** — e.g. `Build the checkout page [2h]` or `Fix nav [1.5h]`. That
31
- convention comes from an estimation workflow (the **td-augury** generator produces
32
- titles in exactly this shape), but nothing here requires that tool: any Basecamp
30
+ estimate suffix** — e.g. `Build the checkout page [2h]`, `Fix nav [1.5h]` or
31
+ `[KS] ContainedBanner [0.25hrs]`. The unit may be written `h`, `hr`, `hrs`, `hour`
32
+ or `hours` (any case). That convention comes from an estimation workflow (the
33
+ **td-augury** generator produces titles in exactly this shape), but nothing here
34
+ requires that tool: any Basecamp
33
35
  todo or card works. Titles *without* a suffix are used verbatim; titles *with* one
34
36
  have it stripped from the task id by default (see `--keep-estimate`).
35
37
 
@@ -45,7 +47,7 @@ Each Basecamp item becomes one td-barrage task:
45
47
 
46
48
  | td-barrage field | Source | Notes |
47
49
  |------------------|--------|-------|
48
- | `id` | item **title** | trailing `[Nh]` estimate suffix stripped; deduped if needed |
50
+ | `id` | item **title** | trailing `[Nh]`/`[Nhrs]` estimate suffix stripped; deduped if needed |
49
51
  | `prompt` | item **description** | HTML flattened to plain text |
50
52
  | `success` | constant | always `{ "strategy": "default" }` |
51
53
  | `timeoutMs` | constant | `35` minutes → `2100000` ms, unless the user specifies otherwise |
@@ -131,7 +133,7 @@ Options:
131
133
 
132
134
  - `--timeout-mins N` — override the 35-minute default (the script converts to ms).
133
135
  - `--max-attempts N` — override the default of 2.
134
- - `--keep-estimate` — keep the `[Nh]` suffix in the id instead of stripping it.
136
+ - `--keep-estimate` — keep the `[Nh]`/`[Nhrs]` suffix in the id instead of stripping it.
135
137
  - `--output PATH` — write somewhere other than the shared `.agents` queue.
136
138
 
137
139
  ### 5. Report
@@ -8,7 +8,7 @@ produced the input; the queue.json format it writes is documented in ../SKILL.md
8
8
  ("Output: the td-barrage queue.json format") so no other repo need be installed.
9
9
 
10
10
  Field mapping (see ../SKILL.md):
11
- - id <- the item title, with any trailing `[Nh]` estimate suffix stripped
11
+ - id <- the item title, with any trailing `[Nh]`/`[Nhrs]` estimate suffix stripped
12
12
  - prompt <- the item description (HTML stripped to plain text)
13
13
  - success <- {"strategy": "default"} on every item
14
14
  - timeoutMs <- --timeout-mins * 60 * 1000 (default 35 minutes)
@@ -42,11 +42,14 @@ from queue_paths import resolve_queue_path # noqa: E402
42
42
  # one, whichever copy of the skill is running (see queue_paths.py).
43
43
  DEFAULT_QUEUE = resolve_queue_path(SKILL_DIR)
44
44
 
45
- # Matches a trailing estimate suffix like " [2h]" or " [1.5h]" (case-insensitive).
46
- # Basecamp titles produced by an estimation workflow carry this suffix (the
47
- # td-augury generator appends "[<hours>h]"); we strip it from the task id so the
48
- # id reads as a plain title. Titles without a suffix are unaffected.
49
- ESTIMATE_SUFFIX_RE = re.compile(r"\s*\[\d+(?:\.\d+)?h\]\s*$", re.IGNORECASE)
45
+ # Matches a trailing estimate suffix like " [2h]", " [1.5h]" or " [0.25hrs]"
46
+ # (case-insensitive). Basecamp titles produced by an estimation workflow carry this
47
+ # suffix (the td-augury generator appends "[<hours>h]", but hand-written titles
48
+ # commonly use "hr"/"hrs"/"hour"/"hours"); we strip it from the task id so the id
49
+ # reads as a plain title. Titles without a suffix are unaffected.
50
+ ESTIMATE_SUFFIX_RE = re.compile(
51
+ r"\s*\[\d+(?:\.\d+)?\s*(?:h|hr|hrs|hour|hours)\]\s*$", re.IGNORECASE
52
+ )
50
53
 
51
54
  # Block-level tags whose close (or self-close) should become a line break when
52
55
  # flattening an HTML card body to plain text.
@@ -228,7 +231,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
228
231
  parser.add_argument(
229
232
  "--keep-estimate",
230
233
  action="store_true",
231
- help="Keep the trailing [Nh] estimate suffix in the id (stripped by default).",
234
+ help="Keep the trailing [Nh]/[Nhrs] estimate suffix in the id (stripped by default).",
232
235
  )
233
236
  return parser.parse_args(argv)
234
237
 
@@ -68,6 +68,19 @@ def test_default_success_timeout_attempts():
68
68
  assert tasks[0]["maxAttempts"] == 5
69
69
 
70
70
 
71
+ def test_estimate_suffix_unit_variants_are_stripped():
72
+ # Hand-written Basecamp titles spell the unit several ways.
73
+ for suffix in ("[0.25h]", "[0.25hr]", "[0.25hrs]", "[0.25 hrs]", "[1HOURS]"):
74
+ item = {
75
+ "id": 7,
76
+ "title": f"[KS] ContainedBanner {suffix}",
77
+ "content": f"[KS] ContainedBanner {suffix}",
78
+ "description": "Build the banner.",
79
+ }
80
+ tasks, _ = build([item])
81
+ assert tasks[0]["id"] == "[KS] ContainedBanner", suffix
82
+
83
+
71
84
  def test_keep_estimate_suffix():
72
85
  tasks, _ = build([TODO], keep_estimate=True)
73
86
  assert tasks[0]["id"] == "Design — Search [2h]"
@@ -1 +0,0 @@
1
- {"version":"4.1.10","results":[[":eslint-plugin-theory/src/rules/guarded-custom-element-define.test.ts",{"duration":0,"failed":true}],[":stylelint-config-theory/src/liquid/mask.test.ts",{"duration":21.486761,"failed":false}],[":theme-check-theory/src/checks/hardcoded-text.test.ts",{"duration":79.642067,"failed":false}],[":stylelint-config-theory/src/integration.test.ts",{"duration":322.234405,"failed":false}],[":theme-check-theory/src/checks/unguarded-nullable-setting.test.ts",{"duration":126.54217099999994,"failed":false}],[":eslint-plugin-theory/src/rules/disconnected-callback-cleanup.test.ts",{"duration":0,"failed":true}],[":eslint-plugin-theory/src/integration.test.ts",{"duration":207.055841,"failed":false}],[":eslint-plugin-theory/src/liquid/mask.test.ts",{"duration":31.769655,"failed":false}],[":stylelint-config-theory/src/config.test.ts",{"duration":13.856021999999996,"failed":false}],[":theme-check-theory/src/checks/unused-section-settings.test.ts",{"duration":63.80623400000002,"failed":false}],[":theme-check-theory/src/checks/unguarded-metaobject.test.ts",{"duration":34.325909000000024,"failed":false}],[":eslint-plugin-theory/src/index.test.ts",{"duration":6.773288999999977,"failed":false}],[":theme-check-theory/src/checks/disallowed-script-or-style-tag.test.ts",{"duration":32.848730000000046,"failed":false}],[":theme-check-theory/src/checks/unguarded-metafield.test.ts",{"duration":37.897699999999986,"failed":false}],[":eslint-plugin-theory/src/rules/no-class-selectors.test.ts",{"duration":0,"failed":true}],[":eslint-plugin-theory/src/rules/no-unapproved-imports.test.ts",{"duration":0,"failed":true}],[":eslint-plugin-theory/src/rules/require-jsdoc.test.ts",{"duration":87.66796799999997,"failed":false}],[":eslint-plugin-theory/src/rules/centralize-selectors.test.ts",{"duration":0,"failed":true}],[":stylelint-config-theory/src/build.test.ts",{"duration":903.9329710000001,"failed":false}],[":theme-check-theory/src/index.test.ts",{"duration":2.380390000000034,"failed":false}],[":eslint-plugin-theory/src/processors/liquid.test.ts",{"duration":6.720345000000009,"failed":false}],[":eslint-plugin-theory/src/build.test.ts",{"duration":965.007413,"failed":false}]]}