@marcomigozzi/trailhead 0.16.1 → 0.18.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.
Files changed (154) hide show
  1. package/README.it.md +82 -25
  2. package/README.md +82 -25
  3. package/bin/base-preflight-docs.test.js +4 -1
  4. package/bin/bulk-cross-reference-docs.test.js +36 -0
  5. package/bin/capture-action.test.js +167 -0
  6. package/bin/capture-docs.test.js +32 -0
  7. package/bin/engine-route-docs.test.js +155 -0
  8. package/bin/facet-stamp-docs.test.js +79 -0
  9. package/bin/forced-mutation-docs.test.js +38 -0
  10. package/bin/grill-model-docs.test.js +155 -0
  11. package/bin/grilling-holistic-review-docs.test.js +7 -3
  12. package/bin/guard-axis-docs.test.js +69 -0
  13. package/bin/inbox-needs-info-docs.test.js +68 -0
  14. package/bin/lib/codex-projection.js +28 -19
  15. package/bin/lib/codex-projection.test.js +77 -20
  16. package/bin/lib/host-descriptor.js +1 -1
  17. package/bin/lib/host-descriptor.test.js +6 -0
  18. package/bin/needs-you-docs.test.js +9 -2
  19. package/bin/options-in-chat-docs.test.js +65 -0
  20. package/bin/pick-stress-test-docs.test.js +1 -1
  21. package/bin/pipeline-review-docs.test.js +118 -0
  22. package/bin/plan-review-budget-docs.test.js +63 -0
  23. package/bin/repo-target-docs.test.js +41 -0
  24. package/bin/report-status-docs.test.js +10 -2
  25. package/bin/seam-coverage-docs.test.js +46 -0
  26. package/bin/session-trust-docs.test.js +37 -0
  27. package/bin/standards-brief-docs.test.js +112 -0
  28. package/bin/surfaced-scope-docs.test.js +57 -0
  29. package/bin/test-once-docs.test.js +101 -0
  30. package/bin/test-run-docs.test.js +47 -0
  31. package/bin/trailhead.js +15 -8
  32. package/bin/trailhead.test.js +71 -17
  33. package/bin/unblock-docs.test.js +56 -0
  34. package/bin/yes-accepts-recommended-docs.test.js +54 -0
  35. package/package.json +1 -1
  36. package/plugins/trailhead/.claude-plugin/plugin.json +1 -1
  37. package/plugins/trailhead/agents/trailhead-code-review.md +2 -1
  38. package/plugins/trailhead/agents/trailhead-codebase-map.md +1 -1
  39. package/plugins/trailhead/agents/trailhead-grill.md +41 -0
  40. package/plugins/trailhead/agents/trailhead-plan.md +1 -1
  41. package/plugins/trailhead/agents/trailhead-verify.md +1 -0
  42. package/plugins/trailhead/hooks/lib/audit-walk.test.js +62 -0
  43. package/plugins/trailhead/hooks/lib/capture.test.js +439 -0
  44. package/plugins/trailhead/hooks/lib/checkout-find.test.js +195 -0
  45. package/plugins/trailhead/hooks/lib/checkout-in.test.js +83 -7
  46. package/plugins/trailhead/hooks/lib/dashboard.test.js +19 -0
  47. package/plugins/trailhead/hooks/lib/gh-auth-preflight.js +89 -0
  48. package/plugins/trailhead/hooks/lib/gh-auth-preflight.test.js +132 -0
  49. package/plugins/trailhead/hooks/lib/git-env-mod.test.js +55 -0
  50. package/plugins/trailhead/hooks/lib/git-env-spawn.test.js +73 -0
  51. package/plugins/trailhead/hooks/lib/git-env.test.js +51 -0
  52. package/plugins/trailhead/hooks/lib/global-config-dir.test.js +48 -0
  53. package/plugins/trailhead/hooks/lib/heredoc-mod.test.js +85 -0
  54. package/plugins/trailhead/hooks/lib/inbox-needs-info.test.js +179 -0
  55. package/plugins/trailhead/hooks/lib/inherit-session.js +17 -0
  56. package/plugins/trailhead/hooks/lib/issue-body.test.js +165 -0
  57. package/plugins/trailhead/hooks/lib/model-defaults-review.js +22 -1
  58. package/plugins/trailhead/hooks/lib/model-defaults-review.test.js +64 -1
  59. package/plugins/trailhead/hooks/lib/model-route.js +207 -0
  60. package/plugins/trailhead/hooks/lib/model-route.test.js +231 -0
  61. package/plugins/trailhead/hooks/lib/needs-you.test.js +45 -1
  62. package/plugins/trailhead/hooks/lib/plan-review-rounds.test.js +272 -0
  63. package/plugins/trailhead/hooks/lib/repo-target.test.js +256 -0
  64. package/plugins/trailhead/hooks/lib/report-status.test.js +56 -1
  65. package/plugins/trailhead/hooks/lib/statusline-git-env.test.js +47 -0
  66. package/plugins/trailhead/hooks/lib/test-run.test.js +757 -0
  67. package/plugins/trailhead/hooks/lib/trailhead-git-env.js +40 -0
  68. package/plugins/trailhead/hooks/mod/README.md +42 -17
  69. package/plugins/trailhead/hooks/mod/auto-run.ts +2 -1
  70. package/plugins/trailhead/hooks/mod/git-env.ts +31 -0
  71. package/plugins/trailhead/hooks/mod/heredoc.ts +79 -0
  72. package/plugins/trailhead/hooks/mod/map-pane-view.ts +3 -1
  73. package/plugins/trailhead/hooks/mod/map-pane.tsx +204 -49
  74. package/plugins/trailhead/hooks/mod/my-tickets.ts +76 -0
  75. package/plugins/trailhead/hooks/mod/repo-pin.ts +113 -9
  76. package/plugins/trailhead/hooks/mod/work-state-locate.ts +2 -1
  77. package/plugins/trailhead/hooks/trailhead-bash-guards.js +8 -8
  78. package/plugins/trailhead/hooks/trailhead-bash-guards.test.js +28 -14
  79. package/plugins/trailhead/hooks/trailhead-check-update.js +20 -2
  80. package/plugins/trailhead/hooks/trailhead-check-update.test.js +60 -0
  81. package/plugins/trailhead/hooks/trailhead-labels-guard.js +2 -2
  82. package/plugins/trailhead/hooks/trailhead-labels-guard.test.js +1 -1
  83. package/plugins/trailhead/hooks/trailhead-test-guard.js +232 -0
  84. package/plugins/trailhead/hooks/trailhead-test-guard.test.js +172 -0
  85. package/plugins/trailhead/skills/_shared/capture-core.md +123 -0
  86. package/plugins/trailhead/skills/_shared/choices.md +2 -2
  87. package/plugins/trailhead/skills/_shared/configuration-reference.md +30 -16
  88. package/plugins/trailhead/skills/_shared/configuration.md +1 -1
  89. package/plugins/trailhead/skills/_shared/load-first.md +2 -0
  90. package/plugins/trailhead/skills/_shared/session-handoff.md +1 -1
  91. package/plugins/trailhead/skills/_shared/substrate-commands.md +19 -6
  92. package/plugins/trailhead/skills/_shared/substrate.md +4 -3
  93. package/plugins/trailhead/skills/_shared/surfaced-scope.md +23 -0
  94. package/plugins/trailhead/skills/_shared/teamwork.md +11 -5
  95. package/plugins/trailhead/skills/_shared/techniques/acceptance-testing.md +1 -1
  96. package/plugins/trailhead/skills/_shared/techniques/code-review-pipeline.md +24 -0
  97. package/plugins/trailhead/skills/_shared/techniques/code-review.md +22 -6
  98. package/plugins/trailhead/skills/_shared/techniques/codebase-map.md +6 -3
  99. package/plugins/trailhead/skills/_shared/techniques/debug.md +5 -2
  100. package/plugins/trailhead/skills/_shared/techniques/grilling.md +28 -3
  101. package/plugins/trailhead/skills/_shared/techniques/plan-review.md +16 -4
  102. package/plugins/trailhead/skills/_shared/techniques/research.md +4 -1
  103. package/plugins/trailhead/skills/_shared/techniques/tdd.md +4 -2
  104. package/plugins/trailhead/skills/_shared/techniques/verify.md +5 -1
  105. package/plugins/trailhead/skills/_shared/techniques.md +8 -6
  106. package/plugins/trailhead/skills/trailhead-capture/SKILL.md +2 -4
  107. package/plugins/trailhead/skills/trailhead-capture/references/capture.md +29 -4
  108. package/plugins/trailhead/skills/trailhead-chart/SKILL.md +2 -2
  109. package/plugins/trailhead/skills/trailhead-chart/references/charting.md +5 -5
  110. package/plugins/trailhead/skills/trailhead-chart/references/inbox.md +11 -6
  111. package/plugins/trailhead/skills/trailhead-manage/references/auditing.md +18 -3
  112. package/plugins/trailhead/skills/trailhead-work/SKILL.md +12 -9
  113. package/plugins/trailhead/skills/trailhead-work/references/auto.md +3 -1
  114. package/plugins/trailhead/skills/trailhead-work/references/executor-brief.md +2 -0
  115. package/plugins/trailhead/skills/trailhead-work/references/ticket-engines.md +13 -13
  116. package/plugins/trailhead/templates/statusline-trailhead.sh +10 -3
  117. package/plugins/trailhead/templates/trailhead-audit-walk.js +56 -4
  118. package/plugins/trailhead/templates/trailhead-auto-merge.js +2 -1
  119. package/plugins/trailhead/templates/trailhead-auto-queue.js +2 -1
  120. package/plugins/trailhead/templates/trailhead-auto-slot.js +2 -1
  121. package/plugins/trailhead/templates/trailhead-base-preflight.js +10 -5
  122. package/plugins/trailhead/templates/trailhead-capture.js +419 -0
  123. package/plugins/trailhead/templates/trailhead-checkout-find.js +257 -0
  124. package/plugins/trailhead/templates/trailhead-checkout-in.js +78 -21
  125. package/plugins/trailhead/templates/trailhead-commit-msg-sync.js +2 -1
  126. package/plugins/trailhead/templates/trailhead-dashboard.js +15 -2
  127. package/plugins/trailhead/templates/trailhead-git-env.js +40 -0
  128. package/plugins/trailhead/templates/trailhead-inbox-needs-info.js +161 -0
  129. package/plugins/trailhead/templates/trailhead-isolation-answer.js +2 -1
  130. package/plugins/trailhead/templates/trailhead-isolation-copy.js +9 -4
  131. package/plugins/trailhead/templates/trailhead-issue-body.js +161 -12
  132. package/plugins/trailhead/templates/trailhead-merge-ticket.js +2 -1
  133. package/plugins/trailhead/templates/trailhead-needs-you.js +38 -4
  134. package/plugins/trailhead/templates/trailhead-plan-review-rounds.js +261 -7
  135. package/plugins/trailhead/templates/trailhead-repo-target.js +302 -0
  136. package/plugins/trailhead/templates/trailhead-report-status.js +57 -9
  137. package/plugins/trailhead/templates/trailhead-test-run.js +752 -0
  138. package/plugins/trailhead/templates/trailhead-uat-backfill.js +2 -1
  139. package/plugins/trailhead/templates/trailhead-uat-followup.js +2 -1
  140. package/plugins/trailhead/templates/trailhead-uat-setup.js +9 -4
  141. package/plugins/trailhead/templates/trailhead-unblock.js +2 -1
  142. package/plugins/trailhead/tests/auto-run-ui.test.ts +2 -1
  143. package/plugins/trailhead/tests/git-env.test.ts +20 -0
  144. package/plugins/trailhead/tests/map-pane-ui.test.ts +386 -50
  145. package/plugins/trailhead/tests/map-pane-view.test.ts +6 -0
  146. package/plugins/trailhead/tests/map-pane-write.test.ts +57 -1
  147. package/plugins/trailhead/tests/my-tickets.test.ts +66 -0
  148. package/plugins/trailhead/tests/repo-pin-late-repo.test.ts +3 -2
  149. package/plugins/trailhead/tests/repo-pin-relocate.test.ts +175 -0
  150. package/plugins/trailhead/tests/repo-pin.test.ts +20 -5
  151. package/plugins/trailhead/tests/unscrub.ts +8 -0
  152. package/plugins/trailhead/tests/work-state-prompt-hook.test.ts +3 -2
  153. package/plugins/trailhead/tests/work-state-worktree.test.ts +2 -1
  154. package/plugins/trailhead/types/index.d.ts +7 -0
