taktcli 0.8.2__tar.gz → 0.8.4__tar.gz

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.
Files changed (76) hide show
  1. {taktcli-0.8.2 → taktcli-0.8.4}/PKG-INFO +32 -5
  2. {taktcli-0.8.2 → taktcli-0.8.4}/README.md +31 -4
  3. {taktcli-0.8.2 → taktcli-0.8.4}/pyproject.toml +5 -1
  4. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/wikis.py +32 -0
  5. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/SKILL.md +31 -0
  6. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/cli.md +12 -9
  7. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/plumbing.md +34 -9
  8. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/tasks.md +13 -10
  9. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/wiki.md +11 -8
  10. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/worker.md +17 -14
  11. taktcli-0.8.4/taktcli/skills/takt/scripts/markdown_index.py +148 -0
  12. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/PKG-INFO +32 -5
  13. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/SOURCES.txt +5 -0
  14. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_auth_commands.py +3 -3
  15. taktcli-0.8.4/tests/test_markdown_index.py +120 -0
  16. taktcli-0.8.4/tests/test_marketing_commands.py +41 -0
  17. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_skill.py +12 -9
  18. taktcli-0.8.4/tests/test_skill_indexes.py +39 -0
  19. taktcli-0.8.4/tests/test_skill_wheel.py +31 -0
  20. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_wikis.py +45 -1
  21. {taktcli-0.8.2 → taktcli-0.8.4}/setup.cfg +0 -0
  22. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/__init__.py +0 -0
  23. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/__main__.py +0 -0
  24. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/auth.py +0 -0
  25. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/__init__.py +0 -0
  26. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/_exec.py +0 -0
  27. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/_run.py +0 -0
  28. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/auth.py +0 -0
  29. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/file.py +0 -0
  30. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/gql.py +0 -0
  31. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/hotpath.py +0 -0
  32. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/label.py +0 -0
  33. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/notif.py +0 -0
  34. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/project.py +0 -0
  35. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/schema.py +0 -0
  36. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/skill.py +0 -0
  37. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/task.py +0 -0
  38. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/watch.py +0 -0
  39. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/wiki.py +0 -0
  40. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/commands/workspace.py +0 -0
  41. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/credentials.py +0 -0
  42. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/errors.py +0 -0
  43. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/introspection.py +0 -0
  44. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/io.py +0 -0
  45. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/oauth.py +0 -0
  46. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/explore-wiki/SKILL.md +0 -0
  47. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/explore-wiki.md +0 -0
  48. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/grooming.md +0 -0
  49. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt/references/wiki-writing.md +0 -0
  50. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt-cli/SKILL.md +0 -0
  51. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/skills/takt-worker/SKILL.md +0 -0
  52. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/transport.py +0 -0
  53. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli/watch.py +0 -0
  54. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/dependency_links.txt +0 -0
  55. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/entry_points.txt +0 -0
  56. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/requires.txt +0 -0
  57. {taktcli-0.8.2 → taktcli-0.8.4}/taktcli.egg-info/top_level.txt +0 -0
  58. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_auth.py +0 -0
  59. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_cli.py +0 -0
  60. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_credentials.py +0 -0
  61. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_file.py +0 -0
  62. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_gql.py +0 -0
  63. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_hotpath.py +0 -0
  64. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_introspection.py +0 -0
  65. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_io.py +0 -0
  66. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_label.py +0 -0
  67. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_notif.py +0 -0
  68. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_project.py +0 -0
  69. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_refresh_concurrency.py +0 -0
  70. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_schema.py +0 -0
  71. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_task.py +0 -0
  72. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_transport.py +0 -0
  73. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_version.py +0 -0
  74. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_watch.py +0 -0
  75. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_wiki.py +0 -0
  76. {taktcli-0.8.2 → taktcli-0.8.4}/tests/test_workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taktcli
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: Authorized GraphQL CLI for Takt — full GraphQL surface from the shell, stdlib-only core
5
5
  Author: Takt
6
6
  License: MIT
@@ -230,6 +230,7 @@ Every MCP tool maps to a verb:
230
230
  | `create_wiki` | `wikis create` |
231
231
  | *(none — CLI-only; GraphQL `updateWiki` / `renameWiki`)* | `wikis update <slug>` |
232
232
  | *(none — CLI-only; GraphQL `wikiRenamePreview`)* | `wikis rename-preview <slug> --new-slug S` |
233
+ | *(none — CLI-only; GraphQL `deleteWiki` / `wikiDeletePreview`)* | `wikis delete <slug> --yes` / `--dry-run` |
233
234
  | `get_project_wiki` | `wikis get <project>` |
234
235
  | `request_upload_url_and_headers` + `confirm_upload` | `file upload <path>` (composite) |
235
236
  | `get_file_url` | `file url <id>` |
@@ -254,7 +255,7 @@ Notes:
254
255
  - The `wiki` page verbs take `--wiki SLUG` (default `$TAKT_WIKI`)
255
256
  and stream big markdown through `--content-file` / `--old-file` / `--new-file`
256
257
  (`-` = stdin).
257
- - The wiki-container verbs are `wikis list/create/get/update` (entity = **Wiki**). The
258
+ - The wiki-container verbs are `wikis list/create/get/update/rename-preview/delete` (entity = **Wiki**). The
258
259
  old `workspace list/create/get` verbs are a hard error naming the replacement
259
260
  for one release — *workspace* is being reclaimed to mean the tenant, and
260
261
  nothing else.
