xtrm-tools 0.7.7 → 0.7.9

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 (123) hide show
  1. package/.xtrm/config/hooks.json +0 -3
  2. package/.xtrm/registry.json +537 -565
  3. package/.xtrm/skills/default/gitnexus-cli/SKILL.md +82 -0
  4. package/.xtrm/skills/default/gitnexus-exploring/SKILL.md +78 -0
  5. package/.xtrm/skills/default/gitnexus-guide/SKILL.md +64 -0
  6. package/.xtrm/skills/default/init-session/SKILL.md +3 -0
  7. package/.xtrm/skills/default/last30days/SKILL.md +1 -1
  8. package/.xtrm/skills/default/last30days/scripts/lib/youtube_yt.py +59 -40
  9. package/.xtrm/skills/default/sync-docs/references/doc-structure.md +1 -1
  10. package/.xtrm/skills/default/sync-docs/references/schema.md +1 -1
  11. package/.xtrm/skills/default/sync-docs/scripts/doc_structure_analyzer.py +2 -2
  12. package/.xtrm/skills/default/using-specialists/SKILL.md +346 -138
  13. package/.xtrm/skills/default/using-specialists/SKILL.safe.md +1082 -0
  14. package/.xtrm/skills/default/using-specialists/SKILL.ultra.md +1082 -0
  15. package/.xtrm/skills/default/vaultctl/SKILL.md +150 -0
  16. package/CHANGELOG.md +4 -4
  17. package/cli/dist/index.cjs +328 -192
  18. package/cli/dist/index.cjs.map +1 -1
  19. package/cli/package.json +1 -1
  20. package/package.json +8 -8
  21. package/packages/pi-extensions/MIGRATION_NOTES.md +39 -0
  22. package/packages/pi-extensions/README.md +43 -0
  23. package/packages/pi-extensions/extensions/README.md +5 -0
  24. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/beads/index.ts +1 -1
  25. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/beads/package.json +1 -4
  26. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-footer/index.ts +1 -1
  27. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-footer/package.json +1 -4
  28. package/packages/pi-extensions/extensions/custom-provider-qwen-cli/package.json +16 -0
  29. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/pi-serena-compact/package.json +9 -2
  30. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/quality-gates/index.ts +1 -1
  31. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/quality-gates/package.json +1 -4
  32. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/service-skills/index.ts +1 -1
  33. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/service-skills/package.json +1 -4
  34. package/{.xtrm/ext-src → packages/pi-extensions/extensions}/session-flow/index.ts +1 -1
  35. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/session-flow/package.json +1 -4
  36. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-loader/index.ts +1 -1
  37. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-loader/package.json +1 -4
  38. package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/index.ts +1 -1
  39. package/packages/pi-extensions/package.json +46 -0
  40. package/packages/pi-extensions/src/core/README.md +9 -0
  41. package/{.xtrm/ext-src/core/lib.ts → packages/pi-extensions/src/core/index.ts} +3 -1
  42. package/packages/pi-extensions/src/extensions/auto-session-name.ts +3 -0
  43. package/packages/pi-extensions/src/extensions/auto-update.ts +3 -0
  44. package/packages/pi-extensions/src/extensions/beads.ts +3 -0
  45. package/packages/pi-extensions/src/extensions/compact-header.ts +3 -0
  46. package/packages/pi-extensions/src/extensions/custom-footer.ts +3 -0
  47. package/packages/pi-extensions/src/extensions/custom-provider-qwen-cli.ts +3 -0
  48. package/packages/pi-extensions/src/extensions/git-checkpoint.ts +3 -0
  49. package/packages/pi-extensions/src/extensions/lsp-bootstrap.ts +3 -0
  50. package/packages/pi-extensions/src/extensions/pi-serena-compact.ts +3 -0
  51. package/packages/pi-extensions/src/extensions/quality-gates.ts +3 -0
  52. package/packages/pi-extensions/src/extensions/service-skills.ts +3 -0
  53. package/packages/pi-extensions/src/extensions/session-flow.ts +3 -0
  54. package/packages/pi-extensions/src/extensions/xtrm-loader.ts +3 -0
  55. package/packages/pi-extensions/src/extensions/xtrm-ui.ts +3 -0
  56. package/packages/pi-extensions/src/index.ts +9 -0
  57. package/packages/pi-extensions/src/registry.ts +52 -0
  58. package/packages/pi-extensions/src/shared/index.ts +1 -0
  59. package/packages/pi-extensions/src/shared/legacy-path-map.ts +23 -0
  60. package/.xtrm/config/pi/extensions/core/package.json +0 -18
  61. package/.xtrm/config/pi/extensions/custom-provider-qwen-cli/package.json +0 -1
  62. package/.xtrm/config/pi/extensions/quality-gates/index.ts +0 -66
  63. package/.xtrm/config/pi/extensions/service-skills/package.json +0 -19
  64. package/.xtrm/config/pi/extensions/session-flow/index.ts +0 -96
  65. package/.xtrm/config/pi/extensions/xtrm-ui/themes/pidex-dark.json +0 -89
  66. package/.xtrm/config/pi/extensions/xtrm-ui/themes/pidex-light.json +0 -89
  67. package/.xtrm/ext-src/auto-session-name/index.ts +0 -29
  68. package/.xtrm/ext-src/auto-session-name/package.json +0 -16
  69. package/.xtrm/ext-src/auto-update/index.ts +0 -71
  70. package/.xtrm/ext-src/auto-update/package.json +0 -16
  71. package/.xtrm/ext-src/beads/index.ts +0 -232
  72. package/.xtrm/ext-src/beads/package.json +0 -19
  73. package/.xtrm/ext-src/compact-header/index.ts +0 -69
  74. package/.xtrm/ext-src/compact-header/package.json +0 -16
  75. package/.xtrm/ext-src/core/adapter.ts +0 -52
  76. package/.xtrm/ext-src/core/guard-rules.ts +0 -100
  77. package/.xtrm/ext-src/core/logger.ts +0 -45
  78. package/.xtrm/ext-src/core/package.json +0 -18
  79. package/.xtrm/ext-src/core/runner.ts +0 -71
  80. package/.xtrm/ext-src/core/session-state.ts +0 -59
  81. package/.xtrm/ext-src/custom-footer/index.ts +0 -398
  82. package/.xtrm/ext-src/custom-footer/package.json +0 -19
  83. package/.xtrm/ext-src/custom-provider-qwen-cli/index.ts +0 -363
  84. package/.xtrm/ext-src/custom-provider-qwen-cli/package.json +0 -1
  85. package/.xtrm/ext-src/git-checkpoint/index.ts +0 -53
  86. package/.xtrm/ext-src/git-checkpoint/package.json +0 -16
  87. package/.xtrm/ext-src/lsp-bootstrap/index.ts +0 -134
  88. package/.xtrm/ext-src/lsp-bootstrap/package.json +0 -17
  89. package/.xtrm/ext-src/pi-serena-compact/index.ts +0 -121
  90. package/.xtrm/ext-src/pi-serena-compact/package.json +0 -16
  91. package/.xtrm/ext-src/quality-gates/package.json +0 -19
  92. package/.xtrm/ext-src/service-skills/index.ts +0 -108
  93. package/.xtrm/ext-src/session-flow/package.json +0 -19
  94. package/.xtrm/ext-src/xtrm-loader/index.ts +0 -152
  95. package/.xtrm/ext-src/xtrm-loader/package.json +0 -19
  96. package/.xtrm/ext-src/xtrm-ui/format.ts +0 -282
  97. package/.xtrm/ext-src/xtrm-ui/index.ts +0 -1112
  98. package/.xtrm/ext-src/xtrm-ui/package.json +0 -21
  99. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.combined.log +0 -0
  100. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.stderr.log +0 -0
  101. /package/.xtrm/{ext-src → config/pi/extensions}/custom-footer/.pi/structured-returns/83051fe4-97da-4e2c-bdaa-343b32f4e714.stdout.log +0 -0
  102. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-session-name/index.ts +0 -0
  103. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-session-name/package.json +0 -0
  104. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-update/index.ts +0 -0
  105. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/auto-update/package.json +0 -0
  106. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/compact-header/index.ts +0 -0
  107. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/compact-header/package.json +0 -0
  108. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/custom-provider-qwen-cli/index.ts +0 -0
  109. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/git-checkpoint/index.ts +0 -0
  110. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/git-checkpoint/package.json +0 -0
  111. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/lsp-bootstrap/index.ts +0 -0
  112. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/lsp-bootstrap/package.json +0 -0
  113. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/pi-serena-compact/index.ts +0 -0
  114. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/format.ts +0 -0
  115. /package/{.xtrm/config/pi → packages/pi-extensions}/extensions/xtrm-ui/package.json +0 -0
  116. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/adapter.ts +0 -0
  117. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/guard-rules.ts +0 -0
  118. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/lib.ts +0 -0
  119. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/logger.ts +0 -0
  120. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/runner.ts +0 -0
  121. /package/{.xtrm/config/pi/extensions → packages/pi-extensions/src}/core/session-state.ts +0 -0
  122. /package/{.xtrm/ext-src/xtrm-ui/themes → packages/pi-extensions/themes/xtrm-ui}/pidex-dark.json +0 -0
  123. /package/{.xtrm/ext-src/xtrm-ui/themes → packages/pi-extensions/themes/xtrm-ui}/pidex-light.json +0 -0
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: gitnexus-cli
3
+ description: "Use when the user needs to run GitNexus CLI commands like analyze/index a repo, check status, clean the index, generate a wiki, or list indexed repos. Examples: \"Index this repo\", \"Reanalyze the codebase\", \"Generate a wiki\""
4
+ ---
5
+
6
+ # GitNexus CLI Commands
7
+
8
+ All commands work via `npx` — no global install required.
9
+
10
+ ## Commands
11
+
12
+ ### analyze — Build or refresh the index
13
+
14
+ ```bash
15
+ npx gitnexus analyze
16
+ ```
17
+
18
+ Run from the project root. This parses all source files, builds the knowledge graph, writes it to `.gitnexus/`, and generates CLAUDE.md / AGENTS.md context files.
19
+
20
+ | Flag | Effect |
21
+ | -------------- | ---------------------------------------------------------------- |
22
+ | `--force` | Force full re-index even if up to date |
23
+ | `--embeddings` | Enable embedding generation for semantic search (off by default) |
24
+
25
+ **When to run:** First time in a project, after major code changes, or when `gitnexus://repo/{name}/context` reports the index is stale. In Claude Code, a PostToolUse hook runs `analyze` automatically after `git commit` and `git merge`, preserving embeddings if previously generated.
26
+
27
+ ### status — Check index freshness
28
+
29
+ ```bash
30
+ npx gitnexus status
31
+ ```
32
+
33
+ Shows whether the current repo has a GitNexus index, when it was last updated, and symbol/relationship counts. Use this to check if re-indexing is needed.
34
+
35
+ ### clean — Delete the index
36
+
37
+ ```bash
38
+ npx gitnexus clean
39
+ ```
40
+
41
+ Deletes the `.gitnexus/` directory and unregisters the repo from the global registry. Use before re-indexing if the index is corrupt or after removing GitNexus from a project.
42
+
43
+ | Flag | Effect |
44
+ | --------- | ------------------------------------------------- |
45
+ | `--force` | Skip confirmation prompt |
46
+ | `--all` | Clean all indexed repos, not just the current one |
47
+
48
+ ### wiki — Generate documentation from the graph
49
+
50
+ ```bash
51
+ npx gitnexus wiki
52
+ ```
53
+
54
+ Generates repository documentation from the knowledge graph using an LLM. Requires an API key (saved to `~/.gitnexus/config.json` on first use).
55
+
56
+ | Flag | Effect |
57
+ | ------------------- | ----------------------------------------- |
58
+ | `--force` | Force full regeneration |
59
+ | `--model <model>` | LLM model (default: minimax/minimax-m2.5) |
60
+ | `--base-url <url>` | LLM API base URL |
61
+ | `--api-key <key>` | LLM API key |
62
+ | `--concurrency <n>` | Parallel LLM calls (default: 3) |
63
+ | `--gist` | Publish wiki as a public GitHub Gist |
64
+
65
+ ### list — Show all indexed repos
66
+
67
+ ```bash
68
+ npx gitnexus list
69
+ ```
70
+
71
+ Lists all repositories registered in `~/.gitnexus/registry.json`. The MCP `list_repos` tool provides the same information.
72
+
73
+ ## After Indexing
74
+
75
+ 1. **Read `gitnexus://repo/{name}/context`** to verify the index loaded
76
+ 2. Use the other GitNexus skills (`exploring`, `debugging`, `impact-analysis`, `refactoring`) for your task
77
+
78
+ ## Troubleshooting
79
+
80
+ - **"Not inside a git repository"**: Run from a directory inside a git repo
81
+ - **Index is stale after re-analyzing**: Restart Claude Code to reload the MCP server
82
+ - **Embeddings slow**: Omit `--embeddings` (it's off by default) or set `OPENAI_API_KEY` for faster API-based embedding
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: gitnexus-exploring
3
+ description: "Use when the user asks how code works, wants to understand architecture, trace execution flows, or explore unfamiliar parts of the codebase. Examples: \"How does X work?\", \"What calls this function?\", \"Show me the auth flow\""
4
+ ---
5
+
6
+ # Exploring Codebases with GitNexus
7
+
8
+ ## When to Use
9
+
10
+ - "How does authentication work?"
11
+ - "What's the project structure?"
12
+ - "Show me the main components"
13
+ - "Where is the database logic?"
14
+ - Understanding code you haven't seen before
15
+
16
+ ## Workflow
17
+
18
+ ```
19
+ 1. READ gitnexus://repos → Discover indexed repos
20
+ 2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness
21
+ 3. gitnexus_query({query: "<what you want to understand>"}) → Find related execution flows
22
+ 4. gitnexus_context({name: "<symbol>"}) → Deep dive on specific symbol
23
+ 5. READ gitnexus://repo/{name}/process/{name} → Trace full execution flow
24
+ ```
25
+
26
+ > If step 2 says "Index is stale" → run `npx gitnexus analyze` in terminal.
27
+
28
+ ## Checklist
29
+
30
+ ```
31
+ - [ ] READ gitnexus://repo/{name}/context
32
+ - [ ] gitnexus_query for the concept you want to understand
33
+ - [ ] Review returned processes (execution flows)
34
+ - [ ] gitnexus_context on key symbols for callers/callees
35
+ - [ ] READ process resource for full execution traces
36
+ - [ ] Read source files for implementation details
37
+ ```
38
+
39
+ ## Resources
40
+
41
+ | Resource | What you get |
42
+ | --------------------------------------- | ------------------------------------------------------- |
43
+ | `gitnexus://repo/{name}/context` | Stats, staleness warning (~150 tokens) |
44
+ | `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores (~300 tokens) |
45
+ | `gitnexus://repo/{name}/cluster/{name}` | Area members with file paths (~500 tokens) |
46
+ | `gitnexus://repo/{name}/process/{name}` | Step-by-step execution trace (~200 tokens) |
47
+
48
+ ## Tools
49
+
50
+ **gitnexus_query** — find execution flows related to a concept:
51
+
52
+ ```
53
+ gitnexus_query({query: "payment processing"})
54
+ → Processes: CheckoutFlow, RefundFlow, WebhookHandler
55
+ → Symbols grouped by flow with file locations
56
+ ```
57
+
58
+ **gitnexus_context** — 360-degree view of a symbol:
59
+
60
+ ```
61
+ gitnexus_context({name: "validateUser"})
62
+ → Incoming calls: loginHandler, apiMiddleware
63
+ → Outgoing calls: checkToken, getUserById
64
+ → Processes: LoginFlow (step 2/5), TokenRefresh (step 1/3)
65
+ ```
66
+
67
+ ## Example: "How does payment processing work?"
68
+
69
+ ```
70
+ 1. READ gitnexus://repo/my-app/context → 918 symbols, 45 processes
71
+ 2. gitnexus_query({query: "payment processing"})
72
+ → CheckoutFlow: processPayment → validateCard → chargeStripe
73
+ → RefundFlow: initiateRefund → calculateRefund → processRefund
74
+ 3. gitnexus_context({name: "processPayment"})
75
+ → Incoming: checkoutHandler, webhookHandler
76
+ → Outgoing: validateCard, chargeStripe, saveTransaction
77
+ 4. Read src/payments/processor.ts for implementation details
78
+ ```
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: gitnexus-guide
3
+ description: "Use when the user asks about GitNexus itself — available tools, how to query the knowledge graph, MCP resources, graph schema, or workflow reference. Examples: \"What GitNexus tools are available?\", \"How do I use GitNexus?\""
4
+ ---
5
+
6
+ # GitNexus Guide
7
+
8
+ Quick reference for all GitNexus MCP tools, resources, and the knowledge graph schema.
9
+
10
+ ## Always Start Here
11
+
12
+ For any task involving code understanding, debugging, impact analysis, or refactoring:
13
+
14
+ 1. **Read `gitnexus://repo/{name}/context`** — codebase overview + check index freshness
15
+ 2. **Match your task to a skill below** and **read that skill file**
16
+ 3. **Follow the skill's workflow and checklist**
17
+
18
+ > If step 1 warns the index is stale, run `npx gitnexus analyze` in the terminal first.
19
+
20
+ ## Skills
21
+
22
+ | Task | Skill to read |
23
+ | -------------------------------------------- | ------------------- |
24
+ | Understand architecture / "How does X work?" | `gitnexus-exploring` |
25
+ | Blast radius / "What breaks if I change X?" | `gitnexus-impact-analysis` |
26
+ | Trace bugs / "Why is X failing?" | `gitnexus-debugging` |
27
+ | Rename / extract / split / refactor | `gitnexus-refactoring` |
28
+ | Tools, resources, schema reference | `gitnexus-guide` (this file) |
29
+ | Index, status, clean, wiki CLI commands | `gitnexus-cli` |
30
+
31
+ ## Tools Reference
32
+
33
+ | Tool | What it gives you |
34
+ | ---------------- | ------------------------------------------------------------------------ |
35
+ | `query` | Process-grouped code intelligence — execution flows related to a concept |
36
+ | `context` | 360-degree symbol view — categorized refs, processes it participates in |
37
+ | `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
38
+ | `detect_changes` | Git-diff impact — what do your current changes affect |
39
+ | `rename` | Multi-file coordinated rename with confidence-tagged edits |
40
+ | `cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
41
+ | `list_repos` | Discover indexed repos |
42
+
43
+ ## Resources Reference
44
+
45
+ Lightweight reads (~100-500 tokens) for navigation:
46
+
47
+ | Resource | Content |
48
+ | ---------------------------------------------- | ----------------------------------------- |
49
+ | `gitnexus://repo/{name}/context` | Stats, staleness check |
50
+ | `gitnexus://repo/{name}/clusters` | All functional areas with cohesion scores |
51
+ | `gitnexus://repo/{name}/cluster/{clusterName}` | Area members |
52
+ | `gitnexus://repo/{name}/processes` | All execution flows |
53
+ | `gitnexus://repo/{name}/process/{processName}` | Step-by-step trace |
54
+ | `gitnexus://repo/{name}/schema` | Graph schema for Cypher |
55
+
56
+ ## Graph Schema
57
+
58
+ **Nodes:** File, Function, Class, Interface, Method, Community, Process
59
+ **Edges (via CodeRelation.type):** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
60
+
61
+ ```cypher
62
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
63
+ RETURN caller.name, caller.filePath
64
+ ```
@@ -1,3 +1,6 @@
1
+ ---
2
+ description: "Bootstrap context for a new session — load latest report, relevant memories, and orient to current project state."
3
+ ---
1
4
  # Session Start
2
5
 
3
6
  Bootstrap context for a new session. Read the latest session report, load relevant memories, and orient to current project state.
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  name: last30days
3
- version: "2.9.6"
4
3
  description: "Deep research engine covering the last 30 days across 10+ sources - Reddit, X/Twitter, YouTube, TikTok, Instagram, Hacker News, Polymarket, and the web. AI synthesizes findings into grounded, cited reports."
5
4
  argument-hint: 'last30 AI video tools, last30 best project management tools'
6
5
  allowed-tools: Bash, Read, Write, AskUserQuestion, WebSearch
@@ -8,6 +7,7 @@ homepage: https://github.com/mvanhorn/last30days-skill
8
7
  repository: https://github.com/mvanhorn/last30days-skill
9
8
  author: mvanhorn
10
9
  license: MIT
10
+ version: "2.9.7"
11
11
  user-invocable: true
12
12
  metadata:
13
13
  openclaw:
@@ -260,6 +260,34 @@ def _clean_vtt(vtt_text: str) -> str:
260
260
  _YT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
261
261
 
262
262
 
263
+ def _build_caption_track_candidates(caption_tracks: List[Dict[str, Any]]) -> List[str]:
264
+ """Return candidate caption track URLs in preferred fetch order."""
265
+ if not caption_tracks:
266
+ return []
267
+
268
+ en_exact = [track for track in caption_tracks if track.get("languageCode", "") == "en"]
269
+ en_variant = [
270
+ track for track in caption_tracks
271
+ if track.get("languageCode", "").startswith("en") and track not in en_exact
272
+ ]
273
+ original_lang = [
274
+ track for track in caption_tracks
275
+ if not track.get("languageCode", "").startswith("en")
276
+ ]
277
+
278
+ ordered_tracks = en_exact + en_variant + original_lang
279
+ seen: Set[str] = set()
280
+ candidate_urls: List[str] = []
281
+ for track in ordered_tracks:
282
+ base_url = track.get("baseUrl")
283
+ if not base_url or base_url in seen:
284
+ continue
285
+ seen.add(base_url)
286
+ candidate_urls.append(base_url)
287
+
288
+ return candidate_urls
289
+
290
+
263
291
  def _fetch_transcript_direct(video_id: str, timeout: int = 30) -> Optional[str]:
264
292
  """Fetch YouTube transcript via direct HTTP without yt-dlp.
265
293
 
@@ -319,41 +347,34 @@ def _fetch_transcript_direct(video_id: str, timeout: int = 30) -> Optional[str]:
319
347
  _log(f"Direct transcript: no caption tracks for {video_id}")
320
348
  return None
321
349
 
322
- # Find English track (prefer exact 'en', then any en variant, then first track)
323
- base_url = None
324
- for track in caption_tracks:
325
- lang = track.get("languageCode", "")
326
- if lang == "en":
327
- base_url = track.get("baseUrl")
328
- break
329
- if not base_url:
330
- for track in caption_tracks:
331
- lang = track.get("languageCode", "")
332
- if lang.startswith("en"):
333
- base_url = track.get("baseUrl")
334
- break
335
- if not base_url:
336
- # Fall back to first available track
337
- base_url = caption_tracks[0].get("baseUrl")
338
- if not base_url:
350
+ candidate_urls = _build_caption_track_candidates(caption_tracks)
351
+ if not candidate_urls:
339
352
  _log(f"Direct transcript: no baseUrl in caption tracks for {video_id}")
340
353
  return None
341
354
 
342
- # Step 3: Fetch the VTT subtitle file
343
- sep = "&" if "?" in base_url else "?"
344
- vtt_url = f"{base_url}{sep}fmt=vtt"
345
- vtt_req = urllib.request.Request(vtt_url, headers=headers)
346
- try:
347
- with urllib.request.urlopen(vtt_req, timeout=timeout) as resp:
348
- vtt_text = resp.read().decode("utf-8", errors="replace")
349
- except (urllib.error.URLError, urllib.error.HTTPError, OSError, TimeoutError) as exc:
350
- _log(f"Direct transcript: failed to fetch VTT for {video_id}: {exc}")
351
- return None
355
+ subtitle_headers = {
356
+ **headers,
357
+ "Referer": watch_url,
358
+ "Origin": "https://www.youtube.com",
359
+ "Accept": "text/vtt,text/plain,*/*",
360
+ }
352
361
 
353
- if not vtt_text or not vtt_text.strip():
354
- return None
362
+ # Step 3: Fetch VTT subtitle file, trying preferred track order
363
+ for base_url in candidate_urls:
364
+ sep = "&" if "?" in base_url else "?"
365
+ vtt_url = f"{base_url}{sep}fmt=vtt"
366
+ vtt_req = urllib.request.Request(vtt_url, headers=subtitle_headers)
367
+ try:
368
+ with urllib.request.urlopen(vtt_req, timeout=timeout) as resp:
369
+ vtt_text = resp.read().decode("utf-8", errors="replace")
370
+ except (urllib.error.URLError, urllib.error.HTTPError, OSError, TimeoutError):
371
+ continue
372
+
373
+ if vtt_text and vtt_text.strip():
374
+ return vtt_text
355
375
 
356
- return vtt_text
376
+ _log(f"Direct transcript: all caption track fetch attempts returned empty for {video_id}")
377
+ return None
357
378
 
358
379
 
359
380
  def _fetch_transcript_ytdlp(video_id: str, temp_dir: str) -> Optional[str]:
@@ -371,7 +392,7 @@ def _fetch_transcript_ytdlp(video_id: str, temp_dir: str) -> Optional[str]:
371
392
  "--ignore-config",
372
393
  "--no-cookies-from-browser",
373
394
  "--write-auto-subs",
374
- "--sub-lang", "en",
395
+ "--sub-lang", "all",
375
396
  "--sub-format", "vtt",
376
397
  "--skip-download",
377
398
  "--no-warnings",
@@ -401,15 +422,13 @@ def _fetch_transcript_ytdlp(video_id: str, temp_dir: str) -> Optional[str]:
401
422
  except FileNotFoundError:
402
423
  return None
403
424
 
404
- # yt-dlp may save as .en.vtt or .en-orig.vtt
405
- vtt_path = Path(temp_dir) / f"{video_id}.en.vtt"
406
- if not vtt_path.exists():
407
- # Try alternate naming
408
- for p in Path(temp_dir).glob(f"{video_id}*.vtt"):
409
- vtt_path = p
410
- break
411
- else:
412
- return None
425
+ # yt-dlp naming varies by language (e.g. .en.vtt, .it.vtt, .en-orig.vtt)
426
+ vtt_path = None
427
+ for p in Path(temp_dir).glob(f"{video_id}*.vtt"):
428
+ vtt_path = p
429
+ break
430
+ if not vtt_path:
431
+ return None
413
432
 
414
433
  try:
415
434
  return vtt_path.read_text(encoding="utf-8", errors="replace")
@@ -20,7 +20,7 @@ This reference defines what belongs in each focused docs/ file vs README.md.
20
20
  | Quick start, one-liner install | `README.md` | Always |
21
21
  | Feature overview table | `README.md` | Always, < 20 lines |
22
22
  | Hook events, scripts, behavior | `docs/hooks.md` | When hooks/ dir exists |
23
- | Pi/Copilot extension catalog | `docs/pi-extensions.md` | When config/pi/extensions/ exists |
23
+ | Pi/Copilot extension catalog | `docs/pi-extensions.md` | When packages/pi-extensions/extensions/ exists |
24
24
  | System architecture, components | `docs/architecture.md` | When > 2 major subsystems |
25
25
  | Policy rules and enforcement | `docs/policies.md` | When policies/ dir exists |
26
26
  | MCP server config and usage | `docs/mcp-servers.md` | When .mcp.json or mcp servers exist |
@@ -49,7 +49,7 @@ A list of glob patterns (fnmatch syntax) pointing to the source files this doc d
49
49
  source_of_truth_for:
50
50
  - "hooks/**/*.mjs"
51
51
  - "policies/*.json"
52
- - "config/pi/extensions/**/*.ts"
52
+ - "packages/pi-extensions/extensions/**/*.ts"
53
53
  ```
54
54
 
55
55
  ### domain
@@ -45,8 +45,8 @@ SECTION_DOCS_MAP = [
45
45
  SUBSYSTEM_SIGNALS: list[tuple[str, str, str, str, str, str, list[str]]] = [
46
46
  ("hooks/", "hooks.md", "hooks/ directory exists",
47
47
  "Hooks Reference", "hooks", "reference", ["hooks/**/*.mjs", "policies/*.json"]),
48
- ("config/pi/extensions/", "pi-extensions.md", "Pi extensions directory exists",
49
- "Pi Extensions Reference", "pi-extensions", "reference", ["config/pi/extensions/**/*.ts"]),
48
+ ("packages/pi-extensions/extensions/", "pi-extensions.md", "Pi extensions directory exists",
49
+ "Pi Extensions Reference", "pi-extensions", "reference", ["packages/pi-extensions/extensions/**/*.ts"]),
50
50
  (".mcp.json", "mcp-servers.md", ".mcp.json present",
51
51
  "MCP Servers Configuration", "mcp-servers", "reference", [".mcp.json"]),
52
52
  ("policies/", "policies.md", "policies/ directory exists",