@@ -3,20 +3,21 @@
3
3
  // trailhead report status check (self-contained, ships in templates/ so it reaches
4
4
  // every install channel). Checks the leading `status:` line of an engine-agent
5
5
  // report (Code review, Goal-backward verification #250; executor, fix, plan, debug,
6
- // research, codebase-map #249) before the engine branches on it, and returns the
6
+ // research, codebase-map #249; grill #323) before the engine branches on it, and returns the
7
7
  // report's fields.
8
8
  //
9
9
  // CLI:
10
- // node trailhead-report-status.js --technique <technique> [--file <path>]
10
+ // node trailhead-report-status.js --technique <technique> [--file <path> | --task-output <path>]
11
11
  // <technique> is verify | code-review | executor | fix | plan | debug | research |
12
- // codebase-map. Reads the report from --file, or from stdin when there is none.
12
+ // codebase-map | grill. Reads the report from --file, from the last assistant message
13
+ // of a background agent's task .output with --task-output, or from stdin when neither.
13
14
  // Prints exactly one JSON line {"action","verdict","problem","report","fields","body"}:
14
15
  // action accept | normalise | reask
15
16
  // verdict the canonical token, or null on reask
16
17
  // problem null | missing | unknown-token | conflicting | counts | fields (null iff not reask)