@@ -284,9 +285,10 @@ Successful metadata updates print `{"updateWiki":{"slug":…, "name":…,
284
285
  `--yes-rewrite-links`; omitting confirmation exits `3` before sending a request.
285
286
  Confirmation does not bypass the server's check that the caller is a human
286
287
  workspace OWNER (`FORBIDDEN` otherwise). The rename rewrites every `[[old/…]]`
287
- mention and app URL into the wiki (`https://takt.sh/wiki/old/…`,
288
- `/w/<workspace>/wiki/old/…`, relative `/wiki/old/…`) across the workspace's pages,
289
- tasks, comments, results and descriptions, in one transaction, and prints
288
+ mention and app URL into the wiki (`https://app.takt.sh/wiki/old/…` and legacy
289
+ `https://takt.sh/wiki/old/…` links, `/w/<workspace>/wiki/old/…`, relative
290
+ `/wiki/old/…`) across the workspace's pages, tasks, comments, results and
291
+ descriptions, in one transaction, and prints
290
292
  `{"renameWiki":{"wiki":{…},"report":{"oldSlug","newSlug","pages","tasks",
291
293
  "comments","results","links","unfixable"}}}`. `unfixable` lists what Takt cannot
292
294
  reach (env such as `WIKI_SLUG`/`TAKT_WIKI`, CLAUDE.md, skills, scripts,
@@ -297,6 +299,31 @@ fails, the metadata edit does not run.
297
299
  `rename-preview` runs `wikiRenamePreview` and prints the same report without
298
300
  writing anything. It is gated like the rename.
299
301
 
302
+ ### Delete a Wiki container
303
+
304
+ ```bash
305
+ taktcli wikis delete knowledge --dry-run
306
+ taktcli wikis delete knowledge --yes
307
+ ```
308
+
309
+ Deleting is **permanent**: there is no trash and no undo. Without `--yes` the
310
+ command exits `3` before sending a request; `--dry-run` runs `wikiDeletePreview`
311
+ and prints the report without writing anything (with or without `--yes`). Both are
312
+ gated like a slug rename: a human workspace OWNER (`FORBIDDEN` otherwise, agents
313
+ included).
314
+
315
+ `deleteWiki` removes the wiki, its pages, their embeddings and its search feedback in
316
+ one transaction. Projects linked to it lose their wiki. Every `[[knowledge/…]]`
317
+ mention elsewhere in the workspace (task titles and descriptions, comments, result
318
+ labels and content, other wikis' pages, project/wiki/workspace descriptions)
319
+ becomes plain text `knowledge/… (deleted)`. A token whose wiki allowlist named it
320
+ loses that entry; a list left empty stays empty (confined to nothing). It prints
321
+ `{"deleteWiki":{"slug","pages","projects","tasks","comments","results",
322
+ "otherPages","links","unfixable"}}`: `pages` deleted, `projects` that lost their
323
+ wiki, rows marked per surface, `links` marked, and `unfixable` (app URLs to the
324
+ wiki, which now 404, and external config such as `WIKI_SLUG`/`TAKT_WIKI`, CLAUDE.md,
325
+ skills and scripts).
326
+
300
327
  ## Output & exit codes
301
328
 
302
329
  Default output is pretty JSON of the unwrapped `.data` payload. `--compact` =
@@ -214,6 +214,7 @@ Every MCP tool maps to a verb:
214
214
  | `create_wiki` | `wikis create` |
215
215
  | *(none — CLI-only; GraphQL `updateWiki` / `renameWiki`)* | `wikis update <slug>` |
216
216
  | *(none — CLI-only; GraphQL `wikiRenamePreview`)* | `wikis rename-preview <slug> --new-slug S` |
217
+ | *(none — CLI-only; GraphQL `deleteWiki` / `wikiDeletePreview`)* | `wikis delete <slug> --yes` / `--dry-run` |
217
218
  | `get_project_wiki` | `wikis get <project>` |
218
219
  | `request_upload_url_and_headers` + `confirm_upload` | `file upload <path>` (composite) |
219
220
  | `get_file_url` | `file url <id>` |
@@ -238,7 +239,7 @@ Notes:
238
239
  - The `wiki` page verbs take `--wiki SLUG` (default `$TAKT_WIKI`)
239
240
  and stream big markdown through `--content-file` / `--old-file` / `--new-file`
240
241
  (`-` = stdin).
241
- - The wiki-container verbs are `wikis list/create/get/update` (entity = **Wiki**). The
242
+ - The wiki-container verbs are `wikis list/create/get/update/rename-preview/delete` (entity = **Wiki**). The
242
243
  old `workspace list/create/get` verbs are a hard error naming the replacement
243
244
  for one release — *workspace* is being reclaimed to mean the tenant, and
244
245
  nothing else.
@@ -268,9 +269,10 @@ Successful metadata updates print `{"updateWiki":{"slug":…, "name":…,
268
269
  `--yes-rewrite-links`; omitting confirmation exits `3` before sending a request.
269
270
  Confirmation does not bypass the server's check that the caller is a human
270
271
  workspace OWNER (`FORBIDDEN` otherwise). The rename rewrites every `[[old/…]]`
271
- mention and app URL into the wiki (`https://takt.sh/wiki/old/…`,
272
- `/w/<workspace>/wiki/old/…`, relative `/wiki/old/…`) across the workspace's pages,
273
- tasks, comments, results and descriptions, in one transaction, and prints
272
+ mention and app URL into the wiki (`https://app.takt.sh/wiki/old/…` and legacy
273
+ `https://takt.sh/wiki/old/…` links, `/w/<workspace>/wiki/old/…`, relative
274
+ `/wiki/old/…`) across the workspace's pages, tasks, comments, results and
275
+ descriptions, in one transaction, and prints
274
276
  `{"renameWiki":{"wiki":{…},"report":{"oldSlug","newSlug","pages","tasks",
275
277
  "comments","results","links","unfixable"}}}`. `unfixable` lists what Takt cannot
276
278
  reach (env such as `WIKI_SLUG`/`TAKT_WIKI`, CLAUDE.md, skills, scripts,
@@ -281,6 +283,31 @@ fails, the metadata edit does not run.
281
283
  `rename-preview` runs `wikiRenamePreview` and prints the same report without
282
284
  writing anything. It is gated like the rename.
283
285
 
286
+ ### Delete a Wiki container
287
+
288
+ ```bash
289
+ taktcli wikis delete knowledge --dry-run
290
+ taktcli wikis delete knowledge --yes
291
+ ```
292
+
293
+ Deleting is **permanent**: there is no trash and no undo. Without `--yes` the
294
+ command exits `3` before sending a request; `--dry-run` runs `wikiDeletePreview`
295
+ and prints the report without writing anything (with or without `--yes`). Both are
296
+ gated like a slug rename: a human workspace OWNER (`FORBIDDEN` otherwise, agents
297
+ included).
298
+
299
+ `deleteWiki` removes the wiki, its pages, their embeddings and its search feedback in
300
+ one transaction. Projects linked to it lose their wiki. Every `[[knowledge/…]]`
301
+ mention elsewhere in the workspace (task titles and descriptions, comments, result
302
+ labels and content, other wikis' pages, project/wiki/workspace descriptions)
303
+ becomes plain text `knowledge/… (deleted)`. A token whose wiki allowlist named it
304
+ loses that entry; a list left empty stays empty (confined to nothing). It prints
305
+ `{"deleteWiki":{"slug","pages","projects","tasks","comments","results",
306
+ "otherPages","links","unfixable"}}`: `pages` deleted, `projects` that lost their
307
+ wiki, rows marked per surface, `links` marked, and `unfixable` (app URLs to the
308
+ wiki, which now 404, and external config such as `WIKI_SLUG`/`TAKT_WIKI`, CLAUDE.md,
309
+ skills and scripts).
310
+
284
311
  ## Output & exit codes
285
312
 
286
313
  Default output is pretty JSON of the unwrapped `.data` payload. `--compact` =
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "taktcli"
3
- version = "0.8.2"
3
+ version = "0.8.4"
4
4
  description = "Authorized GraphQL CLI for Takt — full GraphQL surface from the shell, stdlib-only core"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -25,10 +25,14 @@ testpaths = ["tests"]
25
25
 
26
26
  [tool.setuptools.packages.find]
27
27
  include = ["taktcli*"]
28
+ exclude = ["*.__pycache__"]
28
29
 
29
30
  [tool.setuptools.package-data]
30
31
  taktcli = ["skills/**/*"]
31
32
 
33
+ [tool.setuptools.exclude-package-data]
34
+ "*" = ["**/__pycache__/*", "*.py[cod]", "**/*.py[cod]"]
35
+
32
36
  [build-system]
33
37
  requires = ["setuptools>=75"]
34
38
  build-backend = "setuptools.build_meta"
@@ -59,6 +59,19 @@ def register(subparsers) -> None:
59
59
  add_output_args(p)
60
60
  p.set_defaults(func=rename_preview)
61
61
 
62
+ p = verbs.add_parser(
63
+ "delete",
64
+ help="permanently delete a Wiki and its pages (workspace OWNER); marks refs to it as (deleted)",
65
+ )
66
+ p.add_argument("slug", help="Wiki slug (explicit; does not use TAKT_WIKI)")
67
+ p.add_argument("--yes", action="store_true", help="confirm the permanent delete")
68
+ p.add_argument(
69
+ "--dry-run", action="store_true",
70
+ help="print what the delete would remove and mark, without changing anything",
71
+ )
72
+ add_output_args(p)
73
+ p.set_defaults(func=delete)
74
+
62
75
  p = verbs.add_parser("get", help="get a project's Wiki")
63
76
  p.add_argument("project")
64
77
  add_output_args(p)
@@ -129,6 +142,25 @@ def rename_preview(args) -> int:
129
142
  return run_op(args, document, {"slug": args.slug, "newSlug": args.new_slug})
130
143
 
131
144
 
145
+ DELETE_REPORT_FIELDS = "slug pages projects tasks comments results otherPages links unfixable"
146
+
147
+
148
+ def delete(args) -> int:
149
+ """Permanently delete a Wiki via ``deleteWiki`` and print its report; ``--dry-run`` previews.
150
+
151
+ Refuses (exit 3) without ``--yes`` unless ``--dry-run``: there is no undo.
152
+ """
153
+ if args.dry_run:
154
+ document = f"query($slug:String!){{wikiDeletePreview(slug:$slug){{{DELETE_REPORT_FIELDS}}}}}"
155
+ return run_op(args, document, {"slug": args.slug})
156
+ if not args.yes:
157
+ raise ConfigError(
158
+ f"deleting wiki '{args.slug}' is permanent: pass --yes to confirm, or --dry-run to preview"
159
+ )
160
+ document = f"mutation($slug:String!){{deleteWiki(slug:$slug){{{DELETE_REPORT_FIELDS}}}}}"
161
+ return run_op(args, document, {"slug": args.slug})
162
+
163
+
132
164
  def get(args) -> int:
133
165
  document = (
134
166
  "query($slug:String!){"
@@ -15,6 +15,29 @@ description: >
15
15
 
16
16
  Takt is a task board plus a wiki. `taktcli` is its CLI: argv in, GraphQL out, JSON on stdout.
17
17
 
18
+ ## Index
19
+
20
+ Read a chapter with `sed -n 'A,Bp'` on this file. Long references have their own indexes.
21
+
22
+ - [Quick start](#quick-start): lines 34–40. Check identity, choose a mode and read current state before acting.
23
+ - [Modes](#modes): lines 41–53. Choose CLI lookup, wiki exploration or the worker loop and its detailed reference.
24
+ - [Setup](#setup): lines 54–62. Resolve CLI version, credentials, project and wiki.
25
+ - [Rules](#rules): lines 63–71. Check shell conventions, exit codes and task ownership before writes.
26
+ - [Get a task done end to end](#get-a-task-done-end-to-end): lines 72–94. Start a task, attach results and hand it off for review.
27
+ - [Track your progress in Takt](#track-your-progress-in-takt): lines 95–106. Record milestones, session pointers, outputs and follow-up work.
28
+ - [Find what the wiki knows](#find-what-the-wiki-knows): lines 107–118. Choose literal, keyword or semantic search and read relevant sections.
29
+ - [Write back what you learned](#write-back-what-you-learned): lines 119–129. Update, create, verify or flag wiki knowledge before review.
30
+ - [Recover from an error](#recover-from-an-error): lines 130–143. Diagnose status, dependency, validation, CLI and transport failures.
31
+ - [Don't use](#dont-use): lines 144–149. Replace deprecated task and wiki commands with supported verbs.
32
+ - [Maintain this skill](#maintain-this-skill): lines 150–156. Recalculate indexes, validate the contract and locate the canonical source.
33
+
34
+ ## Quick start
35
+
36
+ 1. Check `taktcli --version` and `taktcli whoami`; resolve credentials, project and wiki with [Setup](#setup).
37
+ 2. Choose a [mode](#modes) and read its reference. Use each reference's index to fetch only the chapter you need.
38
+ 3. Read current state: `taktcli get <id>` for a task, `taktcli board --project <p>` for a board, or `taktcli wiki search "topic" --wiki <w>` for knowledge.
39
+ 4. Before changing a task, read the [rules](#rules). The worker loop is `run` → implement and verify → attach results → REVIEW; never take a DRAFT task.
40
+
18
41
  ## Modes
19
42
 
20
43
  | Invoke | Alias | Use it to | Read |
@@ -123,3 +146,11 @@ More: [cli.md](references/cli.md#errors).
123
146
  - `claim`, `release`, `--lease`: deprecated aliases. Use `run`, `stop`, nothing.
124
147
  - `workspace list|create|get`: use `wikis`.
125
148
  - `status <id> CANCELLED`: use `task transition <id> cancel`.
149
+
150
+ ## Maintain this skill
151
+
152
+ Every agent-facing Markdown file over 100 physical lines needs a complete `## Index` within its first 100 lines. Index every body `##` chapter with an anchor, inclusive line range and reason to read it. Keep this entrypoint's complete quick start within the same budget. Short references can stay unindexed.
153
+
154
+ After editing, run this skill's `scripts/markdown_index.py` with the existing Python interpreter, then repeat with `--check`. It updates ranges in existing entries; authors maintain chapter links and descriptions. Run `--check --quick-start SKILL.md` from the skill directory to check the entrypoint's quick-start budget. Explicit paths resolve from the caller's working directory; the helper's default scope is its own skill's `SKILL.md` and `references/`.
155
+
156
+ For repo edits, the canonical source, repository links, tests and publication are covered in [plumbing.md](references/plumbing.md#maintaining-the-skill).
@@ -2,14 +2,17 @@
2
2
 
3
3
  Look up a verb, a flag, an output shape or an error. The tables cover real usage; `taktcli <noun> <verb> --help` is the ground truth for the installed version.
4
4
 
5
- ## Contents
6
- - Contract
7
- - Verbs
8
- - Quick reference
9
- - Ordering and paging
10
- - Errors
11
- - Verbs that don't exist
12
- - FAQ
5
+ ## Index
6
+
7
+ Read a chapter with `sed -n 'A,Bp'` on this file.
8
+
9
+ - [Contract](#contract): lines 17–30. Check installation, authentication, output, shell and identifier conventions.
10
+ - [Verbs](#verbs): lines 31–44. Find the supported command groups and their verbs.
11
+ - [Quick reference](#quick-reference): lines 45–73. Look up common task, wiki, file and administration commands.
12
+ - [Ordering and paging](#ordering-and-paging): lines 74–87. Choose sorting, limits and offsets and interpret result envelopes.
13
+ - [Errors](#errors): lines 88–103. Recover from GraphQL, transport and usage failures.
14
+ - [Verbs that don't exist](#verbs-that-dont-exist): lines 104–118. Replace common invented commands and flags with supported forms.
15
+ - [FAQ](#faq): lines 119–129. Resolve project and wiki selection, large text and command discovery questions.
13
16
 
14
17
  ## Contract
15
18
 
@@ -122,5 +125,5 @@ Don't use: `claim` / `release` / `--lease` (deprecated aliases of `run` / `stop`
122
125
  | search results are ordered by date | you passed `--order-by UPDATED_AT`, or you're on `wiki list`/`wiki grep`. Check `order` in the output. |
123
126
  | does `run` lock the task? | no. Whoever dispatches decides who works it; check before starting a RUNNING task. |
124
127
  | cancel a task? | `taktcli task transition <id> cancel` |
125
- | a wiki container vs a page? | `wikis …` acts on whole wikis; `wiki …` on pages. `wikis update <slug> --name N` renames a wiki's display name; `--new-slug S --yes-rewrite-links` changes its slug and rewrites every link to it (OWNER only, `wikis rename-preview` first). |
128
+ | a wiki container vs a page? | `wikis …` acts on whole wikis; `wiki …` on pages. `wikis update <slug> --name N` renames a wiki's display name; `--new-slug S --yes-rewrite-links` changes its slug and rewrites every link to it (OWNER only, `wikis rename-preview` first). `wikis delete <slug> --yes` deletes it permanently and marks links to it `(deleted)` (OWNER only, `--dry-run` first). |
126
129
  | find mentions of a task | `wiki grep "web-42" --wiki <w>` (literal; never `--regex` on `[[…]]`) |
@@ -1,14 +1,18 @@
1
1
  # Plumbing — auth, output, gql, files, admin
2
2
 
3
- ## Contents
4
- - Auth
5
- - Output and exit codes
6
- - Output shapes
7
- - gql and schema
8
- - Files and media
9
- - Projects, labels, wikis
10
- - Defaults and versions
11
- - The bundled skill
3
+ ## Index
4
+
5
+ Read a chapter with `sed -n 'A,Bp'` on this file.
6
+
7
+ - [Auth](#auth): lines 17–43. Resolve credentials and endpoints, log in and handle refresh failures.
8
+ - [Output and exit codes](#output-and-exit-codes): lines 44–50. Parse stdout and stderr and branch on the command's exit code.
9
+ - [Output shapes](#output-shapes): lines 51–62. Find result fields for common queries, search and grep.
10
+ - [gql and schema](#gql-and-schema): lines 63–78. Discover the schema and pass typed variables or large text to GraphQL.
11
+ - [Files and media](#files-and-media): lines 79–91. Upload, download, attach and reference media files.
12
+ - [Projects, labels, wikis](#projects-labels-wikis): lines 92–118. Manage project metadata, labels and owner-gated wiki rename or deletion.
13
+ - [Defaults and versions](#defaults-and-versions): lines 119–123. Check default limits and which installed CLI version is running.
14
+ - [The bundled skill](#the-bundled-skill): lines 124–139. Show or install packaged skills and understand overwrite protection.
15
+ - [Maintaining the skill](#maintaining-the-skill): lines 140–156. Update source indexes, run checks and keep distributed copies accurate.
12
16
 
13
17
  ## Auth
14
18
 
@@ -102,12 +106,15 @@ taktcli wikis get <project-slug>
102
106
  taktcli wikis update <slug> --name N | --description TEXT | --description-file d.md
103
107
  taktcli wikis rename-preview <slug> --new-slug S
104
108
  taktcli wikis update <slug> --new-slug S --yes-rewrite-links [--name N …]
109
+ taktcli wikis delete <slug> --dry-run
110
+ taktcli wikis delete <slug> --yes
105
111
  ```
106
112
 
107
113
  - `wikis create` makes a wiki; `wiki create` makes a page.
108
114
  - `wikis update` needs an explicit slug and at least one field; omitted fields stay.
109
115
  - Renaming a slug needs a human workspace OWNER, so an agent token gets `FORBIDDEN`. `--new-slug S` also needs `--yes-rewrite-links`. The rename rewrites every `[[old/…]]` mention and app URL to the wiki (`/wiki/old/…`, `/w/<ws>/wiki/old/…`) in page titles, content and summaries, task titles and descriptions, comments, result labels and content, and project, wiki and workspace descriptions of the workspace. It prints `renameWiki.report`: `pages`, `tasks`, `comments` and `results` (rows changed), `links` (occurrences rewritten) and `unfixable` (what you must update by hand, such as `WIKI_SLUG`/`TAKT_WIKI` env, CLAUDE.md, skills, scripts and bookmarks). The old slug 404s, and there is no redirect.
110
116
  - `wikis rename-preview` returns the same report without writing anything. Run it first, and update the external config it lists after the rename.
117
+ - `wikis delete` is **permanent** (no trash, no undo) and gated like a rename: a human workspace OWNER, so an agent token gets `FORBIDDEN`. It refuses without `--yes`; `--dry-run` prints the preview instead. The wiki's pages, their embeddings and its search feedback go with it; projects linked to it lose their wiki. Every `[[slug/…]]` mention elsewhere in the workspace (task titles and descriptions, comments, results, other wikis' pages, descriptions) becomes plain `slug/… (deleted)`. It prints the report: `pages` (deleted), `projects` (slugs that lost their wiki), `tasks`, `comments`, `results`, `otherPages` (rows marked), `links` (mentions marked) and `unfixable` (app URLs to the wiki, which now 404, and external config such as `WIKI_SLUG`/`TAKT_WIKI`, CLAUDE.md, skills and scripts). A token confined to that wiki keeps working only for what else it was confined to; confined to nothing, it reads nothing.
111
118
 
112
119
  ## Defaults and versions
113
120
 
@@ -129,3 +136,21 @@ taktcli skill install --aliases # also takt-cli, explore-wiki, takt-w
129
136
  ```
130
137
 
131
138
  Install copies the files and writes `VERSION` (the version, then a `sha256 path` line per file). It refuses to replace a copy that was edited, has no `VERSION`, is a symlink, or comes from a newer taktcli; `--force` overrides. An identical copy is left alone (`"action": "unchanged"`).
139
+
140
+ ## Maintaining the skill
141
+
142
+ The canonical source is `cli/taktcli/skills/`, shipped directly in the wheel. `.claude/skills/takt` links to the package's `takt` directory, and each repo alias's `SKILL.md` links to its package entrypoint. Edit the package sources on a task branch; there is no copy or sync step. The explore-wiki hook stays repo-only under `.claude/skills/explore-wiki/hooks/`. Use the project's existing Python interpreter; the bundled `scripts/markdown_index.py` needs only the standard library.
143
+
144
+ From the repo root:
145
+
146
+ ```bash
147
+ npm run skills:index
148
+ npm run skills:check
149
+ npm run test:cli
150
+ ```
151
+
152
+ `skills:index` recalculates chapter ranges in the source entrypoint and references. Authors add or remove entries and write their descriptions; the helper only replaces numbers. A chapter starts at its `##` heading and ends before the next `##`, or at EOF. Fenced examples and frontmatter do not create chapters, but count toward physical line numbers.
153
+
154
+ `skills:check` validates the canonical indexes without writing. The CLI tests enforce complete coverage, exact ranges, the early-index budget and the entrypoint's complete quick start by line 100. They also check repository links, parser regressions and the text returned by `skill show` and copied by `skill install`. These checks run in forge PR CI and the CLI release workflow.
155
+
156
+ Recalculate after the final content edit, then check and test before publishing the task branch and PR. The wheel ships the updated skill on the next CLI release; a repo edit alone does not update an installed package or a separately registered platform copy. If publishing to another surface, validate the exact distributed Markdown: inserted headers or reflowed text invalidate its ranges.
@@ -1,15 +1,18 @@
1
1
  # Tasks — states, start/stop, pointers, results, deps, watch
2
2
 
3
- ## Contents
4
- - Statuses and the two lanes
5
- - Pick from the board
6
- - Start, stop, hand back
7
- - Session pointers in meta
8
- - Finish in order
9
- - Results and comments
10
- - Dependencies and subtasks
11
- - Watch for events
12
- - Notifications
3
+ ## Index
4
+
5
+ Read a chapter with `sed -n 'A,Bp'` on this file.
6
+
7
+ - [Statuses and the two lanes](#statuses-and-the-two-lanes): lines 17–47. Choose legal status edges or lifecycle actions and check dependency gates.
8
+ - [Pick from the board](#pick-from-the-board): lines 48–59. Find ready work and re-fetch a task before acting.
9
+ - [Start, stop, hand back](#start-stop-hand-back): lines 60–70. Start or release work without locks, leases or ownership assumptions.
10
+ - [Session pointers in meta](#session-pointers-in-meta): lines 71–96. Record a session under its tool and role without overwriting another worker.
11
+ - [Finish in order](#finish-in-order): lines 97–111. Attach outputs before review and use DONE only within its authorized scope.
12
+ - [Results and comments](#results-and-comments): lines 112–126. Read dependency outputs, attach results and post feedback.
13
+ - [Dependencies and subtasks](#dependencies-and-subtasks): lines 127–141. Inspect or update dependencies and create or reparent subtasks.
14
+ - [Watch for events](#watch-for-events): lines 142–154. Stream changes and handle reconnects and tasks already ready at startup.
15
+ - [Notifications](#notifications): lines 155–162. Inspect unread notifications and mark them read.
13
16
 
14
17
  ## Statuses and the two lanes
15
18
 
@@ -1,13 +1,16 @@
1
1
  # Wiki — find, read, write, flag
2
2
 
3
- ## Contents
4
- - Find the wiki
5
- - List pages
6
- - Search
7
- - Read
8
- - Write back
9
- - Flag what you can't fix
10
- - Conventions
3
+ ## Index
4
+
5
+ Read a chapter with `sed -n 'A,Bp'` on this file.
6
+
7
+ - [Find the wiki](#find-the-wiki): lines 15–27. Resolve the wiki slug from instructions, a project or the wiki list.
8
+ - [List pages](#list-pages): lines 28–40. Filter pages by folder, labels, status or content and interpret the envelope.
9
+ - [Search](#search): lines 41–56. Choose grep, keyword, semantic or related-task search and page through hits.
10
+ - [Read](#read): lines 57–71. Fetch a page, heading or line slice and follow relevant mentions.
11
+ - [Write back](#write-back): lines 72–87. Edit, create, move or retire knowledge using the appropriate verb.
12
+ - [Flag what you can't fix](#flag-what-you-cant-fix): lines 88–107. Label knowledge problems and inspect search feedback.
13
+ - [Conventions](#conventions): lines 108–116. Check page paths, index links, mentions, media and publication status.
11
14
 
12
15
  ## Find the wiki
13
16
 
@@ -7,18 +7,21 @@ Pick or receive a task, groom it if needed, start it, do the work, attach result
7
7
  /takt worker <project> work the project's READY tasks in priority order
8
8
  ```
9
9
 
10
- ## Contents
11
- - 1. Resolve
12
- - 2. Pick a task
13
- - 3. Groom if vague
14
- - 4. Start and record a pointer
15
- - 5. Load context
16
- - 6. Implement and verify
17
- - 7. Finish: results, wiki, REVIEW
18
- - 8. Handle review feedback
19
- - 9. Hand back or fail
20
- - 10. Next task
21
- - Recover from an error
10
+ ## Index
11
+
12
+ Read a chapter with `sed -n 'A,Bp'` on this file.
13
+
14
+ - [1. Resolve](#1-resolve): lines 26–34. Resolve the task or project argument and its wiki.
15
+ - [2. Pick a task](#2-pick-a-task): lines 35–54. Select eligible ready work without taking another worker's task.
16
+ - [3. Groom if vague](#3-groom-if-vague): lines 55–66. Enrich unclear work or split it before starting implementation.
17
+ - [4. Start and record a pointer](#4-start-and-record-a-pointer): lines 67–86. Re-fetch, start and record an orchestrator-provided session pointer.
18
+ - [5. Load context](#5-load-context): lines 87–98. Read task feedback, dependencies and relevant wiki knowledge.
19
+ - [6. Implement and verify](#6-implement-and-verify): lines 99–112. Isolate the branch, verify scope and tests and publish its PR.
20
+ - [7. Finish: results, wiki, REVIEW](#7-finish-results-wiki-review): lines 113–128. Attach outputs and write back knowledge before the review hand-off.
21
+ - [8. Handle review feedback](#8-handle-review-feedback): lines 129–140. Verify findings, publish fixes and respect merge authority.
22
+ - [9. Hand back or fail](#9-hand-back-or-fail): lines 141–150. Explain blockers, release work or mark it failed.
23
+ - [10. Next task](#10-next-task): lines 151–158. Refresh the board and sequence dependent tasks within the authorized scope.
24
+ - [Recover from an error](#recover-from-an-error): lines 159–169. Handle lifecycle, dependency, test and context failures.
22
25
 
23
26
  ## 1. Resolve
24
27
 
@@ -105,7 +108,7 @@ Then read the tasks and `[[wiki/path]]` pages the description mentions, and run
105
108
  | frontend | if the project ships design guidance and a design skill, use them for the visual work, then finish wiring and tests yourself |
106
109
  | progress | `taktcli task comment <id> --body-file note.md` at milestones and decisions |
107
110
 
108
- Commit in small steps, push, open a PR (body via a file).
111
+ Verify the repo, assigned task branch, remote, PR base and staged diff. Commit in small steps and push the task branch. Update the existing PR for that head/base, or open one (body via a file). Follow an explicit draft, stacked-base, branch-only or no-PR override.
109
112
 
110
113
  ## 7. Finish: results, wiki, REVIEW
111
114
 
@@ -151,7 +154,7 @@ Feedback arrives as PR comments, task comments, or the task returning to READY.
151
154
  2. Low on context → finish the current task cleanly (commit, REVIEW), report, suggest a fresh session.
152
155
  3. Otherwise back to step 2, preferring related tasks.
153
156
 
154
- Several related tasks with one PR each (an epic's subtasks): finish one through REVIEW and merge before starting the next, rebased on the merged result. One PR per task keeps reviews small; bundle only mechanically identical changes. Load shared context once for the whole run.
157
+ Several related tasks with one PR each (an epic's subtasks): finish one through REVIEW, then wait for an authorized merge before starting a dependent task, or stack the next PR on the specified branch if instructed. One PR per task keeps reviews small; bundle only mechanically identical changes. Load shared context once for the whole run.
155
158
 
156
159
  ## Recover from an error
157
160
 
@@ -0,0 +1,148 @@
1
+ import argparse
2
+ import re
3
+ import sys
4
+ from pathlib import Path
5
+
6
+
7
+ HEAD_LINES = 100
8
+ ROOT = Path(__file__).resolve().parents[1]
9
+ HEADING = re.compile(r'^ {0,3}(#{1,6})\s+(.+?)\s*#*\s*$')
10
+ FENCE = re.compile(r'^ {0,3}(`{3,}|~{3,})(.*)$')
11
+ ENTRY = re.compile(r'^- \[(?P<label>[^\]]+)\]\(#(?P<anchor>[^)]+)\): lines (?P<start>\d+)[–-](?P<end>\d+)\. (?P<summary>\S.*)$')
12
+
13
+
14
+ def headings(lines):
15
+ result = []
16
+ used = set()
17
+ fence = None
18
+ frontmatter = bool(lines and lines[0].strip() == '---')
19
+ for number, raw in enumerate(lines, 1):
20
+ line = raw.rstrip('\r\n')
21
+ if frontmatter:
22
+ if number > 1 and line.strip() in ('---', '...'):
23
+ frontmatter = False
24
+ continue
25
+ marker = FENCE.match(line)
26
+ if marker:
27
+ token, suffix = marker.groups()
28
+ if fence is None:
29
+ fence = token
30
+ elif token[0] == fence[0] and len(token) >= len(fence) and not suffix.strip():
31
+ fence = None
32
+ continue
33
+ match = HEADING.match(line)
34
+ if fence or not match:
35
+ continue
36
+ level, title = len(match[1]), match[2]
37
+ visible = re.sub(r'!?\[([^\]]+)\]\([^)]*\)', r'\1', title)
38
+ base = re.sub(r'\s', '-', re.sub(r'[^\w\s-]', '', visible.lower()))
39
+ slug = base
40
+ suffix = 0
41
+ while slug in used:
42
+ suffix += 1
43
+ slug = f'{base}-{suffix}'
44
+ used.add(slug)
45
+ result.append((number, level, title, slug))
46
+ return result
47
+
48
+
49
+ def structure(text):
50
+ lines = text.splitlines(keepends=True)
51
+ chapters = [heading for heading in headings(lines) if heading[1] == 2]
52
+ indexes = [heading for heading in chapters if heading[2] == 'Index']
53
+ sections = {}
54
+ for position, (start, _, title, slug) in enumerate(chapters):
55
+ if title == 'Index':
56
+ continue
57
+ end = chapters[position + 1][0] - 1 if position + 1 < len(chapters) else len(lines)
58
+ sections[slug] = (title, start, end)
59
+ entries = []
60
+ if len(indexes) == 1:
61
+ start = indexes[0][0]
62
+ end = next((heading[0] - 1 for heading in chapters if heading[0] > start), len(lines))
63
+ entries = [(number, ENTRY.fullmatch(lines[number - 1].rstrip('\r\n')))
64
+ for number in range(start + 1, end + 1)
65
+ if lines[number - 1].startswith('- ')]
66
+ return lines, chapters, indexes, sections, entries
67
+
68
+
69
+ def document_errors(text, *, check_ranges=True, quick_start=False):
70
+ lines, chapters, indexes, sections, entries = structure(text)
71
+ if len(lines) <= HEAD_LINES and not indexes:
72
+ return ['An indexed ## Quick start is required.'] if quick_start else []
73
+ if len(indexes) != 1:
74
+ return ['Expected exactly one ## Index for a document longer than 100 lines.']
75
+ errors = []
76
+ if not sections:
77
+ errors.append('Add meaningful ## chapters for the index to address.')
78
+ if chapters[0] != indexes[0]:
79
+ errors.append('Place ## Index before the first body chapter.')
80
+ if not entries or any(match is None for _, match in entries):
81
+ return errors + ['Use - [Chapter](#anchor): lines A–B. When to read it. for every entry.']
82
+ index_end = next((heading[0] - 1 for heading in chapters if heading[0] > indexes[0][0]), len(lines))
83
+ if index_end > HEAD_LINES:
84
+ errors.append('The complete index must fit within the first 100 lines.')
85
+ anchors = [match['anchor'] for _, match in entries]
86
+ if len(anchors) != len(set(anchors)):
87
+ errors.append('A chapter appears more than once in the index.')
88
+ missing = sections.keys() - set(anchors)
89
+ unknown = set(anchors) - sections.keys()
90
+ if missing:
91
+ errors.append(f'Unindexed chapters: {", ".join(sorted(missing))}.')
92
+ if unknown:
93
+ errors.append(f'Unknown chapter anchors: {", ".join(sorted(unknown))}.')
94
+ if check_ranges:
95
+ for _, match in entries:
96
+ if match['anchor'] in sections:
97
+ title, start, end = sections[match['anchor']]
98
+ if (int(match['start']), int(match['end'])) != (start, end):
99
+ errors.append(f'{title}: expected lines {start}–{end}; run markdown_index.py.')
100
+ if quick_start and ('quick-start' not in sections or sections['quick-start'][2] > HEAD_LINES):
101
+ errors.append('The complete ## Quick start must fit within the first 100 lines.')
102
+ return errors
103
+
104
+
105
+ def reindex(text):
106
+ errors = document_errors(text, check_ranges=False)
107
+ if errors:
108
+ raise ValueError('\n'.join(errors))
109
+ lines, _, _, sections, entries = structure(text)
110
+ for number, match in entries:
111
+ _, start, end = sections[match['anchor']]
112
+ line = lines[number - 1]
113
+ lines[number - 1] = line[:match.start('start')] + f'{start}–{end}' + line[match.end('end'):]
114
+ return ''.join(lines)
115
+
116
+
117
+ def documents(paths):
118
+ return sorted({file for path in paths for file in (path.rglob('*.md') if path.is_dir() else [path])})
119
+
120
+
121
+ def main():
122
+ parser = argparse.ArgumentParser(description='Recalculate or check early chapter indexes in Markdown files over 100 lines.')
123
+ parser.add_argument('paths', nargs='*', type=Path, help='Files or directories; default: this skill and its references.')
124
+ parser.add_argument('--check', action='store_true', help='Report missing indexes and stale ranges without writing files.')
125
+ parser.add_argument('--quick-start', action='store_true', help='Also require an indexed Quick start ending by line 100.')
126
+ args = parser.parse_args()
127
+ failures = []
128
+ files = documents(args.paths or [ROOT / 'SKILL.md', ROOT / 'references'])
129
+ for path in files:
130
+ with path.open(encoding='utf-8', newline='') as source:
131
+ text = source.read()
132
+ errors = document_errors(text, check_ranges=args.check, quick_start=args.quick_start)
133
+ failures.extend(f'{path}: {error}' for error in errors)
134
+ if not args.check and not errors:
135
+ updated = reindex(text)
136
+ if updated != text:
137
+ with path.open('w', encoding='utf-8', newline='') as target:
138
+ target.write(updated)
139
+ print(f'Updated {path}')
140
+ if failures:
141
+ print('\n'.join(failures), file=sys.stderr)
142
+ return 1
143
+ print(f'{"Checked" if args.check else "Indexed"} {len(files)} Markdown files.')
144
+ return 0
145
+
146
+
147
+ if __name__ == '__main__':
148
+ raise SystemExit(main())