@kingkyylian/handoffkit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0
4
+
5
+ - Added meaningful target-specific Markdown profiles for Codex, Claude Code, Cursor, and generic handoffs.
6
+ - Made `--for` adjust packet titles, section order, and next-agent action notes while preserving the same collected source facts.
7
+ - Added local secret scanner config discovery for `gitleaks` and `secretlint`.
8
+ - Added scanner installation and config guidance when optional local scanners are unavailable.
9
+ - Fixed secret redaction so scanner names such as `secretlint` are not mistaken for secret assignment keys.
10
+ - Updated tests to cover target profile rendering, unchanged JSON source facts across targets, scanner config discovery, direct `scan-secrets` guidance, and scanner-name redaction.
11
+
12
+ ## 0.1.1
13
+
14
+ - Added automated release tarball install smoke testing.
15
+ - Improved first-run CLI help and non-git error messages.
16
+ - Prepared GitHub Actions npm publishing with provenance.
17
+ - Added structured resume state parsing and Markdown rendering for prior handoffs and checkpoints.
18
+
3
19
  ## 0.1.0
4
20
 
5
21
  - Initial TypeScript ESM CLI scaffold.
package/README.md CHANGED
@@ -104,6 +104,8 @@ Optimize the packet for a target agent:
104
104
  handoffkit pack --for codex --goal "Resume implementation"
105
105
  ```
106
106
 
107
+ Target profiles keep the same collected facts but adjust the title, section order, and next-agent notes for the selected tool. They do not invent project state or call model-specific APIs.
108
+
107
109
  During development:
108
110
 
109
111
  ```sh
@@ -190,7 +192,7 @@ HandoffKit reads local git and filesystem metadata from the current repository:
190
192
  - package manager and verification scripts from the root `package.json`
191
193
  - optional verification results when `--verify` is used
192
194
  - deterministic risk notes from changed file paths
193
- - optional secret scanner availability for `gitleaks` and `secretlint`
195
+ - optional secret scanner availability, local config files, and install guidance for `gitleaks` and `secretlint`
194
196
  - bounded, redacted secret scan results when `--scan-secrets` is used
195
197
 
196
198
  ## What Never Happens
@@ -214,7 +216,7 @@ pnpm pack:dry-run
214
216
 
215
217
  ## Release
216
218
 
217
- Releases are manual and should happen only after CI, package dry-run, and install smoke tests pass. The preferred path is the GitHub `Release` workflow with an `NPM_TOKEN` repository secret so npm provenance is attached to the published package.
219
+ Releases are manual and should happen only after CI, package dry-run, and install smoke tests pass. The preferred path is the GitHub `Release` workflow with an `NPM_TOKEN` repository secret that can publish from CI without an interactive OTP, so npm provenance is attached to the published package.
218
220
 
219
221
  See [docs/RELEASE.md](docs/RELEASE.md) for the release checklist.
220
222
 
@@ -224,6 +226,8 @@ HandoffKit is local-first and deterministic. It reads local git and filesystem s
224
226
 
225
227
  When `--scan-secrets` is used, HandoffKit runs installed local scanners only. It does not install scanners, send code to a service, or fail when `gitleaks` or `secretlint` is missing.
226
228
 
229
+ When scanner config files such as `.gitleaks.toml`, `.gitleaksignore`, `.secretlintrc.*`, or `secretlint.config.*` are present, HandoffKit reports them in the packet so the next agent knows which local policy files exist.
230
+
227
231
  ## License
228
232
 
229
233
  MIT
package/ROADMAP.md CHANGED
@@ -93,11 +93,11 @@ Regex redaction remains the default. HandoffKit detects optional local scanners
93
93
 
94
94
  Scan results are bounded and redacted before rendering.
95
95
 
96
+ Scanner status also reports common local config files such as `.gitleaks.toml`, `.gitleaksignore`, `.secretlintrc.*`, and `secretlint.config.*`. When a scanner is not installed, the packet includes local installation and config guidance without installing anything automatically.
97
+
96
98
  ## Next Up
97
99
 
98
- - Add scanner-specific installation guidance and config discovery.
99
100
  - Make `risk` rules richer by mapping changed files to common failure modes.
100
- - Improve `--for` formats beyond headings, with agent-specific action prompts.
101
101
  - Add transcript parsers for Claude Code, Codex, Cursor, and Gemini exports.
102
102
  - Add a stable `.handoffkit` cache format for verification and resume artifacts.
103
103
 
package/dist/index.js CHANGED
@@ -11,6 +11,20 @@ import { z as z2 } from "zod";
11
11
  import { readFile } from "fs/promises";
12
12
  import { basename } from "path";
13
13
  import { execa } from "execa";
14
+
15
+ // src/cli/errors.ts
16
+ var HandoffKitCliError = class extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = "HandoffKitCliError";
20
+ }
21
+ };
22
+ function formatCliError(error) {
23
+ const message = error instanceof Error ? error.message : String(error);
24
+ return message.trim();
25
+ }
26
+
27
+ // src/core/git.ts
14
28
  var UNTRACKED_PATCH_CHAR_LIMIT = 2e4;
15
29
  var IGNORED_CHANGED_PATH_PREFIXES = ["node_modules/", "dist/", "coverage/", ".git/"];
16
30
  async function findGitRoot(cwd) {
@@ -19,7 +33,10 @@ async function findGitRoot(cwd) {
19
33
  reject: false
20
34
  });
21
35
  if (result.exitCode !== 0) {
22
- throw new Error("HandoffKit must be run inside a git repository.");
36
+ throw new HandoffKitCliError([
37
+ "HandoffKit must be run inside a git repository.",
38
+ "Run this command from a git checkout, or initialize one with `git init`."
39
+ ].join("\n"));
23
40
  }
24
41
  return result.stdout.trimEnd();
25
42
  }
@@ -146,7 +163,7 @@ import fg from "fast-glob";
146
163
 
147
164
  // src/core/redact.ts
148
165
  var REDACTION = "[REDACTED]";