17
18
  // report the original text on accept and reask; the normalised text on normalise
18
19
  // fields label -> trimmed value for the report's fields (executor, fix, plan, debug,
19
- // research, codebase-map); {} for verify and code-review; null on reask
20
+ // research, codebase-map, grill); {} for verify and code-review; null on reask
20
21
  // body plan with `ready` only: the normalised report without its status line, the
21
22
  // PLAN to post verbatim; null otherwise
22
23
  // Exit 0 for all three actions; exit 2 on a usage error (missing or unknown
@@ -89,6 +90,19 @@ const CONTRACTS = Object.freeze({
89
90
  Object.freeze({ when: frozen(['needs_input']), field: 'questions', rule: 'non-empty' }),
90
91
  ]),
91
92
  }),
93
+ grilling: Object.freeze({
94
+ tokens: frozen(['question', 'review']),
95
+ required: frozen(['settled', 'frontier', 'amendments', 'conflicts']),
96
+ optional: frozen(['question', 'recommended', 'areas', 'facts']),
97
+ invariants: Object.freeze([
98
+ Object.freeze({ when: frozen(['question']), field: 'question', rule: 'non-empty' }),
99
+ Object.freeze({ when: frozen(['question']), field: 'recommended', rule: 'non-empty' }),
100
+ Object.freeze({ when: frozen(['question']), field: 'amendments', rule: 'none' }),
101
+ Object.freeze({ when: frozen(['question']), field: 'conflicts', rule: 'none' }),
102
+ Object.freeze({ when: frozen(['review']), field: 'frontier', rule: 'none' }),
103
+ Object.freeze({ when: frozen(['review']), field: 'question', rule: 'none' }),
104
+ ]),
105
+ }),
92
106
  });
93
107
 
94
108
  // Technique -> field family.
@@ -99,6 +113,7 @@ const FAMILY_OF = Object.freeze({
99
113
  research: 'investigating',
100
114
  'codebase-map': 'investigating',
101
115
  plan: 'plan',
116
+ grill: 'grilling',
102
117
  });
103
118
 
104
119
  // Technique -> its closed set of status tokens.
@@ -296,14 +311,38 @@ function checkReport(text, technique) {
296
311
  return { action: 'normalise', verdict, problem: null, report: [...head, ...rest].join('\n'), fields, body };
297
312
  }
298
313
 
314
+ // The report of a background agent, read from the host's task .output (JSONL, often a
315
+ // symlink to the subagent transcript): the text of the last assistant message that has
316
+ // any, its blocks joined in order. One message can span several lines sharing
317
+ // message.id; lines that are not JSON are skipped. null when there is no assistant text.
318
+ function reportFromTaskOutput(raw) {
319
+ const entries = raw.split('\n').flatMap((l) => {
320
+ if (!l.trim()) return [];
321
+ try { return [JSON.parse(l)]; } catch (_) { return []; }
322
+ });
323
+ const texts = (e) => {
324
+ const c = e && e.message && e.message.content;
325
+ if (typeof c === 'string') return [c];
326
+ return Array.isArray(c) ? c.filter((b) => b && b.type === 'text' && typeof b.text === 'string').map((b) => b.text) : [];
327
+ };
328
+ const assistant = entries.filter((e) => e && e.type === 'assistant' && e.message);
329
+ const last = [...assistant].reverse().find((e) => texts(e).length > 0);
330
+ if (!last) return null;
331
+ const id = last.message.id;
332
+ const parts = id === undefined ? texts(last) : assistant.filter((e) => e.message.id === id).flatMap(texts);
333
+ return parts.join('');
334
+ }
335
+
336
+ const VALUE_FLAGS = { '--technique': 'technique', '--file': 'file', '--task-output': 'taskOutput' };
337
+
299
338
  function parseArgs(argv) {
300
- const opts = { technique: null, file: null };
339
+ const opts = { technique: null, file: null, taskOutput: null };
301
340
  for (let i = 0; i < argv.length; i++) {
302
341
  const a = argv[i];
303
- if (a === '--technique' || a === '--file') {
342
+ if (Object.prototype.hasOwnProperty.call(VALUE_FLAGS, a)) {
304
343
  const v = argv[i + 1];
305
344
  if (v === undefined || v === '' || v.startsWith('--')) throw new Error(`${a} needs a value`);
306
- opts[a === '--technique' ? 'technique' : 'file'] = v;
345
+ opts[VALUE_FLAGS[a]] = v;
307
346
  i++;
308
347
  } else {
309
348
  throw new Error(`unknown argument: ${a}`);
@@ -311,9 +350,18 @@ function parseArgs(argv) {
311
350
  }
312
351
  if (!opts.technique) throw new Error(`--technique <${Object.keys(TOKENS).join('|')}> is required`);
313
352
  if (!Object.prototype.hasOwnProperty.call(TOKENS, opts.technique)) throw new Error(`unknown technique: ${opts.technique}`);
353
+ if (opts.file !== null && opts.taskOutput !== null) throw new Error('--file and --task-output are mutually exclusive');
314
354
  return opts;
315
355
  }
316
356
 
357
+ function readReport(opts, readFile, readStdin) {
358
+ if (opts.file !== null) return readFile(opts.file);
359
+ if (opts.taskOutput === null) return readStdin();
360
+ const report = reportFromTaskOutput(readFile(opts.taskOutput));
361
+ if (report === null) throw new Error(`no assistant report in ${opts.taskOutput}`);
362
+ return report;
363
+ }
364
+
317
365
  function main(argv, io = {}) {
318
366
  const stdout = io.stdout || process.stdout;
319
367
  const stderr = io.stderr || process.stderr;
@@ -322,7 +370,7 @@ function main(argv, io = {}) {
322
370
  let result;
323
371
  try {
324
372
  const opts = parseArgs(argv);
325
- const text = opts.file !== null ? readFile(opts.file) : readStdin();
373
+ const text = readReport(opts, readFile, readStdin);
326
374
  result = checkReport(text, opts.technique);
327
375
  } catch (e) {
328
376
  stderr.write(`${JSON.stringify({ error: e.message })}\n`);
@@ -335,4 +383,4 @@ function main(argv, io = {}) {
335
383
  // exitCode, not process.exit(): exiting at once truncates piped stdout at 64 KB.
336
384
  if (require.main === module) process.exitCode = main(process.argv.slice(2));
337
385
 
338
- module.exports = { checkReport, parseArgs, main, TOKENS, CONTRACTS, FAMILY_OF, VERIFY_CLASSES };
386
+ module.exports = { checkReport, reportFromTaskOutput, parseArgs, main, TOKENS, CONTRACTS, FAMILY_OF, VERIFY_CLASSES };