149
- var SECRET_KEY_PATTERN = /(\b[A-Z0-9_.-]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CLIENT[_-]?SECRET|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|COOKIE|SESSION|JWT|AUTH_TOKEN)[A-Z0-9_.-]*\b\s*(?:=|:)\s*)(["']?)([^\s"',}]+)/gi;
166
+ var SECRET_KEY_PATTERN = /(\b(?:[A-Z0-9]+[_.-])*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CLIENT[_-]?SECRET|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|COOKIE|SESSION|JWT|AUTH_TOKEN)(?:[_.-][A-Z0-9]+)*\b\s*(?:=|:)\s*)(["']?)([^\s"',}]+)/gi;
150
167
  var TOKEN_PATTERNS = [
151
168
  /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi,
152
169
  /\bsk-[A-Za-z0-9_-]{16,}/g,
@@ -352,14 +369,15 @@ import { tmpdir } from "os";
352
369
  import { relative, join as join2 } from "path";
353
370
  import { performance } from "perf_hooks";
354
371
  import { execa as execa2 } from "execa";
372
+ import fg2 from "fast-glob";
355
373
  var MAX_FINDINGS = 20;
356
374
  var ERROR_LIMIT = 2e3;
357
- async function detectSecretScanners() {
358
- const [gitleaks, secretlint] = await Promise.all([scannerStatus("gitleaks"), scannerStatus("secretlint")]);
375
+ async function detectSecretScanners(root = process.cwd()) {
376
+ const [gitleaks, secretlint] = await Promise.all([scannerStatus("gitleaks", root), scannerStatus("secretlint", root)]);
359
377
  return { scanners: [gitleaks, secretlint] };
360
378
  }
361
379
  async function runSecretScanners(root) {
362
- const report = await detectSecretScanners();
380
+ const report = await detectSecretScanners(root);
363
381
  const scans = await Promise.all(report.scanners.map((scanner) => runScanner(root, scanner)));
364
382
  return { ...report, scans };
365
383
  }
@@ -405,14 +423,18 @@ function normalizeSecretlintFindings(rawJson, limit = MAX_FINDINGS, root) {
405
423
  }
406
424
  return findings;
407
425
  }
408
- async function scannerStatus(name) {
426
+ async function scannerStatus(name, root) {
409
427
  const result = await execa2(name, ["--version"], {
410
428
  reject: false
411
429
  }).catch(() => void 0);
430
+ const configFiles = await scannerConfigFiles(name, root);
412
431
  return {
413
432
  name,
414
433
  available: Boolean(result && result.exitCode === 0),
415
- ...result?.stdout ? { version: result.stdout.trim() } : {}
434
+ ...result?.stdout ? { version: result.stdout.trim() } : {},
435
+ configFiles,
436
+ configHint: configHint(name, configFiles),
437
+ installHint: installHint(name)
416
438
  };
417
439
  }
418
440
  async function runScanner(root, scanner) {
@@ -501,6 +523,25 @@ function trimError(output) {
501
523
  return trimmed.length > ERROR_LIMIT ? `${trimmed.slice(0, ERROR_LIMIT)}
502
524
  [truncated]` : trimmed;
503
525
  }
526
+ async function scannerConfigFiles(name, root) {
527
+ const patterns = name === "gitleaks" ? ["gitleaks.toml", ".gitleaks.toml", ".gitleaksignore", ".config/gitleaks/*.toml"] : [".secretlintrc", ".secretlintrc.*", "secretlint.config.*"];
528
+ const matches = await fg2(patterns, {
529
+ cwd: root,
530
+ dot: true,
531
+ onlyFiles: true,
532
+ unique: true
533
+ });
534
+ return matches.sort();
535
+ }
536
+ function configHint(name, configFiles) {
537
+ if (configFiles.length > 0) {
538
+ return `config: ${configFiles.join(", ")}`;
539
+ }
540
+ return name === "gitleaks" ? "config: none detected; optional files include .gitleaks.toml, gitleaks.toml, or .config/gitleaks/*.toml" : "config: none detected; optional files include .secretlintrc.*, .secretlintrc, or secretlint.config.*";
541
+ }
542
+ function installHint(name) {
543
+ return name === "gitleaks" ? "Install gitleaks from https://github.com/gitleaks/gitleaks, then rerun with --scan-secrets." : "Install secretlint from https://github.com/secretlint/secretlint, then rerun with --scan-secrets.";
544
+ }
504
545
 
505
546
  // src/core/verify.ts
506
547
  import { performance as performance2 } from "perf_hooks";
@@ -555,7 +596,7 @@ async function collectHandoffReport(options) {
555
596
  }),
556
597
  detectInstructionFiles(root),
557
598
  detectPackageInfo(root),
558
- options.scanSecrets ? runSecretScanners(root) : detectSecretScanners()
599
+ options.scanSecrets ? runSecretScanners(root) : detectSecretScanners(root)
559
600
  ]);
560
601
  const report = {
561
602
  goal: options.goal,
@@ -608,84 +649,176 @@ function renderJsonReport(report) {
608
649
  `;
609
650
  }
610
651
 
652
+ // src/report/profiles.ts
653
+ var genericOrder = [
654
+ "goal",
655
+ "repository",
656
+ "gitStatus",
657
+ "recentCommits",
658
+ "changedFiles",
659
+ "branchDelta",
660
+ "diffSummary",
661
+ "includedBranchDelta",
662
+ "includedDiff",
663
+ "instructionFiles",
664
+ "package",
665
+ "resume",
666
+ "verification",
667
+ "risk",
668
+ "secretScanning"
669
+ ];
670
+ var profiles = {
671
+ generic: {
672
+ title: "Handoff Packet",
673
+ sectionOrder: genericOrder,
674
+ nextAgentNotes: [
675
+ "Use this packet as the starting context for the next coding session.",
676
+ "Verify commands locally before claiming completion."
677
+ ]
678
+ },
679
+ codex: {
680
+ title: "Codex Handoff Packet",
681
+ sectionOrder: [
682
+ "goal",
683
+ "repository",
684
+ "gitStatus",
685
+ "changedFiles",
686
+ "verification",
687
+ "risk",
688
+ "branchDelta",
689
+ "diffSummary",
690
+ "includedBranchDelta",
691
+ "includedDiff",
692
+ "instructionFiles",
693
+ "package",
694
+ "resume",
695
+ "secretScanning",
696
+ "recentCommits"
697
+ ],
698
+ nextAgentNotes: [
699
+ "Start by reading the goal, repository status, changed files, and verification state.",
700
+ "Use local tools to inspect files before editing; do not assume hidden context.",
701
+ "Keep edits scoped and rerun the relevant verification before reporting completion."
702
+ ]
703
+ },
704
+ claude: {
705
+ title: "Claude Code Handoff Packet",
706
+ sectionOrder: [
707
+ "goal",
708
+ "resume",
709
+ "repository",
710
+ "verification",
711
+ "risk",
712
+ "changedFiles",
713
+ "gitStatus",
714
+ "branchDelta",
715
+ "diffSummary",
716
+ "includedBranchDelta",
717
+ "includedDiff",
718
+ "instructionFiles",
719
+ "package",
720
+ "secretScanning",
721
+ "recentCommits"
722
+ ],
723
+ nextAgentNotes: [
724
+ "Treat this as concise project memory plus current branch state.",
725
+ "Use the resume state to separate completed work from remaining work.",
726
+ "Ask for clarification only when the packet leaves a blocking ambiguity."
727
+ ]
728
+ },
729
+ cursor: {
730
+ title: "Cursor Handoff Packet",
731
+ sectionOrder: [
732
+ "goal",
733
+ "repository",
734
+ "changedFiles",
735
+ "gitStatus",
736
+ "includedDiff",
737
+ "diffSummary",
738
+ "branchDelta",
739
+ "includedBranchDelta",
740
+ "instructionFiles",
741
+ "package",
742
+ "verification",
743
+ "risk",
744
+ "resume",
745
+ "secretScanning",
746
+ "recentCommits"
747
+ ],
748
+ nextAgentNotes: [
749
+ "Open the changed files first to build editor context.",
750
+ "Use instruction files and package scripts to keep edits aligned with the workspace.",
751
+ "Prefer small edits and rerun the detected verification scripts."
752
+ ]
753
+ }
754
+ };
755
+ function profileForTarget(target) {
756
+ return profiles[target] ?? profiles.generic;
757
+ }
758
+
611
759
  // src/report/markdown.ts
612
760
  function renderMarkdownReport(report) {
761
+ const profile = profileForTarget(report.target);
613
762
  const lines = [
614
- `# ${titleForTarget(report.target)}`,
615
- "",
616
- "## Goal",
617
- report.goal,
618
- "",
619
- "## Repository",
620
- `- Repository: \`${report.repository.name}\``,
621
- `- Branch: \`${report.repository.branch}\``,
622
- `- Changed files: ${report.repository.changedFiles.length}`,
623
- "",
624
- "## Git Status",
625
- codeBlock(report.repository.status || "Clean working tree."),
763
+ `# ${profile.title}`,
626
764
  "",
627
- "## Recent Commits",
628
- listOrNone(report.repository.recentCommits.map((commit) => `- ${commit}`)),
629
- "",
630
- "## Changed Files",
631
- listOrNone(report.repository.changedFiles.map((file) => `- \`${file}\``)),
632
- "",
633
- ...renderBaseDiffSummary(report),
634
- "## Diff Summary",
635
- "### Staged",
636
- codeBlock(report.repository.stagedDiffSummary || "No staged diff."),
637
- "",
638
- "### Unstaged",
639
- codeBlock(report.repository.unstagedDiffSummary || "No unstaged diff."),
640
- "",
641
- "## Instruction Files",
642
- renderInstructionFiles(report.instructionFiles),
643
- "",
644
- "## Package",
645
- renderPackage(report.packageInfo),
646
- "",
647
- ...renderResumeSource(report),
648
- ...renderVerification(report),
649
- ...renderRisk(report),
650
- ...renderSecretScanning(report),
765
+ ...profile.sectionOrder.flatMap((section) => renderSection(section, report)),
651
766
  "## Next Agent Notes",
767
+ ...profile.nextAgentNotes.map((note) => `- ${note}`),
652
768
  "- This packet was generated from local git and filesystem state.",
653
769
  "- Likely secrets were redacted from generated output.",
654
770
  "- No LLM APIs were called."
655
771
  ];
656
- if (report.repository.includeDiff && report.repository.diff) {
657
- lines.splice(
658
- lines.indexOf("## Instruction Files"),
659
- 0,
660
- "## Included Diff",
661
- "### Staged Patch",
662
- codeBlock(report.repository.diff.staged || "No staged patch."),
663
- "",
664
- "### Unstaged Patch",
665
- codeBlock(report.repository.diff.unstaged || "No unstaged patch."),
666
- ""
667
- );
668
- }
669
- if (report.repository.includeDiff && report.repository.baseDiff) {
670
- lines.splice(
671
- lines.indexOf("## Included Diff"),
672
- 0,
673
- `## Included Branch Delta Since \`${report.repository.baseRef}\``,
674
- codeBlock(report.repository.baseDiff),
675
- ""
676
- );
677
- }
678
772
  return `${lines.join("\n")}
679
773
  `;
680
774
  }
681
- function titleForTarget(target = "generic") {
682
- const labels = {
683
- generic: "Handoff Packet",
684
- codex: "Codex Handoff Packet",
685
- claude: "Claude Handoff Packet",
686
- cursor: "Cursor Handoff Packet"
687
- };
688
- return labels[target] ?? "Handoff Packet";
775
+ function renderSection(section, report) {
776
+ switch (section) {
777
+ case "goal":
778
+ return ["## Goal", report.goal, ""];
779
+ case "repository":
780
+ return [
781
+ "## Repository",
782
+ `- Repository: \`${report.repository.name}\``,
783
+ `- Branch: \`${report.repository.branch}\``,
784
+ `- Changed files: ${report.repository.changedFiles.length}`,
785
+ ""
786
+ ];
787
+ case "gitStatus":
788
+ return ["## Git Status", codeBlock(report.repository.status || "Clean working tree."), ""];
789
+ case "recentCommits":
790
+ return ["## Recent Commits", listOrNone(report.repository.recentCommits.map((commit) => `- ${commit}`)), ""];
791
+ case "changedFiles":
792
+ return ["## Changed Files", listOrNone(report.repository.changedFiles.map((file) => `- \`${file}\``)), ""];
793
+ case "branchDelta":
794
+ return renderBaseDiffSummary(report);
795
+ case "diffSummary":
796
+ return [
797
+ "## Diff Summary",
798
+ "### Staged",
799
+ codeBlock(report.repository.stagedDiffSummary || "No staged diff."),
800
+ "",
801
+ "### Unstaged",
802
+ codeBlock(report.repository.unstagedDiffSummary || "No unstaged diff."),
803
+ ""
804
+ ];
805
+ case "includedBranchDelta":
806
+ return renderIncludedBranchDelta(report);
807
+ case "includedDiff":
808
+ return renderIncludedDiff(report);
809
+ case "instructionFiles":
810
+ return ["## Instruction Files", renderInstructionFiles(report.instructionFiles), ""];
811
+ case "package":
812
+ return ["## Package", renderPackage(report.packageInfo), ""];
813
+ case "resume":
814
+ return renderResumeSource(report);
815
+ case "verification":
816
+ return renderVerification(report);
817
+ case "risk":
818
+ return renderRisk(report);
819
+ case "secretScanning":
820
+ return renderSecretScanning(report);
821
+ }
689
822
  }
690
823
  function renderBaseDiffSummary(report) {
691
824
  if (!report.repository.baseRef) {
@@ -697,6 +830,30 @@ function renderBaseDiffSummary(report) {
697
830
  ""
698
831
  ];
699
832
  }
833
+ function renderIncludedBranchDelta(report) {
834
+ if (!report.repository.includeDiff || !report.repository.baseDiff) {
835
+ return [];
836
+ }
837
+ return [
838
+ `## Included Branch Delta Since \`${report.repository.baseRef}\``,
839
+ codeBlock(report.repository.baseDiff),
840
+ ""
841
+ ];
842
+ }
843
+ function renderIncludedDiff(report) {
844
+ if (!report.repository.includeDiff || !report.repository.diff) {
845
+ return [];
846
+ }
847
+ return [
848
+ "## Included Diff",
849
+ "### Staged Patch",
850
+ codeBlock(report.repository.diff.staged || "No staged patch."),
851
+ "",
852
+ "### Unstaged Patch",
853
+ codeBlock(report.repository.diff.unstaged || "No unstaged patch."),
854
+ ""
855
+ ];
856
+ }
700
857
  function renderPackage(packageInfo) {
701
858
  if (!packageInfo) {
702
859
  return "No package.json detected.";
@@ -724,7 +881,31 @@ function renderResumeSource(report) {
724
881
  if (!report.resumeSource) {
725
882
  return [];
726
883
  }
727
- return ["## Resume Source", `- Source: \`${report.resumeSource.path}\``, codeBlock(report.resumeSource.preview), ""];
884
+ return [
885
+ "## Resume Source",
886
+ `- Source: \`${report.resumeSource.path}\``,
887
+ codeBlock(report.resumeSource.preview),
888
+ "",
889
+ ...renderResumeState(report.resumeSource.state)
890
+ ];
891
+ }
892
+ function renderResumeState(state) {
893
+ if (!state) {
894
+ return [];
895
+ }
896
+ return [
897
+ "## Resume State",
898
+ renderResumeItems("Completed", state.completed),
899
+ renderResumeItems("Remaining", state.remaining),
900
+ renderResumeItems("Failed Commands", state.failedCommands),
901
+ renderResumeItems("Open Questions", state.openQuestions),
902
+ renderResumeItems("Verification", state.verification),
903
+ state.nextSafestAction ? `- Next safest action: ${state.nextSafestAction}` : "- Next safest action: none detected.",
904
+ ""
905
+ ];
906
+ }
907
+ function renderResumeItems(title, items) {
908
+ return [`### ${title}`, listOrNone(items.map((item) => `- ${item.text}`))].join("\n");
728
909
  }
729
910
  function renderVerification(report) {
730
911
  if (!report.verification) {
@@ -760,12 +941,16 @@ function renderSecretScanning(report) {
760
941
  }
761
942
  function renderSecretScannerReport(secretScanning) {
762
943
  if (!secretScanning.scans) {
763
- return secretScanning.scanners.map((scanner) => `- ${scanner.name}: ${scanner.available ? "available" : "not found"}`).join("\n");
944
+ return secretScanning.scanners.map((scanner) => `- ${scannerStatusLine(scanner)}`).join("\n");
764
945
  }
765
946
  return secretScanning.scans.map((scan) => {
947
+ const status = secretScanning.scanners.find((scanner) => scanner.name === scan.name);
766
948
  const lines = [
767
949
  `- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? "not run"}`
768
950
  ];
951
+ if (status) {
952
+ lines.push(...scannerGuidanceLines(status));
953
+ }
769
954
  for (const finding of scan.findings) {
770
955
  lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : ""}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : ""})` : ""}`);
771
956
  }
@@ -775,6 +960,23 @@ function renderSecretScannerReport(secretScanning) {
775
960
  return lines.join("\n");
776
961
  }).join("\n");
777
962
  }
963
+ function scannerStatusLine(scanner) {
964
+ const config = scanner.configFiles.length > 0 ? `; config: ${scanner.configFiles.join(", ")}` : scanner.available ? "" : `; ${scanner.configHint}`;
965
+ const install = scanner.available ? "" : `; ${scanner.installHint}`;
966
+ return `${scanner.name}: ${scanner.available ? "available" : "not found"}${config}${install}`;
967
+ }
968
+ function scannerGuidanceLines(scanner) {
969
+ const lines = [];
970
+ if (scanner.configFiles.length > 0) {
971
+ lines.push(` - config: ${scanner.configFiles.join(", ")}`);
972
+ } else if (!scanner.available) {
973
+ lines.push(` - ${scanner.configHint}`);
974
+ }
975
+ if (!scanner.available) {
976
+ lines.push(` - ${scanner.installHint}`);
977
+ }
978
+ return lines;
979
+ }
778
980
  function codeBlock(text) {
779
981
  return ["```text", text, "```"].join("\n");
780
982
  }
@@ -825,7 +1027,7 @@ var PackCliOptionsSchema = z2.object({
825
1027
  scanSecrets: z2.boolean().default(false)
826
1028
  });
827
1029
  function createPackCommand() {
828
- return new Command("pack").description("Create a safe local handoff packet for another AI assistant.").option("--goal <text>", "handoff goal", "Make your own goal").option("--output <path>", "write output to a file instead of stdout").option("--format <format>", "output format: markdown or json", "markdown").option("--for <agent>", "target output: generic, codex, claude, or cursor", "generic").option("--budget <tokens>", "rough output token budget", parseBudget, 4e3).option("--since <ref>", "focus committed branch delta on a base ref").option("--verify", "run safe verification scripts and include results").option("--scan-secrets", "run optional local secret scanners and include bounded results").option("--include-diff", "include full staged and unstaged patches", false).option("--no-diff", "omit diff summaries and full patches").action(async (rawOptions) => {
1030
+ return new Command("pack").description("Create a safe local handoff packet for another AI assistant.").summary("Create a Markdown or JSON packet from the current git state.").option("--goal <text>", "handoff goal", "Make your own goal").option("--output <path>", "write output to a file instead of stdout").option("--format <format>", "output format: markdown or json", "markdown").option("--for <agent>", "target output: generic, codex, claude, or cursor", "generic").option("--budget <tokens>", "rough output token budget", parseBudget, 4e3).option("--since <ref>", "focus committed branch delta on a base ref").option("--verify", "run safe verification scripts and include results").option("--scan-secrets", "run optional local secret scanners and include bounded results").option("--include-diff", "include full staged and unstaged patches", false).option("--no-diff", "omit diff summaries and full patches").action(async (rawOptions) => {
829
1031
  const options = parseOptions(rawOptions);
830
1032
  const report = await collectHandoffReport({
831
1033
  goal: options.goal,
@@ -867,15 +1069,79 @@ import { z as z3 } from "zod";
867
1069
 
868
1070
  // src/core/resume.ts
869
1071
  var RESUME_PREVIEW_LIMIT = 3e3;
1072
+ var SECTION_ALIASES = {
1073
+ completed: [/^completed$/i, /^done$/i, /^done this session$/i, /^what changed$/i, /^implemented$/i],
1074
+ remaining: [/^remaining$/i, /^next steps$/i, /^todo$/i, /^to do$/i],
1075
+ failedCommands: [/^failed commands$/i, /^failures$/i, /^errors$/i],
1076
+ openQuestions: [/^open questions$/i, /^open questions \/ risks$/i, /^open questions and risks$/i, /^questions$/i, /^blockers$/i],
1077
+ verification: [/^verification$/i, /^tests$/i, /^validation$/i]
1078
+ };
870
1079
  function createResumeSource(path, content) {
871
1080
  const normalized = content.replace(/\r\n/g, "\n").trim();
872
1081
  const preview = normalized.length > RESUME_PREVIEW_LIMIT ? `${normalized.slice(0, RESUME_PREVIEW_LIMIT).trimEnd()}
873
1082
  [truncated]` : normalized;
1083
+ const state = parseResumeState(normalized);
874
1084
  return {
875
1085
  path,
876
- preview: redactText(preview)
1086
+ preview: redactText(preview),
1087
+ ...hasResumeState(state) ? { state } : {}
877
1088
  };
878
1089
  }
1090
+ function parseResumeState(content) {
1091
+ const state = {
1092
+ completed: [],
1093
+ remaining: [],
1094
+ failedCommands: [],
1095
+ openQuestions: [],
1096
+ verification: []
1097
+ };
1098
+ let section;
1099
+ let heading;
1100
+ for (const rawLine of content.replace(/\r\n/g, "\n").split("\n")) {
1101
+ const line = rawLine.trim();
1102
+ const headingMatch = line.match(/^#{1,4}\s+(.+)$/);
1103
+ if (headingMatch) {
1104
+ const headingText = headingMatch[1];
1105
+ if (!headingText) {
1106
+ continue;
1107
+ }
1108
+ heading = headingText.trim();
1109
+ section = sectionForHeading(heading);
1110
+ continue;
1111
+ }
1112
+ if (!section) {
1113
+ continue;
1114
+ }
1115
+ const item = normalizeListItem(line);
1116
+ if (item) {
1117
+ state[section].push({ text: redactText(item), ...heading ? { sourceHeading: redactText(heading) } : {} });
1118
+ }
1119
+ }
1120
+ const next = state.remaining[0] ?? state.openQuestions[0] ?? state.failedCommands[0];
1121
+ if (next) {
1122
+ state.nextSafestAction = next.text;
1123
+ }
1124
+ return state;
1125
+ }
1126
+ function sectionForHeading(heading) {
1127
+ const normalized = normalizeHeading(heading);
1128
+ for (const [section, patterns] of Object.entries(SECTION_ALIASES)) {
1129
+ if (patterns.some((pattern) => pattern.test(normalized))) {
1130
+ return section;
1131
+ }
1132
+ }
1133
+ return void 0;
1134
+ }
1135
+ function normalizeListItem(line) {
1136
+ const match = line.match(/^[-*]\s+(.+)$/) ?? line.match(/^\d+\.\s+(.+)$/);
1137
+ return match?.[1]?.trim();
1138
+ }
1139
+ function normalizeHeading(heading) {
1140
+ return heading.trim().replace(/:$/, "").replace(/\s*\/\s*/g, " / ").replace(/\s+/g, " ");
1141
+ }
1142
+ function hasResumeState(state) {
1143
+ return state.completed.length > 0 || state.remaining.length > 0 || state.failedCommands.length > 0 || state.openQuestions.length > 0 || state.verification.length > 0;
1144
+ }
879
1145
 
880
1146
  // src/cli/commands/resume.ts
881
1147
  var ResumeOptionsSchema = z3.object({
@@ -886,7 +1152,7 @@ var ResumeOptionsSchema = z3.object({
886
1152
  budget: z3.number().int().positive().default(4e3)
887
1153
  });
888
1154
  function createResumeCommand() {
889
- return new Command2("resume").description("Create a fresh handoff packet using a previous handoff as resume context.").argument("<path>", "previous handoff or transcript file").option("--goal <text>", "new handoff goal", "Resume interrupted AI coding session").option("--output <path>", "write output to a file instead of stdout").option("--format <format>", "output format: markdown or json", "markdown").option("--for <agent>", "target output: generic, codex, claude, or cursor", "generic").option("--budget <tokens>", "rough output token budget", parseBudget2, 4e3).action(async (path, rawOptions) => {
1155
+ return new Command2("resume").description("Create a fresh handoff packet using a previous handoff as resume context.").summary("Merge a previous handoff or transcript with fresh repo state.").argument("<path>", "previous handoff or transcript file").option("--goal <text>", "new handoff goal", "Resume interrupted AI coding session").option("--output <path>", "write output to a file instead of stdout").option("--format <format>", "output format: markdown or json", "markdown").option("--for <agent>", "target output: generic, codex, claude, or cursor", "generic").option("--budget <tokens>", "rough output token budget", parseBudget2, 4e3).action(async (path, rawOptions) => {
890
1156
  const options = ResumeOptionsSchema.parse(rawOptions);
891
1157
  const source = createResumeSource(path, await readFile5(path, "utf8"));
892
1158
  const report = await collectHandoffReport({
@@ -920,7 +1186,7 @@ var RiskOptionsSchema = z4.object({
920
1186
  format: z4.enum(["markdown", "json"]).default("markdown")
921
1187
  });
922
1188
  function createRiskCommand() {
923
- return new Command3("risk").description("Show deterministic risk notes for the current handoff.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
1189
+ return new Command3("risk").description("Show deterministic risk notes for the current handoff.").summary("Show deterministic risk notes from changed files.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
924
1190
  const options = RiskOptionsSchema.parse(rawOptions);
925
1191
  const report = await collectHandoffReport({
926
1192
  goal: "Review local risk",
@@ -952,7 +1218,7 @@ var ScanSecretsOptionsSchema = z5.object({
952
1218
  format: z5.enum(["markdown", "json"]).default("markdown")
953
1219
  });
954
1220
  function createScanSecretsCommand() {
955
- return new Command4("scan-secrets").description("Run optional local secret scanners and print bounded redacted results.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
1221
+ return new Command4("scan-secrets").description("Run optional local secret scanners and print bounded redacted results.").summary("Run optional local secret scanners.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
956
1222
  const options = ScanSecretsOptionsSchema.parse(rawOptions);
957
1223
  const root = await findGitRoot(process.cwd());
958
1224
  const report = await runSecretScanners(root);
@@ -967,7 +1233,11 @@ function createScanSecretsCommand() {
967
1233
  function renderScanMarkdown(report) {
968
1234
  const lines = ["# Secret Scan Results", ""];
969
1235
  for (const scan of report.scans ?? []) {
1236
+ const status = report.scanners.find((scanner) => scanner.name === scan.name);
970
1237
  lines.push(`- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? "not run"}`);
1238
+ if (status) {
1239
+ lines.push(...scannerGuidanceLines2(status));
1240
+ }
971
1241
  for (const finding of scan.findings) {
972
1242
  lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : ""}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : ""})` : ""}`);
973
1243
  }
@@ -975,6 +1245,18 @@ function renderScanMarkdown(report) {
975
1245
  return `${lines.join("\n")}
976
1246
  `;
977
1247
  }
1248
+ function scannerGuidanceLines2(scanner) {
1249
+ const lines = [];
1250
+ if (scanner.configFiles.length > 0) {
1251
+ lines.push(` - config: ${scanner.configFiles.join(", ")}`);
1252
+ } else if (!scanner.available) {
1253
+ lines.push(` - ${scanner.configHint}`);
1254
+ }
1255
+ if (!scanner.available) {
1256
+ lines.push(` - ${scanner.installHint}`);
1257
+ }
1258
+ return lines;
1259
+ }
978
1260
 
979
1261
  // src/cli/commands/verify.ts
980
1262
  import { Command as Command5 } from "commander";
@@ -983,7 +1265,7 @@ var VerifyOptionsSchema = z6.object({
983
1265
  format: z6.enum(["markdown", "json"]).default("markdown")
984
1266
  });
985
1267
  function createVerifyCommand() {
986
- return new Command5("verify").description("Run safe local verification scripts.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
1268
+ return new Command5("verify").description("Run safe local verification scripts.").summary("Run safe detected verification scripts.").option("--format <format>", "output format: markdown or json", "markdown").action(async (rawOptions) => {
987
1269
  const options = VerifyOptionsSchema.parse(rawOptions);
988
1270
  const root = await findGitRoot(process.cwd());
989
1271
  const verification = await runVerification(root);
@@ -1009,7 +1291,7 @@ function renderVerificationMarkdown(commands) {
1009
1291
  }
1010
1292
 
1011
1293
  // src/cli/index.ts
1012
- var program = new Command6().name("handoffkit").description("Create safe local handoff packets for AI-assisted coding sessions.").version("0.1.0");
1294
+ var program = new Command6().name("handoffkit").description("Create safe local handoff packets for AI-assisted coding sessions.").summary("Create local-first AI coding session handoff packets.").showHelpAfterError("(run with --help for usage)").version("0.2.0");
1013
1295
  program.addCommand(createPackCommand());
1014
1296
  program.addCommand(createVerifyCommand());
1015
1297
  program.addCommand(createRiskCommand());
@@ -1018,8 +1300,7 @@ program.addCommand(createResumeCommand());
1018
1300
  try {
1019
1301
  await program.parseAsync(process.argv);
1020
1302
  } catch (error) {
1021
- const message = error instanceof Error ? error.message : String(error);
1022
- process.stderr.write(`${message}
1303
+ process.stderr.write(`${formatCliError(error)}
1023
1304
  `);
1024
1305
  process.exitCode = 1;
1025
1306
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/pack.ts","../src/core/git.ts","../src/core/instructions.ts","../src/core/redact.ts","../src/core/package-json.ts","../src/core/risk.ts","../src/core/scanners.ts","../src/core/verify.ts","../src/core/collect.ts","../src/cli/output.ts","../src/core/budget.ts","../src/report/json.ts","../src/report/markdown.ts","../src/cli/commands/resume.ts","../src/core/resume.ts","../src/cli/commands/risk.ts","../src/cli/commands/scan-secrets.ts","../src/cli/commands/verify.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\n\nimport { createPackCommand } from \"./commands/pack.js\";\nimport { createResumeCommand } from \"./commands/resume.js\";\nimport { createRiskCommand } from \"./commands/risk.js\";\nimport { createScanSecretsCommand } from \"./commands/scan-secrets.js\";\nimport { createVerifyCommand } from \"./commands/verify.js\";\n\nconst program = new Command()\n .name(\"handoffkit\")\n .description(\"Create safe local handoff packets for AI-assisted coding sessions.\")\n .version(\"0.1.0\");\n\nprogram.addCommand(createPackCommand());\nprogram.addCommand(createVerifyCommand());\nprogram.addCommand(createRiskCommand());\nprogram.addCommand(createScanSecretsCommand());\nprogram.addCommand(createResumeCommand());\n\ntry {\n await program.parseAsync(process.argv);\n} catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${message}\\n`);\n process.exitCode = 1;\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\nimport { writeRenderedReport } from \"../output.js\";\n\nconst PackCliOptionsSchema = z.object({\n goal: z.string().trim().min(1).default(\"Make your own goal\"),\n output: z.string().optional(),\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\"),\n for: z.enum([\"generic\", \"codex\", \"claude\", \"cursor\"]).default(\"generic\"),\n budget: z.number().int().positive().default(4000),\n includeDiff: z.boolean().default(false),\n diff: z.boolean().default(true),\n since: z.string().trim().min(1).optional(),\n verify: z.boolean().default(false),\n scanSecrets: z.boolean().default(false)\n});\n\nexport function createPackCommand() {\n return new Command(\"pack\")\n .description(\"Create a safe local handoff packet for another AI assistant.\")\n .option(\"--goal <text>\", \"handoff goal\", \"Make your own goal\")\n .option(\"--output <path>\", \"write output to a file instead of stdout\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .option(\"--for <agent>\", \"target output: generic, codex, claude, or cursor\", \"generic\")\n .option(\"--budget <tokens>\", \"rough output token budget\", parseBudget, 4000)\n .option(\"--since <ref>\", \"focus committed branch delta on a base ref\")\n .option(\"--verify\", \"run safe verification scripts and include results\")\n .option(\"--scan-secrets\", \"run optional local secret scanners and include bounded results\")\n .option(\"--include-diff\", \"include full staged and unstaged patches\", false)\n .option(\"--no-diff\", \"omit diff summaries and full patches\")\n .action(async (rawOptions) => {\n const options = parseOptions(rawOptions);\n const report = await collectHandoffReport({\n goal: options.goal,\n cwd: process.cwd(),\n ...(options.output ? { output: options.output } : {}),\n format: options.format,\n target: options.for,\n budget: options.budget,\n includeDiff: options.includeDiff,\n includeDiffSummary: options.diff,\n ...(options.since ? { since: options.since } : {}),\n includeVerification: options.verify,\n scanSecrets: options.scanSecrets\n });\n\n await writeRenderedReport(report, options.format, options.budget, options.output);\n });\n}\n\nfunction parseOptions(rawOptions: unknown) {\n const result = PackCliOptionsSchema.safeParse(rawOptions);\n\n if (!result.success) {\n const message = result.error.issues.map((issue) => issue.message).join(\"\\n\");\n throw new Error(`Invalid pack options:\\n${message}`);\n }\n\n return result.data;\n}\n\nfunction parseBudget(value: string) {\n const parsed = Number.parseInt(value, 10);\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(\"--budget must be a positive integer.\");\n }\n\n return parsed;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { execa } from \"execa\";\n\nimport type { DiffInfo, RepositoryInfo } from \"../types.js\";\n\nconst UNTRACKED_PATCH_CHAR_LIMIT = 20_000;\nconst IGNORED_CHANGED_PATH_PREFIXES = [\"node_modules/\", \"dist/\", \"coverage/\", \".git/\"];\n\nexport interface GitCollectOptions {\n includeDiff: boolean;\n includeDiffSummary: boolean;\n since?: string;\n}\n\nexport async function findGitRoot(cwd: string): Promise<string> {\n const result = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n reject: false\n });\n\n if (result.exitCode !== 0) {\n throw new Error(\"HandoffKit must be run inside a git repository.\");\n }\n\n return result.stdout.trimEnd();\n}\n\nexport async function collectGitInfo(root: string, options: GitCollectOptions): Promise<RepositoryInfo> {\n const [branch, status, porcelainStatus, recentCommits, stagedDiffSummary, trackedUnstagedDiffSummary, baseInfo] =\n await Promise.all([\n currentBranch(root),\n git(root, [\"status\", \"--short\", \"--branch\"]),\n git(root, [\"status\", \"--porcelain=v1\", \"--untracked-files=all\"]),\n recentCommitLines(root, options.since),\n options.includeDiffSummary ? git(root, [\"diff\", \"--cached\", \"--stat\"]) : Promise.resolve(\"\"),\n options.includeDiffSummary ? git(root, [\"diff\", \"--stat\"]) : Promise.resolve(\"\"),\n options.since ? collectBaseInfo(root, options.since, options.includeDiffSummary, options.includeDiff) : Promise.resolve(undefined)\n ]);\n\n const changedFiles = uniqueSorted([...(baseInfo?.changedFiles ?? []), ...parseChangedFiles(porcelainStatus)]);\n const untrackedFiles = parseUntrackedFiles(porcelainStatus);\n const unstagedDiffSummary = options.includeDiffSummary\n ? joinSections([trackedUnstagedDiffSummary, renderUntrackedSummary(untrackedFiles)])\n : \"\";\n const diff = options.includeDiff ? await collectDiff(root, untrackedFiles) : undefined;\n\n return {\n name: basename(root),\n branch,\n ...(options.since ? { baseRef: options.since } : {}),\n status,\n recentCommits,\n changedFiles,\n ...(baseInfo?.summary ? { baseDiffSummary: baseInfo.summary } : {}),\n stagedDiffSummary,\n unstagedDiffSummary,\n includeDiff: options.includeDiff,\n ...(baseInfo?.patch ? { baseDiff: baseInfo.patch } : {}),\n ...(diff ? { diff } : {})\n };\n}\n\nasync function currentBranch(root: string) {\n const branch = await git(root, [\"branch\", \"--show-current\"]);\n\n if (branch) {\n return branch;\n }\n\n const commit = await git(root, [\"rev-parse\", \"--short\", \"HEAD\"], { allowFailure: true });\n return commit ? `detached:${commit}` : \"unknown\";\n}\n\nasync function recentCommitLines(root: string, since?: string) {\n const args = since ? [\"log\", \"--oneline\", \"-n\", \"10\", `${since}..HEAD`] : [\"log\", \"--oneline\", \"-n\", \"10\"];\n const output = await git(root, args, { allowFailure: true });\n return output ? output.split(\"\\n\") : [];\n}\n\nasync function collectBaseInfo(root: string, since: string, includeDiffSummary: boolean, includeDiff: boolean) {\n await ensureRef(root, since);\n const range = `${since}...HEAD`;\n const [changedFiles, summary, patch] = await Promise.all([\n git(root, [\"diff\", \"--name-only\", range], { allowFailure: true }),\n includeDiffSummary ? git(root, [\"diff\", \"--stat\", range], { allowFailure: true }) : Promise.resolve(\"\"),\n includeDiff ? git(root, [\"diff\", \"--patch\", range], { allowFailure: true }) : Promise.resolve(\"\")\n ]);\n\n return {\n changedFiles: changedFiles ? changedFiles.split(\"\\n\").filter(Boolean) : [],\n summary,\n patch\n };\n}\n\nasync function ensureRef(root: string, ref: string) {\n const result = await execa(\"git\", [\"rev-parse\", \"--verify\", `${ref}^{commit}`], {\n cwd: root,\n reject: false\n });\n\n if (result.exitCode !== 0) {\n throw new Error(`Could not resolve --since ref: ${ref}`);\n }\n}\n\nasync function collectDiff(root: string, untrackedFiles: string[]): Promise<DiffInfo> {\n const [staged, unstagedTracked, untracked] = await Promise.all([\n git(root, [\"diff\", \"--cached\", \"--patch\"]),\n git(root, [\"diff\", \"--patch\"]),\n untrackedPatch(root, untrackedFiles)\n ]);\n\n return { staged, unstaged: joinSections([unstagedTracked, untracked]) };\n}\n\nasync function git(root: string, args: string[], options: { allowFailure?: boolean } = {}) {\n const result = await execa(\"git\", args, {\n cwd: root,\n reject: false\n });\n\n if (result.exitCode !== 0 && !options.allowFailure) {\n throw new Error(result.stderr || `git ${args.join(\" \")} failed`);\n }\n\n return result.stdout.trim();\n}\n\nfunction parseChangedFiles(status: string) {\n const files = status\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter(Boolean)\n .map((line) => line.slice(line[2] === \" \" ? 3 : 2).trim())\n .map((path) => (path.includes(\" -> \") ? path.split(\" -> \").at(-1) ?? path : path))\n .map((path) => path.replace(/^\"|\"$/g, \"\"));\n\n return uniqueSorted(files.filter((file) => !isIgnoredChangedPath(file)));\n}\n\nfunction parseUntrackedFiles(status: string) {\n return status\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.startsWith(\"?? \"))\n .map((line) => line.slice(3).trim())\n .map((path) => path.replace(/^\"|\"$/g, \"\"))\n .filter((file) => !isIgnoredChangedPath(file))\n .sort();\n}\n\nfunction renderUntrackedSummary(files: string[]) {\n if (files.length === 0) {\n return \"\";\n }\n\n return files.map((file) => `${file} | untracked`).join(\"\\n\");\n}\n\nasync function untrackedPatch(root: string, files: string[]) {\n const patches = await Promise.all(\n files.map(async (file) => {\n const content = await readFile(`${root}/${file}`, \"utf8\");\n const trimmedContent =\n content.length > UNTRACKED_PATCH_CHAR_LIMIT\n ? `${content.slice(0, UNTRACKED_PATCH_CHAR_LIMIT).trimEnd()}\\n[truncated]`\n : content.trimEnd();\n\n return [`Untracked file: ${file}`, \"```text\", trimmedContent, \"```\"].join(\"\\n\");\n })\n );\n\n return patches.join(\"\\n\\n\");\n}\n\nfunction joinSections(sections: string[]) {\n return sections.filter(Boolean).join(\"\\n\\n\").trim();\n}\n\nfunction uniqueSorted(files: string[]) {\n return [...new Set(files.filter((file) => !isIgnoredChangedPath(file)))].sort();\n}\n\nfunction isIgnoredChangedPath(file: string) {\n return IGNORED_CHANGED_PATH_PREFIXES.some((prefix) => file === prefix.slice(0, -1) || file.startsWith(prefix));\n}\n","import { readFile, stat } from \"node:fs/promises\";\n\nimport fg from \"fast-glob\";\n\nimport type { InstructionFile } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst INSTRUCTION_PATTERNS = [\n \"**/AGENTS.md\",\n \"**/CLAUDE.md\",\n \"**/GEMINI.md\",\n \".cursor/rules\",\n \".cursor/rules/**/*\",\n \".github/copilot-instructions.md\"\n];\n\nconst PREVIEW_CHAR_LIMIT = 1200;\n\nexport async function detectInstructionFiles(root: string): Promise<InstructionFile[]> {\n const paths = await fg(INSTRUCTION_PATTERNS, {\n cwd: root,\n dot: true,\n onlyFiles: false,\n unique: true,\n ignore: [\"**/.git/**\", \"**/node_modules/**\", \"**/dist/**\", \"**/coverage/**\"]\n });\n\n return Promise.all(paths.sort().map((path) => instructionFile(root, path)));\n}\n\nasync function instructionFile(root: string, path: string): Promise<InstructionFile> {\n return {\n path,\n kind: instructionKind(path),\n preview: await readPreview(root, path)\n };\n}\n\nasync function readPreview(root: string, path: string) {\n const fullPath = `${root}/${path}`;\n const metadata = await stat(fullPath);\n\n if (!metadata.isFile()) {\n return \"Directory rule set detected.\";\n }\n\n const content = await readFile(fullPath, \"utf8\");\n const normalized = content.replace(/\\r\\n/g, \"\\n\").trim();\n const preview =\n normalized.length > PREVIEW_CHAR_LIMIT ? `${normalized.slice(0, PREVIEW_CHAR_LIMIT).trimEnd()}\\n[truncated]` : normalized;\n\n return redactText(preview);\n}\n\nfunction instructionKind(path: string): InstructionFile[\"kind\"] {\n if (path.endsWith(\"AGENTS.md\")) {\n return \"agents\";\n }\n\n if (path.endsWith(\"CLAUDE.md\")) {\n return \"claude\";\n }\n\n if (path.endsWith(\"GEMINI.md\")) {\n return \"gemini\";\n }\n\n if (path === \".cursor/rules\" || path.startsWith(\".cursor/rules/\")) {\n return \"cursor\";\n }\n\n if (path === \".github/copilot-instructions.md\") {\n return \"copilot\";\n }\n\n return \"instruction\";\n}\n","const REDACTION = \"[REDACTED]\";\n\nconst SECRET_KEY_PATTERN =\n /(\\b[A-Z0-9_.-]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CLIENT[_-]?SECRET|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|COOKIE|SESSION|JWT|AUTH_TOKEN)[A-Z0-9_.-]*\\b\\s*(?:=|:)\\s*)([\"']?)([^\\s\"',}]+)/gi;\n\nconst TOKEN_PATTERNS: RegExp[] = [\n /\\bBearer\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n /\\bsk-[A-Za-z0-9_-]{16,}/g,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}/g,\n /\\bnpm_[A-Za-z0-9_-]{16,}/g,\n /\\bxox[baprs]-[A-Za-z0-9-]{16,}/g,\n /\\bAIza[0-9A-Za-z_-]{20,}/g,\n /\\bAKIA[0-9A-Z]{16}\\b/g,\n /\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b/g,\n /\\/\\/([^/\\s:@]+):([^@\\s/]+)@/g\n];\n\nexport function redactText(input: string): string {\n let output = input.replace(\n /-----BEGIN ([A-Z ]*PRIVATE KEY)-----[\\s\\S]*?-----END \\1-----/g,\n (_match, keyType: string) => `-----BEGIN ${keyType}-----\\n${REDACTION}\\n-----END ${keyType}-----`\n );\n\n output = output.replace(SECRET_KEY_PATTERN, (_match, prefix: string, quote: string) => {\n return `${prefix}${quote}${REDACTION}${quote}`;\n });\n\n output = output.replace(/\\bBearer\\s+[A-Za-z0-9._~+/=-]{12,}/gi, \"Bearer [REDACTED]\");\n output = output.replace(/\\/\\/([^/\\s:@]+):([^@\\s/]+)@/g, \"//[REDACTED]@\");\n\n for (const pattern of TOKEN_PATTERNS.slice(1, -1)) {\n output = output.replace(pattern, REDACTION);\n }\n\n return output;\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport type { PackageInfo, VerificationScript } from \"../types.js\";\n\nconst PackageJsonSchema = z.object({\n name: z.string().optional(),\n packageManager: z.string().optional(),\n scripts: z.record(z.string(), z.string()).optional()\n});\n\nconst VERIFY_SCRIPT_ORDER = [\"build\", \"test\", \"typecheck\", \"lint\", \"check\", \"verify\", \"ci\"];\nconst VERIFY_SCRIPT_PREFIX = /^(build|test|typecheck|lint|check|verify|ci)(:|$)/;\n\nexport async function detectPackageInfo(root: string): Promise<PackageInfo | undefined> {\n const packageJsonPath = join(root, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return undefined;\n }\n\n const rawPackageJson = await readFile(packageJsonPath, \"utf8\");\n const packageJson = PackageJsonSchema.parse(JSON.parse(rawPackageJson));\n const packageManager = await detectPackageManager(root, packageJson.packageManager);\n const verificationScripts = detectVerificationScripts(packageJson.scripts ?? {});\n\n return {\n ...(packageJson.name ? { name: packageJson.name } : {}),\n ...(packageManager ? { packageManager } : {}),\n verificationScripts\n };\n}\n\nexport async function detectPackageManager(root: string, packageManagerField?: string) {\n if (packageManagerField) {\n return packageManagerField.split(\"@\")[0] || packageManagerField;\n }\n\n const lockfiles: Array<[string, string]> = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"package-lock.json\", \"npm\"],\n [\"bun.lock\", \"bun\"],\n [\"bun.lockb\", \"bun\"]\n ];\n\n for (const [lockfile, manager] of lockfiles) {\n if (await pathExists(join(root, lockfile))) {\n return manager;\n }\n }\n\n return undefined;\n}\n\nexport function detectVerificationScripts(scripts: Record<string, string>): VerificationScript[] {\n return Object.entries(scripts)\n .filter(([name]) => VERIFY_SCRIPT_PREFIX.test(name))\n .sort(([left], [right]) => {\n const leftIndex = orderIndex(left);\n const rightIndex = orderIndex(right);\n\n if (leftIndex !== rightIndex) {\n return leftIndex - rightIndex;\n }\n\n return left.localeCompare(right);\n })\n .map(([name, command]) => ({ name, command }));\n}\n\nasync function pathExists(path: string) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction orderIndex(name: string) {\n const baseName = name.split(\":\")[0] ?? name;\n const index = VERIFY_SCRIPT_ORDER.indexOf(baseName);\n return index === -1 ? VERIFY_SCRIPT_ORDER.length : index;\n}\n","import type { HandoffReport, RiskReport, RiskNote } from \"../types.js\";\n\nexport function analyzeRisk(report: HandoffReport): RiskReport {\n const files = report.repository.changedFiles;\n const notes: RiskNote[] = [];\n\n if (files.some((file) => /(^|\\/)(redact|secret|auth|token|security)/i.test(file))) {\n notes.push({\n severity: \"high\",\n title: \"Security-sensitive code changed\",\n detail: \"Review redaction, auth, token, or secret-handling changes carefully before handoff.\"\n });\n }\n\n if (files.some((file) => file === \"package.json\" || file.endsWith(\"-lock.yaml\") || file.endsWith(\"lock.json\"))) {\n notes.push({\n severity: \"medium\",\n title: \"Dependency or package metadata changed\",\n detail: \"Run install/build verification and check package publishing metadata.\"\n });\n }\n\n if (files.some((file) => file.startsWith(\".github/workflows/\"))) {\n notes.push({\n severity: \"medium\",\n title: \"CI workflow changed\",\n detail: \"Confirm GitHub Actions still passes after push.\"\n });\n }\n\n const sourceFiles = files.filter((file) => file.startsWith(\"src/\") && file.endsWith(\".ts\"));\n const testFiles = files.filter((file) => file.startsWith(\"tests/\") && file.endsWith(\".test.ts\"));\n\n if (sourceFiles.length > 0 && testFiles.length === 0) {\n notes.push({\n severity: \"medium\",\n title: \"Source changed without matching tests\",\n detail: `Review test coverage for ${sourceFiles.slice(0, 5).join(\", \")}.`\n });\n }\n\n if (notes.length === 0) {\n notes.push({\n severity: \"low\",\n title: \"No obvious local risk signals\",\n detail: \"No deterministic risk rule matched the current changed file set.\"\n });\n }\n\n return { notes };\n}\n","import { mkdtemp, readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { relative, join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { execa } from \"execa\";\n\nimport type { SecretFinding, SecretScannerReport, SecretScannerStatus, SecretScanResult } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst MAX_FINDINGS = 20;\nconst ERROR_LIMIT = 2000;\n\nexport async function detectSecretScanners(): Promise<SecretScannerReport> {\n const [gitleaks, secretlint] = await Promise.all([scannerStatus(\"gitleaks\"), scannerStatus(\"secretlint\")]);\n return { scanners: [gitleaks, secretlint] };\n}\n\nexport async function runSecretScanners(root: string): Promise<SecretScannerReport> {\n const report = await detectSecretScanners();\n const scans = await Promise.all(report.scanners.map((scanner) => runScanner(root, scanner)));\n return { ...report, scans };\n}\n\nexport function formatScannerSummary(report: SecretScannerReport): string {\n const availability = report.scanners\n .map((scanner) => `${scanner.name}: ${scanner.available ? \"available\" : \"not found\"}`)\n .join(\"\\n\");\n\n if (!report.scans) {\n return availability;\n }\n\n const scans = report.scans\n .map((scan) => `${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s)` : scan.error ?? \"not run\"}`)\n .join(\"\\n\");\n\n return `${availability}\\n${scans}`;\n}\n\nexport function normalizeGitleaksFindings(rawJson: string, limit = MAX_FINDINGS): SecretFinding[] {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return [];\n }\n\n return parsed.slice(0, limit).map((finding) => {\n const ruleId = stringValue(finding.RuleID);\n const file = stringValue(finding.File);\n const line = numberValue(finding.StartLine);\n\n return {\n ...(ruleId ? { ruleId } : {}),\n message: redactText(stringValue(finding.Description) || \"Secret finding\"),\n ...(file ? { file } : {}),\n ...(line ? { line } : {})\n };\n });\n}\n\nexport function normalizeSecretlintFindings(rawJson: string, limit = MAX_FINDINGS, root?: string): SecretFinding[] {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return [];\n }\n\n const findings: SecretFinding[] = [];\n\n for (const fileResult of parsed) {\n const messages = Array.isArray(fileResult.messages) ? fileResult.messages : [];\n\n for (const message of messages) {\n if (findings.length >= limit) {\n return findings;\n }\n\n const filePath = stringValue(fileResult.filePath);\n const ruleId = stringValue(message.ruleId);\n const line = numberValue(message.line);\n findings.push({\n ...(ruleId ? { ruleId } : {}),\n message: redactText(stringValue(message.message) || \"Secret finding\"),\n ...(filePath ? { file: root ? relative(root, filePath) || filePath : filePath } : {}),\n ...(line ? { line } : {})\n });\n }\n }\n\n return findings;\n}\n\nasync function scannerStatus(name: \"gitleaks\" | \"secretlint\"): Promise<SecretScannerStatus> {\n const result = await execa(name, [\"--version\"], {\n reject: false\n }).catch(() => undefined);\n\n return {\n name,\n available: Boolean(result && result.exitCode === 0),\n ...(result?.stdout ? { version: result.stdout.trim() } : {})\n };\n}\n\nasync function runScanner(root: string, scanner: SecretScannerStatus): Promise<SecretScanResult> {\n if (!scanner.available) {\n return {\n name: scanner.name,\n available: false,\n ran: false,\n findings: [],\n error: \"Scanner binary not found.\",\n truncated: false\n };\n }\n\n return scanner.name === \"gitleaks\" ? runGitleaks(root) : runSecretlint(root);\n}\n\nasync function runGitleaks(root: string): Promise<SecretScanResult> {\n const started = performance.now();\n const tempDir = await mkdtemp(join(tmpdir(), \"handoffkit-gitleaks-\"));\n const reportPath = join(tempDir, \"report.json\");\n const result = await execa(\n \"gitleaks\",\n [\"dir\", root, \"--no-banner\", \"--no-color\", \"--redact=100\", \"--report-format\", \"json\", \"--report-path\", reportPath, \"--max-target-megabytes\", \"2\"],\n { reject: false, all: true }\n );\n const rawReport = await readFile(reportPath, \"utf8\").catch(() => \"[]\");\n const findings = normalizeGitleaksFindings(rawReport);\n\n return {\n name: \"gitleaks\",\n available: true,\n ran: result.exitCode === 0 || result.exitCode === 1,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n findings,\n ...(result.exitCode && result.exitCode > 1 ? { error: redactText(trimError(result.all ?? result.stderr ?? \"\")) } : {}),\n truncated: countJsonArray(rawReport) > findings.length\n };\n}\n\nasync function runSecretlint(root: string): Promise<SecretScanResult> {\n const started = performance.now();\n const result = await execa(\"secretlint\", [\"**/*\", \"--format\", \"json\", \"--no-color\"], {\n cwd: root,\n reject: false,\n all: true\n });\n const rawOutput = result.stdout || result.all || \"[]\";\n const findings = normalizeSecretlintFindings(rawOutput, MAX_FINDINGS, root);\n\n return {\n name: \"secretlint\",\n available: true,\n ran: result.exitCode === 0 || result.exitCode === 1,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n findings,\n ...(result.exitCode && result.exitCode > 1 ? { error: redactText(trimError(result.all ?? result.stderr ?? \"\")) } : {}),\n truncated: countSecretlintMessages(rawOutput) > findings.length\n };\n}\n\nfunction safeJson(rawJson: string): unknown {\n try {\n return JSON.parse(rawJson || \"[]\");\n } catch {\n return [];\n }\n}\n\nfunction stringValue(value: unknown) {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction numberValue(value: unknown) {\n return typeof value === \"number\" ? value : undefined;\n}\n\nfunction countJsonArray(rawJson: string) {\n const parsed = safeJson(rawJson);\n return Array.isArray(parsed) ? parsed.length : 0;\n}\n\nfunction countSecretlintMessages(rawJson: string) {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return 0;\n }\n\n return parsed.reduce((count, fileResult) => {\n return count + (Array.isArray(fileResult.messages) ? fileResult.messages.length : 0);\n }, 0);\n}\n\nfunction trimError(output: string) {\n const trimmed = output.trim();\n return trimmed.length > ERROR_LIMIT ? `${trimmed.slice(0, ERROR_LIMIT)}\\n[truncated]` : trimmed;\n}\n","import { performance } from \"node:perf_hooks\";\n\nimport { execa } from \"execa\";\n\nimport type { PackageInfo, VerificationReport, VerificationResult, VerificationScript } from \"../types.js\";\nimport { detectPackageInfo } from \"./package-json.js\";\n\nconst VERIFY_ORDER = [\"typecheck\", \"lint\", \"test\", \"build\"];\nconst OUTPUT_LIMIT = 4000;\n\nexport function selectVerificationScripts(packageInfo: PackageInfo | undefined): VerificationScript[] {\n if (!packageInfo) {\n return [];\n }\n\n return VERIFY_ORDER.flatMap((name) => packageInfo.verificationScripts.filter((script) => script.name === name));\n}\n\nexport async function runVerification(root: string): Promise<VerificationReport> {\n const packageInfo = await detectPackageInfo(root);\n const scripts = selectVerificationScripts(packageInfo);\n const commands: VerificationResult[] = [];\n\n for (const script of scripts) {\n commands.push(await runScript(root, packageInfo?.packageManager ?? \"npm\", script));\n }\n\n return { commands };\n}\n\nasync function runScript(root: string, packageManager: string, script: VerificationScript): Promise<VerificationResult> {\n const started = performance.now();\n const command = `${packageManager} run ${script.name}`;\n const result = await execa(packageManager, [\"run\", script.name], {\n cwd: root,\n reject: false,\n all: true\n });\n\n return {\n name: script.name,\n command,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n output: trimOutput(result.all ?? result.stdout ?? result.stderr ?? \"\")\n };\n}\n\nfunction trimOutput(output: string) {\n const normalized = output.trim();\n return normalized.length > OUTPUT_LIMIT ? `${normalized.slice(-OUTPUT_LIMIT)}\\n[trimmed]` : normalized;\n}\n","import type { HandoffReport, PackOptions } from \"../types.js\";\nimport { collectGitInfo, findGitRoot } from \"./git.js\";\nimport { detectInstructionFiles } from \"./instructions.js\";\nimport { detectPackageInfo } from \"./package-json.js\";\nimport { analyzeRisk } from \"./risk.js\";\nimport { detectSecretScanners, runSecretScanners } from \"./scanners.js\";\nimport { runVerification } from \"./verify.js\";\n\nexport async function collectHandoffReport(options: PackOptions): Promise<HandoffReport> {\n const root = await findGitRoot(options.cwd);\n const [repository, instructionFiles, packageInfo, secretScanning] = await Promise.all([\n collectGitInfo(root, {\n includeDiff: options.includeDiff && options.includeDiffSummary,\n includeDiffSummary: options.includeDiffSummary,\n ...(options.since ? { since: options.since } : {})\n }),\n detectInstructionFiles(root),\n detectPackageInfo(root),\n options.scanSecrets ? runSecretScanners(root) : detectSecretScanners()\n ]);\n\n const report: HandoffReport = {\n goal: options.goal,\n target: options.target,\n repository,\n instructionFiles,\n ...(packageInfo ? { packageInfo } : {}),\n ...(options.resumeSource ? { resumeSource: options.resumeSource } : {}),\n ...(options.includeVerification ? { verification: await runVerification(root) } : {}),\n secretScanning,\n budget: {\n requestedTokens: options.budget,\n estimatedTokens: 0,\n wasTrimmed: false\n }\n };\n\n report.risk = analyzeRisk(report);\n return report;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { applyMarkdownBudget, estimateTokens } from \"../core/budget.js\";\nimport { redactText } from \"../core/redact.js\";\nimport { renderJsonReport } from \"../report/json.js\";\nimport { renderMarkdownReport } from \"../report/markdown.js\";\nimport type { HandoffReport, OutputFormat } from \"../types.js\";\n\nexport async function writeRenderedReport(report: HandoffReport, format: OutputFormat, budget: number, output?: string) {\n const rendered = redactText(renderOutput(report, format, budget));\n\n if (output) {\n const outputPath = resolve(process.cwd(), output);\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, rendered, \"utf8\");\n process.stderr.write(`Wrote handoff packet to ${outputPath}\\n`);\n return;\n }\n\n process.stdout.write(rendered);\n}\n\nfunction renderOutput(report: HandoffReport, format: OutputFormat, budget: number) {\n if (format === \"json\") {\n const rendered = renderJsonReport(report);\n report.budget.estimatedTokens = estimateTokens(rendered);\n return renderJsonReport(report);\n }\n\n const firstRender = renderMarkdownReport(report);\n const budgeted = applyMarkdownBudget(firstRender, budget);\n report.budget.estimatedTokens = budgeted.estimatedTokens;\n report.budget.wasTrimmed = budgeted.wasTrimmed;\n\n if (budgeted.wasTrimmed) {\n return budgeted.text;\n }\n\n return renderMarkdownReport(report);\n}\n","export function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport function applyMarkdownBudget(text: string, budget: number) {\n const estimatedTokens = estimateTokens(text);\n\n if (estimatedTokens <= budget) {\n return { text, estimatedTokens, wasTrimmed: false };\n }\n\n const notice = `\\n\\n> Output trimmed to fit --budget ${budget}. Re-run with a larger budget or --output for the full packet.\\n`;\n const charLimit = Math.max(0, budget * 4 - notice.length);\n const trimmed = `${text.slice(0, charLimit).trimEnd()}${notice}`;\n\n return {\n text: trimmed,\n estimatedTokens: estimateTokens(trimmed),\n wasTrimmed: true\n };\n}\n","import type { HandoffReport } from \"../types.js\";\n\nexport function renderJsonReport(report: HandoffReport): string {\n return `${JSON.stringify(report, null, 2)}\\n`;\n}\n","import type { HandoffReport, PackageInfo } from \"../types.js\";\n\nexport function renderMarkdownReport(report: HandoffReport): string {\n const lines: string[] = [\n `# ${titleForTarget(report.target)}`,\n \"\",\n \"## Goal\",\n report.goal,\n \"\",\n \"## Repository\",\n `- Repository: \\`${report.repository.name}\\``,\n `- Branch: \\`${report.repository.branch}\\``,\n `- Changed files: ${report.repository.changedFiles.length}`,\n \"\",\n \"## Git Status\",\n codeBlock(report.repository.status || \"Clean working tree.\"),\n \"\",\n \"## Recent Commits\",\n listOrNone(report.repository.recentCommits.map((commit) => `- ${commit}`)),\n \"\",\n \"## Changed Files\",\n listOrNone(report.repository.changedFiles.map((file) => `- \\`${file}\\``)),\n \"\",\n ...renderBaseDiffSummary(report),\n \"## Diff Summary\",\n \"### Staged\",\n codeBlock(report.repository.stagedDiffSummary || \"No staged diff.\"),\n \"\",\n \"### Unstaged\",\n codeBlock(report.repository.unstagedDiffSummary || \"No unstaged diff.\"),\n \"\",\n \"## Instruction Files\",\n renderInstructionFiles(report.instructionFiles),\n \"\",\n \"## Package\",\n renderPackage(report.packageInfo),\n \"\",\n ...renderResumeSource(report),\n ...renderVerification(report),\n ...renderRisk(report),\n ...renderSecretScanning(report),\n \"## Next Agent Notes\",\n \"- This packet was generated from local git and filesystem state.\",\n \"- Likely secrets were redacted from generated output.\",\n \"- No LLM APIs were called.\"\n ];\n\n if (report.repository.includeDiff && report.repository.diff) {\n lines.splice(\n lines.indexOf(\"## Instruction Files\"),\n 0,\n \"## Included Diff\",\n \"### Staged Patch\",\n codeBlock(report.repository.diff.staged || \"No staged patch.\"),\n \"\",\n \"### Unstaged Patch\",\n codeBlock(report.repository.diff.unstaged || \"No unstaged patch.\"),\n \"\"\n );\n }\n\n if (report.repository.includeDiff && report.repository.baseDiff) {\n lines.splice(\n lines.indexOf(\"## Included Diff\"),\n 0,\n `## Included Branch Delta Since \\`${report.repository.baseRef}\\``,\n codeBlock(report.repository.baseDiff),\n \"\"\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction titleForTarget(target = \"generic\") {\n const labels: Record<string, string> = {\n generic: \"Handoff Packet\",\n codex: \"Codex Handoff Packet\",\n claude: \"Claude Handoff Packet\",\n cursor: \"Cursor Handoff Packet\"\n };\n\n return labels[target] ?? \"Handoff Packet\";\n}\n\nfunction renderBaseDiffSummary(report: HandoffReport) {\n if (!report.repository.baseRef) {\n return [];\n }\n\n return [\n `## Branch Delta Since \\`${report.repository.baseRef}\\``,\n codeBlock(report.repository.baseDiffSummary || \"No committed branch delta detected.\"),\n \"\"\n ];\n}\n\nfunction renderPackage(packageInfo: PackageInfo | undefined) {\n if (!packageInfo) {\n return \"No package.json detected.\";\n }\n\n const lines = [\n packageInfo.name ? `- Package: \\`${packageInfo.name}\\`` : undefined,\n packageInfo.packageManager ? `- Package manager: \\`${packageInfo.packageManager}\\`` : undefined\n ].filter((line): line is string => Boolean(line));\n\n if (packageInfo.verificationScripts.length > 0) {\n const prefix = packageInfo.packageManager ?? \"npm\";\n lines.push(\"- Verification scripts:\");\n lines.push(...packageInfo.verificationScripts.map((script) => ` - \\`${prefix} ${script.name}\\``));\n } else {\n lines.push(\"- Verification scripts: none detected.\");\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction renderInstructionFiles(instructionFiles: HandoffReport[\"instructionFiles\"]) {\n if (instructionFiles.length === 0) {\n return \"None detected.\";\n }\n\n return instructionFiles\n .map((file) => [`- \\`${file.path}\\` (${file.kind})`, codeBlock(file.preview || \"No preview available.\")].join(\"\\n\"))\n .join(\"\\n\\n\");\n}\n\nfunction renderResumeSource(report: HandoffReport) {\n if (!report.resumeSource) {\n return [];\n }\n\n return [\"## Resume Source\", `- Source: \\`${report.resumeSource.path}\\``, codeBlock(report.resumeSource.preview), \"\"];\n}\n\nfunction renderVerification(report: HandoffReport) {\n if (!report.verification) {\n return [];\n }\n\n return [\n \"## Verification\",\n report.verification.commands.length > 0\n ? report.verification.commands\n .map((command) =>\n [`- \\`${command.command}\\` exited ${command.exitCode} in ${command.durationMs}ms`, codeBlock(command.output || \"No output.\")]\n .join(\"\\n\")\n )\n .join(\"\\n\\n\")\n : \"No safe verification scripts detected.\",\n \"\"\n ];\n}\n\nfunction renderRisk(report: HandoffReport) {\n if (!report.risk) {\n return [];\n }\n\n return [\n \"## Risk Notes\",\n report.risk.notes.map((note) => `- **${note.severity}**: ${note.title} - ${note.detail}`).join(\"\\n\"),\n \"\"\n ];\n}\n\nfunction renderSecretScanning(report: HandoffReport) {\n if (!report.secretScanning) {\n return [];\n }\n\n return [\n report.secretScanning.scans ? \"## Secret Scan Results\" : \"## Secret Scanner Availability\",\n renderSecretScannerReport(report.secretScanning),\n \"\"\n ];\n}\n\nfunction renderSecretScannerReport(secretScanning: NonNullable<HandoffReport[\"secretScanning\"]>) {\n if (!secretScanning.scans) {\n return secretScanning.scanners.map((scanner) => `- ${scanner.name}: ${scanner.available ? \"available\" : \"not found\"}`).join(\"\\n\");\n }\n\n return secretScanning.scans\n .map((scan) => {\n const lines = [\n `- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? \"not run\"}`\n ];\n\n for (const finding of scan.findings) {\n lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : \"\"}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : \"\"})` : \"\"}`);\n }\n\n if (scan.truncated) {\n lines.push(\" - Additional findings were truncated.\");\n }\n\n return lines.join(\"\\n\");\n })\n .join(\"\\n\");\n}\n\nfunction codeBlock(text: string) {\n return [\"```text\", text, \"```\"].join(\"\\n\");\n}\n\nfunction listOrNone(items: string[]) {\n return items.length > 0 ? items.join(\"\\n\") : \"None detected.\";\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\nimport { createResumeSource } from \"../../core/resume.js\";\nimport { writeRenderedReport } from \"../output.js\";\n\nconst ResumeOptionsSchema = z.object({\n goal: z.string().trim().min(1).default(\"Resume interrupted AI coding session\"),\n output: z.string().optional(),\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\"),\n for: z.enum([\"generic\", \"codex\", \"claude\", \"cursor\"]).default(\"generic\"),\n budget: z.number().int().positive().default(4000)\n});\n\nexport function createResumeCommand() {\n return new Command(\"resume\")\n .description(\"Create a fresh handoff packet using a previous handoff as resume context.\")\n .argument(\"<path>\", \"previous handoff or transcript file\")\n .option(\"--goal <text>\", \"new handoff goal\", \"Resume interrupted AI coding session\")\n .option(\"--output <path>\", \"write output to a file instead of stdout\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .option(\"--for <agent>\", \"target output: generic, codex, claude, or cursor\", \"generic\")\n .option(\"--budget <tokens>\", \"rough output token budget\", parseBudget, 4000)\n .action(async (path: string, rawOptions) => {\n const options = ResumeOptionsSchema.parse(rawOptions);\n const source = createResumeSource(path, await readFile(path, \"utf8\"));\n const report = await collectHandoffReport({\n goal: options.goal,\n cwd: process.cwd(),\n ...(options.output ? { output: options.output } : {}),\n format: options.format,\n target: options.for,\n budget: options.budget,\n includeDiff: false,\n includeDiffSummary: true,\n includeVerification: false,\n scanSecrets: false,\n resumeSource: source\n });\n\n await writeRenderedReport(report, options.format, options.budget, options.output);\n });\n}\n\nfunction parseBudget(value: string) {\n const parsed = Number.parseInt(value, 10);\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(\"--budget must be a positive integer.\");\n }\n\n return parsed;\n}\n","import type { ResumeSource } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst RESUME_PREVIEW_LIMIT = 3000;\n\nexport function createResumeSource(path: string, content: string): ResumeSource {\n const normalized = content.replace(/\\r\\n/g, \"\\n\").trim();\n const preview =\n normalized.length > RESUME_PREVIEW_LIMIT ? `${normalized.slice(0, RESUME_PREVIEW_LIMIT).trimEnd()}\\n[truncated]` : normalized;\n\n return {\n path,\n preview: redactText(preview)\n };\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\n\nconst RiskOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createRiskCommand() {\n return new Command(\"risk\")\n .description(\"Show deterministic risk notes for the current handoff.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = RiskOptionsSchema.parse(rawOptions);\n const report = await collectHandoffReport({\n goal: \"Review local risk\",\n cwd: process.cwd(),\n format: options.format,\n target: \"generic\",\n budget: 4000,\n includeDiff: false,\n includeDiffSummary: false,\n includeVerification: false,\n scanSecrets: false\n });\n\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(report.risk, null, 2)}\\n`);\n return;\n }\n\n process.stdout.write(`# Risk Notes\\n\\n${report.risk?.notes.map((note) => `- **${note.severity}**: ${note.title} - ${note.detail}`).join(\"\\n\")}\\n`);\n });\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { findGitRoot } from \"../../core/git.js\";\nimport { redactText } from \"../../core/redact.js\";\nimport { runSecretScanners } from \"../../core/scanners.js\";\n\nconst ScanSecretsOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createScanSecretsCommand() {\n return new Command(\"scan-secrets\")\n .description(\"Run optional local secret scanners and print bounded redacted results.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = ScanSecretsOptionsSchema.parse(rawOptions);\n const root = await findGitRoot(process.cwd());\n const report = await runSecretScanners(root);\n\n if (options.format === \"json\") {\n process.stdout.write(redactText(`${JSON.stringify(report, null, 2)}\\n`));\n return;\n }\n\n process.stdout.write(redactText(renderScanMarkdown(report)));\n });\n}\n\nfunction renderScanMarkdown(report: Awaited<ReturnType<typeof runSecretScanners>>) {\n const lines = [\"# Secret Scan Results\", \"\"];\n\n for (const scan of report.scans ?? []) {\n lines.push(`- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? \"not run\"}`);\n\n for (const finding of scan.findings) {\n lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : \"\"}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : \"\"})` : \"\"}`);\n }\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { findGitRoot } from \"../../core/git.js\";\nimport { redactText } from \"../../core/redact.js\";\nimport { runVerification } from \"../../core/verify.js\";\nimport type { VerificationResult } from \"../../types.js\";\n\nconst VerifyOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createVerifyCommand() {\n return new Command(\"verify\")\n .description(\"Run safe local verification scripts.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = VerifyOptionsSchema.parse(rawOptions);\n const root = await findGitRoot(process.cwd());\n const verification = await runVerification(root);\n\n if (options.format === \"json\") {\n process.stdout.write(redactText(`${JSON.stringify(verification, null, 2)}\\n`));\n return;\n }\n\n process.stdout.write(redactText(renderVerificationMarkdown(verification.commands)));\n });\n}\n\nfunction renderVerificationMarkdown(commands: VerificationResult[]) {\n const lines = [\"# Verification\", \"\"];\n\n if (commands.length === 0) {\n lines.push(\"No safe verification scripts detected.\");\n } else {\n for (const command of commands) {\n lines.push(`- \\`${command.command}\\` exited ${command.exitCode} in ${command.durationMs}ms`);\n }\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n"],"mappings":"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","names":["Command","z","readFile","readFile","readFile","readFile","join","execa","execa","join","readFile","performance","execa","performance","execa","z","readFile","Command","z","z","Command","parseBudget","readFile","Command","z","z","Command","Command","z","z","Command","Command","z","z","Command","Command"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/cli/commands/pack.ts","../src/core/git.ts","../src/cli/errors.ts","../src/core/instructions.ts","../src/core/redact.ts","../src/core/package-json.ts","../src/core/risk.ts","../src/core/scanners.ts","../src/core/verify.ts","../src/core/collect.ts","../src/cli/output.ts","../src/core/budget.ts","../src/report/json.ts","../src/report/profiles.ts","../src/report/markdown.ts","../src/cli/commands/resume.ts","../src/core/resume.ts","../src/cli/commands/risk.ts","../src/cli/commands/scan-secrets.ts","../src/cli/commands/verify.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\n\nimport { createPackCommand } from \"./commands/pack.js\";\nimport { createResumeCommand } from \"./commands/resume.js\";\nimport { createRiskCommand } from \"./commands/risk.js\";\nimport { createScanSecretsCommand } from \"./commands/scan-secrets.js\";\nimport { createVerifyCommand } from \"./commands/verify.js\";\nimport { formatCliError } from \"./errors.js\";\n\nconst program = new Command()\n .name(\"handoffkit\")\n .description(\"Create safe local handoff packets for AI-assisted coding sessions.\")\n .summary(\"Create local-first AI coding session handoff packets.\")\n .showHelpAfterError(\"(run with --help for usage)\")\n .version(\"0.2.0\");\n\nprogram.addCommand(createPackCommand());\nprogram.addCommand(createVerifyCommand());\nprogram.addCommand(createRiskCommand());\nprogram.addCommand(createScanSecretsCommand());\nprogram.addCommand(createResumeCommand());\n\ntry {\n await program.parseAsync(process.argv);\n} catch (error) {\n process.stderr.write(`${formatCliError(error)}\\n`);\n process.exitCode = 1;\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\nimport { writeRenderedReport } from \"../output.js\";\n\nconst PackCliOptionsSchema = z.object({\n goal: z.string().trim().min(1).default(\"Make your own goal\"),\n output: z.string().optional(),\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\"),\n for: z.enum([\"generic\", \"codex\", \"claude\", \"cursor\"]).default(\"generic\"),\n budget: z.number().int().positive().default(4000),\n includeDiff: z.boolean().default(false),\n diff: z.boolean().default(true),\n since: z.string().trim().min(1).optional(),\n verify: z.boolean().default(false),\n scanSecrets: z.boolean().default(false)\n});\n\nexport function createPackCommand() {\n return new Command(\"pack\")\n .description(\"Create a safe local handoff packet for another AI assistant.\")\n .summary(\"Create a Markdown or JSON packet from the current git state.\")\n .option(\"--goal <text>\", \"handoff goal\", \"Make your own goal\")\n .option(\"--output <path>\", \"write output to a file instead of stdout\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .option(\"--for <agent>\", \"target output: generic, codex, claude, or cursor\", \"generic\")\n .option(\"--budget <tokens>\", \"rough output token budget\", parseBudget, 4000)\n .option(\"--since <ref>\", \"focus committed branch delta on a base ref\")\n .option(\"--verify\", \"run safe verification scripts and include results\")\n .option(\"--scan-secrets\", \"run optional local secret scanners and include bounded results\")\n .option(\"--include-diff\", \"include full staged and unstaged patches\", false)\n .option(\"--no-diff\", \"omit diff summaries and full patches\")\n .action(async (rawOptions) => {\n const options = parseOptions(rawOptions);\n const report = await collectHandoffReport({\n goal: options.goal,\n cwd: process.cwd(),\n ...(options.output ? { output: options.output } : {}),\n format: options.format,\n target: options.for,\n budget: options.budget,\n includeDiff: options.includeDiff,\n includeDiffSummary: options.diff,\n ...(options.since ? { since: options.since } : {}),\n includeVerification: options.verify,\n scanSecrets: options.scanSecrets\n });\n\n await writeRenderedReport(report, options.format, options.budget, options.output);\n });\n}\n\nfunction parseOptions(rawOptions: unknown) {\n const result = PackCliOptionsSchema.safeParse(rawOptions);\n\n if (!result.success) {\n const message = result.error.issues.map((issue) => issue.message).join(\"\\n\");\n throw new Error(`Invalid pack options:\\n${message}`);\n }\n\n return result.data;\n}\n\nfunction parseBudget(value: string) {\n const parsed = Number.parseInt(value, 10);\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(\"--budget must be a positive integer.\");\n }\n\n return parsed;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { execa } from \"execa\";\n\nimport { HandoffKitCliError } from \"../cli/errors.js\";\nimport type { DiffInfo, RepositoryInfo } from \"../types.js\";\n\nconst UNTRACKED_PATCH_CHAR_LIMIT = 20_000;\nconst IGNORED_CHANGED_PATH_PREFIXES = [\"node_modules/\", \"dist/\", \"coverage/\", \".git/\"];\n\nexport interface GitCollectOptions {\n includeDiff: boolean;\n includeDiffSummary: boolean;\n since?: string;\n}\n\nexport async function findGitRoot(cwd: string): Promise<string> {\n const result = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n reject: false\n });\n\n if (result.exitCode !== 0) {\n throw new HandoffKitCliError([\n \"HandoffKit must be run inside a git repository.\",\n \"Run this command from a git checkout, or initialize one with `git init`.\"\n ].join(\"\\n\"));\n }\n\n return result.stdout.trimEnd();\n}\n\nexport async function collectGitInfo(root: string, options: GitCollectOptions): Promise<RepositoryInfo> {\n const [branch, status, porcelainStatus, recentCommits, stagedDiffSummary, trackedUnstagedDiffSummary, baseInfo] =\n await Promise.all([\n currentBranch(root),\n git(root, [\"status\", \"--short\", \"--branch\"]),\n git(root, [\"status\", \"--porcelain=v1\", \"--untracked-files=all\"]),\n recentCommitLines(root, options.since),\n options.includeDiffSummary ? git(root, [\"diff\", \"--cached\", \"--stat\"]) : Promise.resolve(\"\"),\n options.includeDiffSummary ? git(root, [\"diff\", \"--stat\"]) : Promise.resolve(\"\"),\n options.since ? collectBaseInfo(root, options.since, options.includeDiffSummary, options.includeDiff) : Promise.resolve(undefined)\n ]);\n\n const changedFiles = uniqueSorted([...(baseInfo?.changedFiles ?? []), ...parseChangedFiles(porcelainStatus)]);\n const untrackedFiles = parseUntrackedFiles(porcelainStatus);\n const unstagedDiffSummary = options.includeDiffSummary\n ? joinSections([trackedUnstagedDiffSummary, renderUntrackedSummary(untrackedFiles)])\n : \"\";\n const diff = options.includeDiff ? await collectDiff(root, untrackedFiles) : undefined;\n\n return {\n name: basename(root),\n branch,\n ...(options.since ? { baseRef: options.since } : {}),\n status,\n recentCommits,\n changedFiles,\n ...(baseInfo?.summary ? { baseDiffSummary: baseInfo.summary } : {}),\n stagedDiffSummary,\n unstagedDiffSummary,\n includeDiff: options.includeDiff,\n ...(baseInfo?.patch ? { baseDiff: baseInfo.patch } : {}),\n ...(diff ? { diff } : {})\n };\n}\n\nasync function currentBranch(root: string) {\n const branch = await git(root, [\"branch\", \"--show-current\"]);\n\n if (branch) {\n return branch;\n }\n\n const commit = await git(root, [\"rev-parse\", \"--short\", \"HEAD\"], { allowFailure: true });\n return commit ? `detached:${commit}` : \"unknown\";\n}\n\nasync function recentCommitLines(root: string, since?: string) {\n const args = since ? [\"log\", \"--oneline\", \"-n\", \"10\", `${since}..HEAD`] : [\"log\", \"--oneline\", \"-n\", \"10\"];\n const output = await git(root, args, { allowFailure: true });\n return output ? output.split(\"\\n\") : [];\n}\n\nasync function collectBaseInfo(root: string, since: string, includeDiffSummary: boolean, includeDiff: boolean) {\n await ensureRef(root, since);\n const range = `${since}...HEAD`;\n const [changedFiles, summary, patch] = await Promise.all([\n git(root, [\"diff\", \"--name-only\", range], { allowFailure: true }),\n includeDiffSummary ? git(root, [\"diff\", \"--stat\", range], { allowFailure: true }) : Promise.resolve(\"\"),\n includeDiff ? git(root, [\"diff\", \"--patch\", range], { allowFailure: true }) : Promise.resolve(\"\")\n ]);\n\n return {\n changedFiles: changedFiles ? changedFiles.split(\"\\n\").filter(Boolean) : [],\n summary,\n patch\n };\n}\n\nasync function ensureRef(root: string, ref: string) {\n const result = await execa(\"git\", [\"rev-parse\", \"--verify\", `${ref}^{commit}`], {\n cwd: root,\n reject: false\n });\n\n if (result.exitCode !== 0) {\n throw new Error(`Could not resolve --since ref: ${ref}`);\n }\n}\n\nasync function collectDiff(root: string, untrackedFiles: string[]): Promise<DiffInfo> {\n const [staged, unstagedTracked, untracked] = await Promise.all([\n git(root, [\"diff\", \"--cached\", \"--patch\"]),\n git(root, [\"diff\", \"--patch\"]),\n untrackedPatch(root, untrackedFiles)\n ]);\n\n return { staged, unstaged: joinSections([unstagedTracked, untracked]) };\n}\n\nasync function git(root: string, args: string[], options: { allowFailure?: boolean } = {}) {\n const result = await execa(\"git\", args, {\n cwd: root,\n reject: false\n });\n\n if (result.exitCode !== 0 && !options.allowFailure) {\n throw new Error(result.stderr || `git ${args.join(\" \")} failed`);\n }\n\n return result.stdout.trim();\n}\n\nfunction parseChangedFiles(status: string) {\n const files = status\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter(Boolean)\n .map((line) => line.slice(line[2] === \" \" ? 3 : 2).trim())\n .map((path) => (path.includes(\" -> \") ? path.split(\" -> \").at(-1) ?? path : path))\n .map((path) => path.replace(/^\"|\"$/g, \"\"));\n\n return uniqueSorted(files.filter((file) => !isIgnoredChangedPath(file)));\n}\n\nfunction parseUntrackedFiles(status: string) {\n return status\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.startsWith(\"?? \"))\n .map((line) => line.slice(3).trim())\n .map((path) => path.replace(/^\"|\"$/g, \"\"))\n .filter((file) => !isIgnoredChangedPath(file))\n .sort();\n}\n\nfunction renderUntrackedSummary(files: string[]) {\n if (files.length === 0) {\n return \"\";\n }\n\n return files.map((file) => `${file} | untracked`).join(\"\\n\");\n}\n\nasync function untrackedPatch(root: string, files: string[]) {\n const patches = await Promise.all(\n files.map(async (file) => {\n const content = await readFile(`${root}/${file}`, \"utf8\");\n const trimmedContent =\n content.length > UNTRACKED_PATCH_CHAR_LIMIT\n ? `${content.slice(0, UNTRACKED_PATCH_CHAR_LIMIT).trimEnd()}\\n[truncated]`\n : content.trimEnd();\n\n return [`Untracked file: ${file}`, \"```text\", trimmedContent, \"```\"].join(\"\\n\");\n })\n );\n\n return patches.join(\"\\n\\n\");\n}\n\nfunction joinSections(sections: string[]) {\n return sections.filter(Boolean).join(\"\\n\\n\").trim();\n}\n\nfunction uniqueSorted(files: string[]) {\n return [...new Set(files.filter((file) => !isIgnoredChangedPath(file)))].sort();\n}\n\nfunction isIgnoredChangedPath(file: string) {\n return IGNORED_CHANGED_PATH_PREFIXES.some((prefix) => file === prefix.slice(0, -1) || file.startsWith(prefix));\n}\n","export class HandoffKitCliError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"HandoffKitCliError\";\n }\n}\n\nexport function formatCliError(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return message.trim();\n}\n","import { readFile, stat } from \"node:fs/promises\";\n\nimport fg from \"fast-glob\";\n\nimport type { InstructionFile } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst INSTRUCTION_PATTERNS = [\n \"**/AGENTS.md\",\n \"**/CLAUDE.md\",\n \"**/GEMINI.md\",\n \".cursor/rules\",\n \".cursor/rules/**/*\",\n \".github/copilot-instructions.md\"\n];\n\nconst PREVIEW_CHAR_LIMIT = 1200;\n\nexport async function detectInstructionFiles(root: string): Promise<InstructionFile[]> {\n const paths = await fg(INSTRUCTION_PATTERNS, {\n cwd: root,\n dot: true,\n onlyFiles: false,\n unique: true,\n ignore: [\"**/.git/**\", \"**/node_modules/**\", \"**/dist/**\", \"**/coverage/**\"]\n });\n\n return Promise.all(paths.sort().map((path) => instructionFile(root, path)));\n}\n\nasync function instructionFile(root: string, path: string): Promise<InstructionFile> {\n return {\n path,\n kind: instructionKind(path),\n preview: await readPreview(root, path)\n };\n}\n\nasync function readPreview(root: string, path: string) {\n const fullPath = `${root}/${path}`;\n const metadata = await stat(fullPath);\n\n if (!metadata.isFile()) {\n return \"Directory rule set detected.\";\n }\n\n const content = await readFile(fullPath, \"utf8\");\n const normalized = content.replace(/\\r\\n/g, \"\\n\").trim();\n const preview =\n normalized.length > PREVIEW_CHAR_LIMIT ? `${normalized.slice(0, PREVIEW_CHAR_LIMIT).trimEnd()}\\n[truncated]` : normalized;\n\n return redactText(preview);\n}\n\nfunction instructionKind(path: string): InstructionFile[\"kind\"] {\n if (path.endsWith(\"AGENTS.md\")) {\n return \"agents\";\n }\n\n if (path.endsWith(\"CLAUDE.md\")) {\n return \"claude\";\n }\n\n if (path.endsWith(\"GEMINI.md\")) {\n return \"gemini\";\n }\n\n if (path === \".cursor/rules\" || path.startsWith(\".cursor/rules/\")) {\n return \"cursor\";\n }\n\n if (path === \".github/copilot-instructions.md\") {\n return \"copilot\";\n }\n\n return \"instruction\";\n}\n","const REDACTION = \"[REDACTED]\";\n\nconst SECRET_KEY_PATTERN =\n /(\\b(?:[A-Z0-9]+[_.-])*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CLIENT[_-]?SECRET|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|COOKIE|SESSION|JWT|AUTH_TOKEN)(?:[_.-][A-Z0-9]+)*\\b\\s*(?:=|:)\\s*)([\"']?)([^\\s\"',}]+)/gi;\n\nconst TOKEN_PATTERNS: RegExp[] = [\n /\\bBearer\\s+[A-Za-z0-9._~+/=-]{12,}/gi,\n /\\bsk-[A-Za-z0-9_-]{16,}/g,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}/g,\n /\\bnpm_[A-Za-z0-9_-]{16,}/g,\n /\\bxox[baprs]-[A-Za-z0-9-]{16,}/g,\n /\\bAIza[0-9A-Za-z_-]{20,}/g,\n /\\bAKIA[0-9A-Z]{16}\\b/g,\n /\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b/g,\n /\\/\\/([^/\\s:@]+):([^@\\s/]+)@/g\n];\n\nexport function redactText(input: string): string {\n let output = input.replace(\n /-----BEGIN ([A-Z ]*PRIVATE KEY)-----[\\s\\S]*?-----END \\1-----/g,\n (_match, keyType: string) => `-----BEGIN ${keyType}-----\\n${REDACTION}\\n-----END ${keyType}-----`\n );\n\n output = output.replace(SECRET_KEY_PATTERN, (_match, prefix: string, quote: string) => {\n return `${prefix}${quote}${REDACTION}${quote}`;\n });\n\n output = output.replace(/\\bBearer\\s+[A-Za-z0-9._~+/=-]{12,}/gi, \"Bearer [REDACTED]\");\n output = output.replace(/\\/\\/([^/\\s:@]+):([^@\\s/]+)@/g, \"//[REDACTED]@\");\n\n for (const pattern of TOKEN_PATTERNS.slice(1, -1)) {\n output = output.replace(pattern, REDACTION);\n }\n\n return output;\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport type { PackageInfo, VerificationScript } from \"../types.js\";\n\nconst PackageJsonSchema = z.object({\n name: z.string().optional(),\n packageManager: z.string().optional(),\n scripts: z.record(z.string(), z.string()).optional()\n});\n\nconst VERIFY_SCRIPT_ORDER = [\"build\", \"test\", \"typecheck\", \"lint\", \"check\", \"verify\", \"ci\"];\nconst VERIFY_SCRIPT_PREFIX = /^(build|test|typecheck|lint|check|verify|ci)(:|$)/;\n\nexport async function detectPackageInfo(root: string): Promise<PackageInfo | undefined> {\n const packageJsonPath = join(root, \"package.json\");\n\n if (!(await pathExists(packageJsonPath))) {\n return undefined;\n }\n\n const rawPackageJson = await readFile(packageJsonPath, \"utf8\");\n const packageJson = PackageJsonSchema.parse(JSON.parse(rawPackageJson));\n const packageManager = await detectPackageManager(root, packageJson.packageManager);\n const verificationScripts = detectVerificationScripts(packageJson.scripts ?? {});\n\n return {\n ...(packageJson.name ? { name: packageJson.name } : {}),\n ...(packageManager ? { packageManager } : {}),\n verificationScripts\n };\n}\n\nexport async function detectPackageManager(root: string, packageManagerField?: string) {\n if (packageManagerField) {\n return packageManagerField.split(\"@\")[0] || packageManagerField;\n }\n\n const lockfiles: Array<[string, string]> = [\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"package-lock.json\", \"npm\"],\n [\"bun.lock\", \"bun\"],\n [\"bun.lockb\", \"bun\"]\n ];\n\n for (const [lockfile, manager] of lockfiles) {\n if (await pathExists(join(root, lockfile))) {\n return manager;\n }\n }\n\n return undefined;\n}\n\nexport function detectVerificationScripts(scripts: Record<string, string>): VerificationScript[] {\n return Object.entries(scripts)\n .filter(([name]) => VERIFY_SCRIPT_PREFIX.test(name))\n .sort(([left], [right]) => {\n const leftIndex = orderIndex(left);\n const rightIndex = orderIndex(right);\n\n if (leftIndex !== rightIndex) {\n return leftIndex - rightIndex;\n }\n\n return left.localeCompare(right);\n })\n .map(([name, command]) => ({ name, command }));\n}\n\nasync function pathExists(path: string) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction orderIndex(name: string) {\n const baseName = name.split(\":\")[0] ?? name;\n const index = VERIFY_SCRIPT_ORDER.indexOf(baseName);\n return index === -1 ? VERIFY_SCRIPT_ORDER.length : index;\n}\n","import type { HandoffReport, RiskReport, RiskNote } from \"../types.js\";\n\nexport function analyzeRisk(report: HandoffReport): RiskReport {\n const files = report.repository.changedFiles;\n const notes: RiskNote[] = [];\n\n if (files.some((file) => /(^|\\/)(redact|secret|auth|token|security)/i.test(file))) {\n notes.push({\n severity: \"high\",\n title: \"Security-sensitive code changed\",\n detail: \"Review redaction, auth, token, or secret-handling changes carefully before handoff.\"\n });\n }\n\n if (files.some((file) => file === \"package.json\" || file.endsWith(\"-lock.yaml\") || file.endsWith(\"lock.json\"))) {\n notes.push({\n severity: \"medium\",\n title: \"Dependency or package metadata changed\",\n detail: \"Run install/build verification and check package publishing metadata.\"\n });\n }\n\n if (files.some((file) => file.startsWith(\".github/workflows/\"))) {\n notes.push({\n severity: \"medium\",\n title: \"CI workflow changed\",\n detail: \"Confirm GitHub Actions still passes after push.\"\n });\n }\n\n const sourceFiles = files.filter((file) => file.startsWith(\"src/\") && file.endsWith(\".ts\"));\n const testFiles = files.filter((file) => file.startsWith(\"tests/\") && file.endsWith(\".test.ts\"));\n\n if (sourceFiles.length > 0 && testFiles.length === 0) {\n notes.push({\n severity: \"medium\",\n title: \"Source changed without matching tests\",\n detail: `Review test coverage for ${sourceFiles.slice(0, 5).join(\", \")}.`\n });\n }\n\n if (notes.length === 0) {\n notes.push({\n severity: \"low\",\n title: \"No obvious local risk signals\",\n detail: \"No deterministic risk rule matched the current changed file set.\"\n });\n }\n\n return { notes };\n}\n","import { mkdtemp, readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { relative, join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { execa } from \"execa\";\nimport fg from \"fast-glob\";\n\nimport type { SecretFinding, SecretScannerReport, SecretScannerStatus, SecretScanResult } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst MAX_FINDINGS = 20;\nconst ERROR_LIMIT = 2000;\n\nexport async function detectSecretScanners(root = process.cwd()): Promise<SecretScannerReport> {\n const [gitleaks, secretlint] = await Promise.all([scannerStatus(\"gitleaks\", root), scannerStatus(\"secretlint\", root)]);\n return { scanners: [gitleaks, secretlint] };\n}\n\nexport async function runSecretScanners(root: string): Promise<SecretScannerReport> {\n const report = await detectSecretScanners(root);\n const scans = await Promise.all(report.scanners.map((scanner) => runScanner(root, scanner)));\n return { ...report, scans };\n}\n\nexport function formatScannerSummary(report: SecretScannerReport): string {\n const availability = report.scanners.map(formatScannerStatus).join(\"\\n\");\n\n if (!report.scans) {\n return availability;\n }\n\n const scans = report.scans\n .map((scan) => `${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s)` : scan.error ?? \"not run\"}`)\n .join(\"\\n\");\n\n return `${availability}\\n${scans}`;\n}\n\nexport function normalizeGitleaksFindings(rawJson: string, limit = MAX_FINDINGS): SecretFinding[] {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return [];\n }\n\n return parsed.slice(0, limit).map((finding) => {\n const ruleId = stringValue(finding.RuleID);\n const file = stringValue(finding.File);\n const line = numberValue(finding.StartLine);\n\n return {\n ...(ruleId ? { ruleId } : {}),\n message: redactText(stringValue(finding.Description) || \"Secret finding\"),\n ...(file ? { file } : {}),\n ...(line ? { line } : {})\n };\n });\n}\n\nexport function normalizeSecretlintFindings(rawJson: string, limit = MAX_FINDINGS, root?: string): SecretFinding[] {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return [];\n }\n\n const findings: SecretFinding[] = [];\n\n for (const fileResult of parsed) {\n const messages = Array.isArray(fileResult.messages) ? fileResult.messages : [];\n\n for (const message of messages) {\n if (findings.length >= limit) {\n return findings;\n }\n\n const filePath = stringValue(fileResult.filePath);\n const ruleId = stringValue(message.ruleId);\n const line = numberValue(message.line);\n findings.push({\n ...(ruleId ? { ruleId } : {}),\n message: redactText(stringValue(message.message) || \"Secret finding\"),\n ...(filePath ? { file: root ? relative(root, filePath) || filePath : filePath } : {}),\n ...(line ? { line } : {})\n });\n }\n }\n\n return findings;\n}\n\nasync function scannerStatus(name: \"gitleaks\" | \"secretlint\", root: string): Promise<SecretScannerStatus> {\n const result = await execa(name, [\"--version\"], {\n reject: false\n }).catch(() => undefined);\n const configFiles = await scannerConfigFiles(name, root);\n\n return {\n name,\n available: Boolean(result && result.exitCode === 0),\n ...(result?.stdout ? { version: result.stdout.trim() } : {}),\n configFiles,\n configHint: configHint(name, configFiles),\n installHint: installHint(name)\n };\n}\n\nasync function runScanner(root: string, scanner: SecretScannerStatus): Promise<SecretScanResult> {\n if (!scanner.available) {\n return {\n name: scanner.name,\n available: false,\n ran: false,\n findings: [],\n error: \"Scanner binary not found.\",\n truncated: false\n };\n }\n\n return scanner.name === \"gitleaks\" ? runGitleaks(root) : runSecretlint(root);\n}\n\nasync function runGitleaks(root: string): Promise<SecretScanResult> {\n const started = performance.now();\n const tempDir = await mkdtemp(join(tmpdir(), \"handoffkit-gitleaks-\"));\n const reportPath = join(tempDir, \"report.json\");\n const result = await execa(\n \"gitleaks\",\n [\"dir\", root, \"--no-banner\", \"--no-color\", \"--redact=100\", \"--report-format\", \"json\", \"--report-path\", reportPath, \"--max-target-megabytes\", \"2\"],\n { reject: false, all: true }\n );\n const rawReport = await readFile(reportPath, \"utf8\").catch(() => \"[]\");\n const findings = normalizeGitleaksFindings(rawReport);\n\n return {\n name: \"gitleaks\",\n available: true,\n ran: result.exitCode === 0 || result.exitCode === 1,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n findings,\n ...(result.exitCode && result.exitCode > 1 ? { error: redactText(trimError(result.all ?? result.stderr ?? \"\")) } : {}),\n truncated: countJsonArray(rawReport) > findings.length\n };\n}\n\nasync function runSecretlint(root: string): Promise<SecretScanResult> {\n const started = performance.now();\n const result = await execa(\"secretlint\", [\"**/*\", \"--format\", \"json\", \"--no-color\"], {\n cwd: root,\n reject: false,\n all: true\n });\n const rawOutput = result.stdout || result.all || \"[]\";\n const findings = normalizeSecretlintFindings(rawOutput, MAX_FINDINGS, root);\n\n return {\n name: \"secretlint\",\n available: true,\n ran: result.exitCode === 0 || result.exitCode === 1,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n findings,\n ...(result.exitCode && result.exitCode > 1 ? { error: redactText(trimError(result.all ?? result.stderr ?? \"\")) } : {}),\n truncated: countSecretlintMessages(rawOutput) > findings.length\n };\n}\n\nfunction safeJson(rawJson: string): unknown {\n try {\n return JSON.parse(rawJson || \"[]\");\n } catch {\n return [];\n }\n}\n\nfunction stringValue(value: unknown) {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction numberValue(value: unknown) {\n return typeof value === \"number\" ? value : undefined;\n}\n\nfunction countJsonArray(rawJson: string) {\n const parsed = safeJson(rawJson);\n return Array.isArray(parsed) ? parsed.length : 0;\n}\n\nfunction countSecretlintMessages(rawJson: string) {\n const parsed = safeJson(rawJson);\n\n if (!Array.isArray(parsed)) {\n return 0;\n }\n\n return parsed.reduce((count, fileResult) => {\n return count + (Array.isArray(fileResult.messages) ? fileResult.messages.length : 0);\n }, 0);\n}\n\nfunction trimError(output: string) {\n const trimmed = output.trim();\n return trimmed.length > ERROR_LIMIT ? `${trimmed.slice(0, ERROR_LIMIT)}\\n[truncated]` : trimmed;\n}\n\nfunction formatScannerStatus(scanner: SecretScannerStatus) {\n const config = scanner.configFiles.length > 0 ? `; config: ${scanner.configFiles.join(\", \")}` : scanner.available ? \"\" : `; ${scanner.configHint}`;\n const install = scanner.available ? \"\" : `; ${scanner.installHint}`;\n return `${scanner.name}: ${scanner.available ? \"available\" : \"not found\"}${config}${install}`;\n}\n\nasync function scannerConfigFiles(name: \"gitleaks\" | \"secretlint\", root: string) {\n const patterns =\n name === \"gitleaks\"\n ? [\"gitleaks.toml\", \".gitleaks.toml\", \".gitleaksignore\", \".config/gitleaks/*.toml\"]\n : [\".secretlintrc\", \".secretlintrc.*\", \"secretlint.config.*\"];\n\n const matches = await fg(patterns, {\n cwd: root,\n dot: true,\n onlyFiles: true,\n unique: true\n });\n\n return matches.sort();\n}\n\nfunction configHint(name: \"gitleaks\" | \"secretlint\", configFiles: string[]) {\n if (configFiles.length > 0) {\n return `config: ${configFiles.join(\", \")}`;\n }\n\n return name === \"gitleaks\"\n ? \"config: none detected; optional files include .gitleaks.toml, gitleaks.toml, or .config/gitleaks/*.toml\"\n : \"config: none detected; optional files include .secretlintrc.*, .secretlintrc, or secretlint.config.*\";\n}\n\nfunction installHint(name: \"gitleaks\" | \"secretlint\") {\n return name === \"gitleaks\"\n ? \"Install gitleaks from https://github.com/gitleaks/gitleaks, then rerun with --scan-secrets.\"\n : \"Install secretlint from https://github.com/secretlint/secretlint, then rerun with --scan-secrets.\";\n}\n","import { performance } from \"node:perf_hooks\";\n\nimport { execa } from \"execa\";\n\nimport type { PackageInfo, VerificationReport, VerificationResult, VerificationScript } from \"../types.js\";\nimport { detectPackageInfo } from \"./package-json.js\";\n\nconst VERIFY_ORDER = [\"typecheck\", \"lint\", \"test\", \"build\"];\nconst OUTPUT_LIMIT = 4000;\n\nexport function selectVerificationScripts(packageInfo: PackageInfo | undefined): VerificationScript[] {\n if (!packageInfo) {\n return [];\n }\n\n return VERIFY_ORDER.flatMap((name) => packageInfo.verificationScripts.filter((script) => script.name === name));\n}\n\nexport async function runVerification(root: string): Promise<VerificationReport> {\n const packageInfo = await detectPackageInfo(root);\n const scripts = selectVerificationScripts(packageInfo);\n const commands: VerificationResult[] = [];\n\n for (const script of scripts) {\n commands.push(await runScript(root, packageInfo?.packageManager ?? \"npm\", script));\n }\n\n return { commands };\n}\n\nasync function runScript(root: string, packageManager: string, script: VerificationScript): Promise<VerificationResult> {\n const started = performance.now();\n const command = `${packageManager} run ${script.name}`;\n const result = await execa(packageManager, [\"run\", script.name], {\n cwd: root,\n reject: false,\n all: true\n });\n\n return {\n name: script.name,\n command,\n exitCode: result.exitCode ?? 1,\n durationMs: Math.round(performance.now() - started),\n output: trimOutput(result.all ?? result.stdout ?? result.stderr ?? \"\")\n };\n}\n\nfunction trimOutput(output: string) {\n const normalized = output.trim();\n return normalized.length > OUTPUT_LIMIT ? `${normalized.slice(-OUTPUT_LIMIT)}\\n[trimmed]` : normalized;\n}\n","import type { HandoffReport, PackOptions } from \"../types.js\";\nimport { collectGitInfo, findGitRoot } from \"./git.js\";\nimport { detectInstructionFiles } from \"./instructions.js\";\nimport { detectPackageInfo } from \"./package-json.js\";\nimport { analyzeRisk } from \"./risk.js\";\nimport { detectSecretScanners, runSecretScanners } from \"./scanners.js\";\nimport { runVerification } from \"./verify.js\";\n\nexport async function collectHandoffReport(options: PackOptions): Promise<HandoffReport> {\n const root = await findGitRoot(options.cwd);\n const [repository, instructionFiles, packageInfo, secretScanning] = await Promise.all([\n collectGitInfo(root, {\n includeDiff: options.includeDiff && options.includeDiffSummary,\n includeDiffSummary: options.includeDiffSummary,\n ...(options.since ? { since: options.since } : {})\n }),\n detectInstructionFiles(root),\n detectPackageInfo(root),\n options.scanSecrets ? runSecretScanners(root) : detectSecretScanners(root)\n ]);\n\n const report: HandoffReport = {\n goal: options.goal,\n target: options.target,\n repository,\n instructionFiles,\n ...(packageInfo ? { packageInfo } : {}),\n ...(options.resumeSource ? { resumeSource: options.resumeSource } : {}),\n ...(options.includeVerification ? { verification: await runVerification(root) } : {}),\n secretScanning,\n budget: {\n requestedTokens: options.budget,\n estimatedTokens: 0,\n wasTrimmed: false\n }\n };\n\n report.risk = analyzeRisk(report);\n return report;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport { applyMarkdownBudget, estimateTokens } from \"../core/budget.js\";\nimport { redactText } from \"../core/redact.js\";\nimport { renderJsonReport } from \"../report/json.js\";\nimport { renderMarkdownReport } from \"../report/markdown.js\";\nimport type { HandoffReport, OutputFormat } from \"../types.js\";\n\nexport async function writeRenderedReport(report: HandoffReport, format: OutputFormat, budget: number, output?: string) {\n const rendered = redactText(renderOutput(report, format, budget));\n\n if (output) {\n const outputPath = resolve(process.cwd(), output);\n await mkdir(dirname(outputPath), { recursive: true });\n await writeFile(outputPath, rendered, \"utf8\");\n process.stderr.write(`Wrote handoff packet to ${outputPath}\\n`);\n return;\n }\n\n process.stdout.write(rendered);\n}\n\nfunction renderOutput(report: HandoffReport, format: OutputFormat, budget: number) {\n if (format === \"json\") {\n const rendered = renderJsonReport(report);\n report.budget.estimatedTokens = estimateTokens(rendered);\n return renderJsonReport(report);\n }\n\n const firstRender = renderMarkdownReport(report);\n const budgeted = applyMarkdownBudget(firstRender, budget);\n report.budget.estimatedTokens = budgeted.estimatedTokens;\n report.budget.wasTrimmed = budgeted.wasTrimmed;\n\n if (budgeted.wasTrimmed) {\n return budgeted.text;\n }\n\n return renderMarkdownReport(report);\n}\n","export function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport function applyMarkdownBudget(text: string, budget: number) {\n const estimatedTokens = estimateTokens(text);\n\n if (estimatedTokens <= budget) {\n return { text, estimatedTokens, wasTrimmed: false };\n }\n\n const notice = `\\n\\n> Output trimmed to fit --budget ${budget}. Re-run with a larger budget or --output for the full packet.\\n`;\n const charLimit = Math.max(0, budget * 4 - notice.length);\n const trimmed = `${text.slice(0, charLimit).trimEnd()}${notice}`;\n\n return {\n text: trimmed,\n estimatedTokens: estimateTokens(trimmed),\n wasTrimmed: true\n };\n}\n","import type { HandoffReport } from \"../types.js\";\n\nexport function renderJsonReport(report: HandoffReport): string {\n return `${JSON.stringify(report, null, 2)}\\n`;\n}\n","import type { AgentTarget } from \"../types.js\";\n\nexport type ReportSectionKey =\n | \"goal\"\n | \"repository\"\n | \"gitStatus\"\n | \"recentCommits\"\n | \"changedFiles\"\n | \"branchDelta\"\n | \"diffSummary\"\n | \"includedBranchDelta\"\n | \"includedDiff\"\n | \"instructionFiles\"\n | \"package\"\n | \"resume\"\n | \"verification\"\n | \"risk\"\n | \"secretScanning\";\n\nexport interface ReportProfile {\n title: string;\n sectionOrder: ReportSectionKey[];\n nextAgentNotes: string[];\n}\n\nconst genericOrder: ReportSectionKey[] = [\n \"goal\",\n \"repository\",\n \"gitStatus\",\n \"recentCommits\",\n \"changedFiles\",\n \"branchDelta\",\n \"diffSummary\",\n \"includedBranchDelta\",\n \"includedDiff\",\n \"instructionFiles\",\n \"package\",\n \"resume\",\n \"verification\",\n \"risk\",\n \"secretScanning\"\n];\n\nconst profiles: Record<AgentTarget, ReportProfile> = {\n generic: {\n title: \"Handoff Packet\",\n sectionOrder: genericOrder,\n nextAgentNotes: [\n \"Use this packet as the starting context for the next coding session.\",\n \"Verify commands locally before claiming completion.\"\n ]\n },\n codex: {\n title: \"Codex Handoff Packet\",\n sectionOrder: [\n \"goal\",\n \"repository\",\n \"gitStatus\",\n \"changedFiles\",\n \"verification\",\n \"risk\",\n \"branchDelta\",\n \"diffSummary\",\n \"includedBranchDelta\",\n \"includedDiff\",\n \"instructionFiles\",\n \"package\",\n \"resume\",\n \"secretScanning\",\n \"recentCommits\"\n ],\n nextAgentNotes: [\n \"Start by reading the goal, repository status, changed files, and verification state.\",\n \"Use local tools to inspect files before editing; do not assume hidden context.\",\n \"Keep edits scoped and rerun the relevant verification before reporting completion.\"\n ]\n },\n claude: {\n title: \"Claude Code Handoff Packet\",\n sectionOrder: [\n \"goal\",\n \"resume\",\n \"repository\",\n \"verification\",\n \"risk\",\n \"changedFiles\",\n \"gitStatus\",\n \"branchDelta\",\n \"diffSummary\",\n \"includedBranchDelta\",\n \"includedDiff\",\n \"instructionFiles\",\n \"package\",\n \"secretScanning\",\n \"recentCommits\"\n ],\n nextAgentNotes: [\n \"Treat this as concise project memory plus current branch state.\",\n \"Use the resume state to separate completed work from remaining work.\",\n \"Ask for clarification only when the packet leaves a blocking ambiguity.\"\n ]\n },\n cursor: {\n title: \"Cursor Handoff Packet\",\n sectionOrder: [\n \"goal\",\n \"repository\",\n \"changedFiles\",\n \"gitStatus\",\n \"includedDiff\",\n \"diffSummary\",\n \"branchDelta\",\n \"includedBranchDelta\",\n \"instructionFiles\",\n \"package\",\n \"verification\",\n \"risk\",\n \"resume\",\n \"secretScanning\",\n \"recentCommits\"\n ],\n nextAgentNotes: [\n \"Open the changed files first to build editor context.\",\n \"Use instruction files and package scripts to keep edits aligned with the workspace.\",\n \"Prefer small edits and rerun the detected verification scripts.\"\n ]\n }\n};\n\nexport function profileForTarget(target: AgentTarget): ReportProfile {\n return profiles[target] ?? profiles.generic;\n}\n","import type { HandoffReport, PackageInfo, ResumeItem, ResumeState } from \"../types.js\";\nimport { profileForTarget, type ReportSectionKey } from \"./profiles.js\";\n\nexport function renderMarkdownReport(report: HandoffReport): string {\n const profile = profileForTarget(report.target);\n const lines: string[] = [\n `# ${profile.title}`,\n \"\",\n ...profile.sectionOrder.flatMap((section) => renderSection(section, report)),\n \"## Next Agent Notes\",\n ...profile.nextAgentNotes.map((note) => `- ${note}`),\n \"- This packet was generated from local git and filesystem state.\",\n \"- Likely secrets were redacted from generated output.\",\n \"- No LLM APIs were called.\"\n ];\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction renderSection(section: ReportSectionKey, report: HandoffReport) {\n switch (section) {\n case \"goal\":\n return [\"## Goal\", report.goal, \"\"];\n case \"repository\":\n return [\n \"## Repository\",\n `- Repository: \\`${report.repository.name}\\``,\n `- Branch: \\`${report.repository.branch}\\``,\n `- Changed files: ${report.repository.changedFiles.length}`,\n \"\"\n ];\n case \"gitStatus\":\n return [\"## Git Status\", codeBlock(report.repository.status || \"Clean working tree.\"), \"\"];\n case \"recentCommits\":\n return [\"## Recent Commits\", listOrNone(report.repository.recentCommits.map((commit) => `- ${commit}`)), \"\"];\n case \"changedFiles\":\n return [\"## Changed Files\", listOrNone(report.repository.changedFiles.map((file) => `- \\`${file}\\``)), \"\"];\n case \"branchDelta\":\n return renderBaseDiffSummary(report);\n case \"diffSummary\":\n return [\n \"## Diff Summary\",\n \"### Staged\",\n codeBlock(report.repository.stagedDiffSummary || \"No staged diff.\"),\n \"\",\n \"### Unstaged\",\n codeBlock(report.repository.unstagedDiffSummary || \"No unstaged diff.\"),\n \"\"\n ];\n case \"includedBranchDelta\":\n return renderIncludedBranchDelta(report);\n case \"includedDiff\":\n return renderIncludedDiff(report);\n case \"instructionFiles\":\n return [\"## Instruction Files\", renderInstructionFiles(report.instructionFiles), \"\"];\n case \"package\":\n return [\"## Package\", renderPackage(report.packageInfo), \"\"];\n case \"resume\":\n return renderResumeSource(report);\n case \"verification\":\n return renderVerification(report);\n case \"risk\":\n return renderRisk(report);\n case \"secretScanning\":\n return renderSecretScanning(report);\n }\n}\n\nfunction renderBaseDiffSummary(report: HandoffReport) {\n if (!report.repository.baseRef) {\n return [];\n }\n\n return [\n `## Branch Delta Since \\`${report.repository.baseRef}\\``,\n codeBlock(report.repository.baseDiffSummary || \"No committed branch delta detected.\"),\n \"\"\n ];\n}\n\nfunction renderIncludedBranchDelta(report: HandoffReport) {\n if (!report.repository.includeDiff || !report.repository.baseDiff) {\n return [];\n }\n\n return [\n `## Included Branch Delta Since \\`${report.repository.baseRef}\\``,\n codeBlock(report.repository.baseDiff),\n \"\"\n ];\n}\n\nfunction renderIncludedDiff(report: HandoffReport) {\n if (!report.repository.includeDiff || !report.repository.diff) {\n return [];\n }\n\n return [\n \"## Included Diff\",\n \"### Staged Patch\",\n codeBlock(report.repository.diff.staged || \"No staged patch.\"),\n \"\",\n \"### Unstaged Patch\",\n codeBlock(report.repository.diff.unstaged || \"No unstaged patch.\"),\n \"\"\n ];\n}\n\nfunction renderPackage(packageInfo: PackageInfo | undefined) {\n if (!packageInfo) {\n return \"No package.json detected.\";\n }\n\n const lines = [\n packageInfo.name ? `- Package: \\`${packageInfo.name}\\`` : undefined,\n packageInfo.packageManager ? `- Package manager: \\`${packageInfo.packageManager}\\`` : undefined\n ].filter((line): line is string => Boolean(line));\n\n if (packageInfo.verificationScripts.length > 0) {\n const prefix = packageInfo.packageManager ?? \"npm\";\n lines.push(\"- Verification scripts:\");\n lines.push(...packageInfo.verificationScripts.map((script) => ` - \\`${prefix} ${script.name}\\``));\n } else {\n lines.push(\"- Verification scripts: none detected.\");\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction renderInstructionFiles(instructionFiles: HandoffReport[\"instructionFiles\"]) {\n if (instructionFiles.length === 0) {\n return \"None detected.\";\n }\n\n return instructionFiles\n .map((file) => [`- \\`${file.path}\\` (${file.kind})`, codeBlock(file.preview || \"No preview available.\")].join(\"\\n\"))\n .join(\"\\n\\n\");\n}\n\nfunction renderResumeSource(report: HandoffReport) {\n if (!report.resumeSource) {\n return [];\n }\n\n return [\n \"## Resume Source\",\n `- Source: \\`${report.resumeSource.path}\\``,\n codeBlock(report.resumeSource.preview),\n \"\",\n ...renderResumeState(report.resumeSource.state)\n ];\n}\n\nfunction renderResumeState(state: ResumeState | undefined) {\n if (!state) {\n return [];\n }\n\n return [\n \"## Resume State\",\n renderResumeItems(\"Completed\", state.completed),\n renderResumeItems(\"Remaining\", state.remaining),\n renderResumeItems(\"Failed Commands\", state.failedCommands),\n renderResumeItems(\"Open Questions\", state.openQuestions),\n renderResumeItems(\"Verification\", state.verification),\n state.nextSafestAction ? `- Next safest action: ${state.nextSafestAction}` : \"- Next safest action: none detected.\",\n \"\"\n ];\n}\n\nfunction renderResumeItems(title: string, items: ResumeItem[]) {\n return [`### ${title}`, listOrNone(items.map((item) => `- ${item.text}`))].join(\"\\n\");\n}\n\nfunction renderVerification(report: HandoffReport) {\n if (!report.verification) {\n return [];\n }\n\n return [\n \"## Verification\",\n report.verification.commands.length > 0\n ? report.verification.commands\n .map((command) =>\n [`- \\`${command.command}\\` exited ${command.exitCode} in ${command.durationMs}ms`, codeBlock(command.output || \"No output.\")]\n .join(\"\\n\")\n )\n .join(\"\\n\\n\")\n : \"No safe verification scripts detected.\",\n \"\"\n ];\n}\n\nfunction renderRisk(report: HandoffReport) {\n if (!report.risk) {\n return [];\n }\n\n return [\n \"## Risk Notes\",\n report.risk.notes.map((note) => `- **${note.severity}**: ${note.title} - ${note.detail}`).join(\"\\n\"),\n \"\"\n ];\n}\n\nfunction renderSecretScanning(report: HandoffReport) {\n if (!report.secretScanning) {\n return [];\n }\n\n return [\n report.secretScanning.scans ? \"## Secret Scan Results\" : \"## Secret Scanner Availability\",\n renderSecretScannerReport(report.secretScanning),\n \"\"\n ];\n}\n\nfunction renderSecretScannerReport(secretScanning: NonNullable<HandoffReport[\"secretScanning\"]>) {\n if (!secretScanning.scans) {\n return secretScanning.scanners.map((scanner) => `- ${scannerStatusLine(scanner)}`).join(\"\\n\");\n }\n\n return secretScanning.scans\n .map((scan) => {\n const status = secretScanning.scanners.find((scanner) => scanner.name === scan.name);\n const lines = [\n `- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? \"not run\"}`\n ];\n\n if (status) {\n lines.push(...scannerGuidanceLines(status));\n }\n\n for (const finding of scan.findings) {\n lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : \"\"}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : \"\"})` : \"\"}`);\n }\n\n if (scan.truncated) {\n lines.push(\" - Additional findings were truncated.\");\n }\n\n return lines.join(\"\\n\");\n })\n .join(\"\\n\");\n}\n\nfunction scannerStatusLine(scanner: NonNullable<HandoffReport[\"secretScanning\"]>[\"scanners\"][number]) {\n const config = scanner.configFiles.length > 0 ? `; config: ${scanner.configFiles.join(\", \")}` : scanner.available ? \"\" : `; ${scanner.configHint}`;\n const install = scanner.available ? \"\" : `; ${scanner.installHint}`;\n return `${scanner.name}: ${scanner.available ? \"available\" : \"not found\"}${config}${install}`;\n}\n\nfunction scannerGuidanceLines(scanner: NonNullable<HandoffReport[\"secretScanning\"]>[\"scanners\"][number]) {\n const lines: string[] = [];\n\n if (scanner.configFiles.length > 0) {\n lines.push(` - config: ${scanner.configFiles.join(\", \")}`);\n } else if (!scanner.available) {\n lines.push(` - ${scanner.configHint}`);\n }\n\n if (!scanner.available) {\n lines.push(` - ${scanner.installHint}`);\n }\n\n return lines;\n}\n\nfunction codeBlock(text: string) {\n return [\"```text\", text, \"```\"].join(\"\\n\");\n}\n\nfunction listOrNone(items: string[]) {\n return items.length > 0 ? items.join(\"\\n\") : \"None detected.\";\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\nimport { createResumeSource } from \"../../core/resume.js\";\nimport { writeRenderedReport } from \"../output.js\";\n\nconst ResumeOptionsSchema = z.object({\n goal: z.string().trim().min(1).default(\"Resume interrupted AI coding session\"),\n output: z.string().optional(),\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\"),\n for: z.enum([\"generic\", \"codex\", \"claude\", \"cursor\"]).default(\"generic\"),\n budget: z.number().int().positive().default(4000)\n});\n\nexport function createResumeCommand() {\n return new Command(\"resume\")\n .description(\"Create a fresh handoff packet using a previous handoff as resume context.\")\n .summary(\"Merge a previous handoff or transcript with fresh repo state.\")\n .argument(\"<path>\", \"previous handoff or transcript file\")\n .option(\"--goal <text>\", \"new handoff goal\", \"Resume interrupted AI coding session\")\n .option(\"--output <path>\", \"write output to a file instead of stdout\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .option(\"--for <agent>\", \"target output: generic, codex, claude, or cursor\", \"generic\")\n .option(\"--budget <tokens>\", \"rough output token budget\", parseBudget, 4000)\n .action(async (path: string, rawOptions) => {\n const options = ResumeOptionsSchema.parse(rawOptions);\n const source = createResumeSource(path, await readFile(path, \"utf8\"));\n const report = await collectHandoffReport({\n goal: options.goal,\n cwd: process.cwd(),\n ...(options.output ? { output: options.output } : {}),\n format: options.format,\n target: options.for,\n budget: options.budget,\n includeDiff: false,\n includeDiffSummary: true,\n includeVerification: false,\n scanSecrets: false,\n resumeSource: source\n });\n\n await writeRenderedReport(report, options.format, options.budget, options.output);\n });\n}\n\nfunction parseBudget(value: string) {\n const parsed = Number.parseInt(value, 10);\n\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(\"--budget must be a positive integer.\");\n }\n\n return parsed;\n}\n","import type { ResumeSource, ResumeState } from \"../types.js\";\nimport { redactText } from \"./redact.js\";\n\nconst RESUME_PREVIEW_LIMIT = 3000;\nconst SECTION_ALIASES = {\n completed: [/^completed$/i, /^done$/i, /^done this session$/i, /^what changed$/i, /^implemented$/i],\n remaining: [/^remaining$/i, /^next steps$/i, /^todo$/i, /^to do$/i],\n failedCommands: [/^failed commands$/i, /^failures$/i, /^errors$/i],\n openQuestions: [/^open questions$/i, /^open questions \\/ risks$/i, /^open questions and risks$/i, /^questions$/i, /^blockers$/i],\n verification: [/^verification$/i, /^tests$/i, /^validation$/i]\n} as const;\n\ntype ResumeSection = keyof typeof SECTION_ALIASES;\n\nexport function createResumeSource(path: string, content: string): ResumeSource {\n const normalized = content.replace(/\\r\\n/g, \"\\n\").trim();\n const preview =\n normalized.length > RESUME_PREVIEW_LIMIT ? `${normalized.slice(0, RESUME_PREVIEW_LIMIT).trimEnd()}\\n[truncated]` : normalized;\n const state = parseResumeState(normalized);\n\n return {\n path,\n preview: redactText(preview),\n ...(hasResumeState(state) ? { state } : {})\n };\n}\n\nexport function parseResumeState(content: string): ResumeState {\n const state: ResumeState = {\n completed: [],\n remaining: [],\n failedCommands: [],\n openQuestions: [],\n verification: []\n };\n let section: ResumeSection | undefined;\n let heading: string | undefined;\n\n for (const rawLine of content.replace(/\\r\\n/g, \"\\n\").split(\"\\n\")) {\n const line = rawLine.trim();\n const headingMatch = line.match(/^#{1,4}\\s+(.+)$/);\n\n if (headingMatch) {\n const headingText = headingMatch[1];\n if (!headingText) {\n continue;\n }\n\n heading = headingText.trim();\n section = sectionForHeading(heading);\n continue;\n }\n\n if (!section) {\n continue;\n }\n\n const item = normalizeListItem(line);\n if (item) {\n state[section].push({ text: redactText(item), ...(heading ? { sourceHeading: redactText(heading) } : {}) });\n }\n }\n\n const next = state.remaining[0] ?? state.openQuestions[0] ?? state.failedCommands[0];\n if (next) {\n state.nextSafestAction = next.text;\n }\n\n return state;\n}\n\nfunction sectionForHeading(heading: string): ResumeSection | undefined {\n const normalized = normalizeHeading(heading);\n\n for (const [section, patterns] of Object.entries(SECTION_ALIASES)) {\n if (patterns.some((pattern) => pattern.test(normalized))) {\n return section as ResumeSection;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeListItem(line: string) {\n const match = line.match(/^[-*]\\s+(.+)$/) ?? line.match(/^\\d+\\.\\s+(.+)$/);\n return match?.[1]?.trim();\n}\n\nfunction normalizeHeading(heading: string) {\n return heading.trim().replace(/:$/, \"\").replace(/\\s*\\/\\s*/g, \" / \").replace(/\\s+/g, \" \");\n}\n\nfunction hasResumeState(state: ResumeState) {\n return (\n state.completed.length > 0 ||\n state.remaining.length > 0 ||\n state.failedCommands.length > 0 ||\n state.openQuestions.length > 0 ||\n state.verification.length > 0\n );\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { collectHandoffReport } from \"../../core/collect.js\";\n\nconst RiskOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createRiskCommand() {\n return new Command(\"risk\")\n .description(\"Show deterministic risk notes for the current handoff.\")\n .summary(\"Show deterministic risk notes from changed files.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = RiskOptionsSchema.parse(rawOptions);\n const report = await collectHandoffReport({\n goal: \"Review local risk\",\n cwd: process.cwd(),\n format: options.format,\n target: \"generic\",\n budget: 4000,\n includeDiff: false,\n includeDiffSummary: false,\n includeVerification: false,\n scanSecrets: false\n });\n\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(report.risk, null, 2)}\\n`);\n return;\n }\n\n process.stdout.write(`# Risk Notes\\n\\n${report.risk?.notes.map((note) => `- **${note.severity}**: ${note.title} - ${note.detail}`).join(\"\\n\")}\\n`);\n });\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { findGitRoot } from \"../../core/git.js\";\nimport { redactText } from \"../../core/redact.js\";\nimport { runSecretScanners } from \"../../core/scanners.js\";\nimport type { SecretScannerReport, SecretScannerStatus } from \"../../types.js\";\n\nconst ScanSecretsOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createScanSecretsCommand() {\n return new Command(\"scan-secrets\")\n .description(\"Run optional local secret scanners and print bounded redacted results.\")\n .summary(\"Run optional local secret scanners.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = ScanSecretsOptionsSchema.parse(rawOptions);\n const root = await findGitRoot(process.cwd());\n const report = await runSecretScanners(root);\n\n if (options.format === \"json\") {\n process.stdout.write(redactText(`${JSON.stringify(report, null, 2)}\\n`));\n return;\n }\n\n process.stdout.write(redactText(renderScanMarkdown(report)));\n });\n}\n\nexport function renderScanMarkdown(report: SecretScannerReport) {\n const lines = [\"# Secret Scan Results\", \"\"];\n\n for (const scan of report.scans ?? []) {\n const status = report.scanners.find((scanner) => scanner.name === scan.name);\n lines.push(`- ${scan.name}: ${scan.ran ? `${scan.findings.length} finding(s), exit ${scan.exitCode}` : scan.error ?? \"not run\"}`);\n\n if (status) {\n lines.push(...scannerGuidanceLines(status));\n }\n\n for (const finding of scan.findings) {\n lines.push(` - ${finding.ruleId ? `${finding.ruleId}: ` : \"\"}${finding.message}${finding.file ? ` (${finding.file}${finding.line ? `:${finding.line}` : \"\"})` : \"\"}`);\n }\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction scannerGuidanceLines(scanner: SecretScannerStatus) {\n const lines: string[] = [];\n\n if (scanner.configFiles.length > 0) {\n lines.push(` - config: ${scanner.configFiles.join(\", \")}`);\n } else if (!scanner.available) {\n lines.push(` - ${scanner.configHint}`);\n }\n\n if (!scanner.available) {\n lines.push(` - ${scanner.installHint}`);\n }\n\n return lines;\n}\n","import { Command } from \"commander\";\nimport { z } from \"zod\";\n\nimport { findGitRoot } from \"../../core/git.js\";\nimport { redactText } from \"../../core/redact.js\";\nimport { runVerification } from \"../../core/verify.js\";\nimport type { VerificationResult } from \"../../types.js\";\n\nconst VerifyOptionsSchema = z.object({\n format: z.enum([\"markdown\", \"json\"]).default(\"markdown\")\n});\n\nexport function createVerifyCommand() {\n return new Command(\"verify\")\n .description(\"Run safe local verification scripts.\")\n .summary(\"Run safe detected verification scripts.\")\n .option(\"--format <format>\", \"output format: markdown or json\", \"markdown\")\n .action(async (rawOptions) => {\n const options = VerifyOptionsSchema.parse(rawOptions);\n const root = await findGitRoot(process.cwd());\n const verification = await runVerification(root);\n\n if (options.format === \"json\") {\n process.stdout.write(redactText(`${JSON.stringify(verification, null, 2)}\\n`));\n return;\n }\n\n process.stdout.write(redactText(renderVerificationMarkdown(verification.commands)));\n });\n}\n\nfunction renderVerificationMarkdown(commands: VerificationResult[]) {\n const lines = [\"# Verification\", \"\"];\n\n if (commands.length === 0) {\n lines.push(\"No safe verification scripts detected.\");\n } else {\n for (const command of commands) {\n lines.push(`- \\`${command.command}\\` exited ${command.exitCode} in ${command.durationMs}ms`);\n }\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n"],"mappings":"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","names":["Command","z","readFile","readFile","readFile","readFile","join","execa","fg","execa","join","readFile","fg","performance","execa","performance","execa","z","readFile","Command","z","z","Command","parseBudget","readFile","Command","z","z","Command","Command","z","z","Command","scannerGuidanceLines","Command","z","z","Command","Command"]}
package/docs/RELEASE.md CHANGED
@@ -9,7 +9,7 @@ HandoffKit releases are intentionally manual. A release should prove that the so
9
9
  - Node.js 22 or newer
10
10
  - pnpm via Corepack
11
11
 
12
- For GitHub Actions publishing, add an `NPM_TOKEN` repository secret with publish access. Without that secret, the `Release` workflow can run verification but cannot publish.
12
+ For GitHub Actions publishing, add an `NPM_TOKEN` repository secret with publish access. The token must be usable from CI without an interactive one-time password; for npm accounts with publish 2FA, use a granular token with package write access and 2FA bypass enabled, or configure npm trusted publishing. Without a valid publish token, the `Release` workflow can run verification but cannot publish.
13
13
 
14
14
  ## Before Tagging
15
15
 
@@ -22,40 +22,29 @@ pnpm pack:dry-run
22
22
  npm --cache ./.npm-cache publish --dry-run --access public
23
23
  ```
24
24
 
25
- Create a real tarball and install it into a clean temporary repository:
25
+ Run the packaged install smoke:
26
26
 
27
27
  ```sh
28
- mkdir -p /private/tmp/handoffkit-release-smoke
29
- npm --cache ./.npm-cache pack --pack-destination /private/tmp/handoffkit-release-smoke
30
-
31
- SMOKE_DIR="$(mktemp -d /private/tmp/handoffkit-install-smoke.XXXXXX)"
32
- cd "$SMOKE_DIR"
33
- git init --initial-branch=main
34
- printf '# Smoke\n' > README.md
35
- npm init -y
36
- npm --cache /private/tmp/handoffkit-npm-cache install /private/tmp/handoffkit-release-smoke/kingkyylian-handoffkit-0.1.0.tgz
37
- ./node_modules/.bin/handoffkit pack --goal "Smoke release" --format json --no-diff
38
- ./node_modules/.bin/handoffkit risk --format json
39
- ./node_modules/.bin/handoffkit scan-secrets --format json
40
- ./node_modules/.bin/handoffkit resume README.md --goal "Resume smoke" --format json
28
+ pnpm smoke:release
41
29
  ```
42
30
 
43
- Confirm that `node_modules`, `dist`, and `coverage` do not appear in `changedFiles` just because the package was installed or built.
31
+ The script packs the current package, installs it into a clean temporary git repository, runs `pack`, `risk`, `scan-secrets`, and `resume`, and fails if generated directories such as `node_modules`, `dist`, or `coverage` appear in `changedFiles`.
44
32
 
45
33
  ## Tag and Release
46
34
 
47
35
  After CI passes on `main`:
48
36
 
49
37
  ```sh
50
- git tag v0.1.0
51
- git push origin v0.1.0
52
- gh release create v0.1.0 --repo kingkyylian/handoffkit --title "HandoffKit v0.1.0" --notes-file /private/tmp/handoffkit-v0.1.0-release-notes.md
38
+ version=0.2.0
39
+ git tag "v${version}"
40
+ git push origin "v${version}"
41
+ gh release create "v${version}" --repo kingkyylian/handoffkit --title "HandoffKit v${version}" --notes-file "/private/tmp/handoffkit-v${version}-release-notes.md"
53
42
  ```
54
43
 
55
44
  Preferred publish path:
56
45
 
57
46
  ```sh
58
- gh workflow run Release --repo kingkyylian/handoffkit --ref v0.1.0
47
+ gh workflow run Release --repo kingkyylian/handoffkit --ref "v${version}"
59
48
  ```
60
49
 
61
50
  Fallback local publish path when `NPM_TOKEN` is not configured:
@@ -67,8 +56,8 @@ npm --cache ./.npm-cache publish --provenance --access public
67
56
  ## After Publishing
68
57
 
69
58
  ```sh
70
- npm view @kingkyylian/handoffkit version
71
- pnpm dlx @kingkyylian/handoffkit pack --goal "Registry smoke" --format json --no-diff
59
+ npm view "@kingkyylian/handoffkit@${version}" version --registry=https://registry.npmjs.org/
60
+ pnpm dlx "@kingkyylian/handoffkit@${version}" pack --goal "Registry smoke" --format json --no-diff
72
61
  ```
73
62
 
74
63
  The published version should match the tag, and the registry smoke command should exit successfully inside a git repository.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingkyylian/handoffkit",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Clean handoff packets for interrupted AI coding sessions.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -58,6 +58,7 @@
58
58
  "lint": "eslint .",
59
59
  "pack:dry-run": "npm --cache ./.npm-cache pack --dry-run",
60
60
  "prepack": "pnpm build",
61
+ "smoke:release": "node scripts/release-smoke.mjs",
61
62
  "test": "vitest run",
62
63
  "typecheck": "tsc --noEmit"
63
64
  },