pm-github 2026.10.28 → 2026.10.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +43 -4
  3. package/dist/closeout.d.ts.map +1 -1
  4. package/dist/closeout.js +71 -30
  5. package/dist/closeout.js.map +1 -1
  6. package/dist/discussion-schema.d.ts +110 -0
  7. package/dist/discussion-schema.d.ts.map +1 -0
  8. package/dist/discussion-schema.js +41 -0
  9. package/dist/discussion-schema.js.map +1 -0
  10. package/dist/discussions.d.ts +26 -0
  11. package/dist/discussions.d.ts.map +1 -0
  12. package/dist/discussions.js +215 -0
  13. package/dist/discussions.js.map +1 -0
  14. package/dist/gate.d.ts +2 -0
  15. package/dist/gate.d.ts.map +1 -1
  16. package/dist/gate.js +20 -9
  17. package/dist/gate.js.map +1 -1
  18. package/dist/identity.d.ts.map +1 -1
  19. package/dist/identity.js +2 -1
  20. package/dist/identity.js.map +1 -1
  21. package/dist/import-fidelity.d.ts +8 -3
  22. package/dist/import-fidelity.d.ts.map +1 -1
  23. package/dist/import-fidelity.js +39 -10
  24. package/dist/import-fidelity.js.map +1 -1
  25. package/dist/import-tags.d.ts +1 -1
  26. package/dist/import-tags.d.ts.map +1 -1
  27. package/dist/import-tags.js +8 -6
  28. package/dist/import-tags.js.map +1 -1
  29. package/dist/index.d.ts +48 -40
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +164 -69
  32. package/dist/index.js.map +1 -1
  33. package/dist/issue-forms.d.ts +1 -1
  34. package/dist/issue-forms.d.ts.map +1 -1
  35. package/dist/issue-forms.js +6 -4
  36. package/dist/issue-forms.js.map +1 -1
  37. package/dist/projects.d.ts +6 -4
  38. package/dist/projects.d.ts.map +1 -1
  39. package/dist/projects.js +21 -20
  40. package/dist/projects.js.map +1 -1
  41. package/dist/refresh.d.ts +2 -1
  42. package/dist/refresh.d.ts.map +1 -1
  43. package/dist/refresh.js +17 -8
  44. package/dist/refresh.js.map +1 -1
  45. package/dist/webhooks.d.ts.map +1 -1
  46. package/dist/webhooks.js +5 -2
  47. package/dist/webhooks.js.map +1 -1
  48. package/dist/workflow-diagnostic.d.ts +9 -0
  49. package/dist/workflow-diagnostic.d.ts.map +1 -0
  50. package/dist/workflow-diagnostic.js +62 -0
  51. package/dist/workflow-diagnostic.js.map +1 -0
  52. package/dist/workspace.d.ts +18 -0
  53. package/dist/workspace.d.ts.map +1 -0
  54. package/dist/workspace.js +39 -0
  55. package/dist/workspace.js.map +1 -0
  56. package/docs/discussion-capture-example.json +14 -0
  57. package/docs/discussion-capture.md +44 -0
  58. package/manifest.json +1 -1
  59. package/package.json +8 -4
@@ -0,0 +1,110 @@
1
+ /** Shared bounded contracts for explicit selections, lossless evidence and receipts. */
2
+ import { z } from "zod";
3
+ /** One strict request schema also validates JSON/TOON-decoded round trips. Offsets count UTF-16 code units. */
4
+ export declare const discussionRequestSchema: z.ZodObject<{
5
+ repo: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
6
+ issue: z.ZodNumber;
7
+ item: z.ZodString;
8
+ selections: z.ZodArray<z.ZodObject<{
9
+ comment: z.ZodNumber;
10
+ start: z.ZodNumber;
11
+ end: z.ZodNumber;
12
+ quote: z.ZodString;
13
+ marked: z.ZodLiteral<true>;
14
+ }, z.core.$strict>>;
15
+ }, z.core.$strict>;
16
+ /** SDK callers supply exactly the same selection document as CLI users. */
17
+ export type DiscussionCaptureInput = z.input<typeof discussionRequestSchema>;
18
+ /** Project the public comment wire envelope through the same author and numeric domains as evidence. */
19
+ export declare const discussionSourceSchema: z.ZodObject<{
20
+ id: z.ZodNumber;
21
+ body: z.ZodString;
22
+ issue_url: z.ZodString;
23
+ html_url: z.ZodString;
24
+ updated_at: z.ZodString;
25
+ user: z.ZodObject<{
26
+ id: z.ZodNumber;
27
+ login: z.ZodString;
28
+ }, z.core.$strip>;
29
+ }, z.core.$strip>;
30
+ /** Exact quoted bytes are JSON data, never a template, command or instruction. */
31
+ export declare const discussionEvidenceSchema: z.ZodObject<{
32
+ type: z.ZodLiteral<"github.discussion-decision.v1">;
33
+ repo: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
34
+ issue: z.ZodNumber;
35
+ comment: z.ZodNumber;
36
+ url: z.ZodString;
37
+ revision: z.ZodString;
38
+ author: z.ZodObject<{
39
+ id: z.ZodNumber;
40
+ login: z.ZodString;
41
+ }, z.core.$strict>;
42
+ updatedAt: z.ZodString;
43
+ span: z.ZodObject<{
44
+ start: z.ZodNumber;
45
+ end: z.ZodNumber;
46
+ quote: z.ZodString;
47
+ }, z.core.$strict>;
48
+ }, z.core.$strict>;
49
+ /** Evidence can be handed to a citation workflow without inventing another citation store. */
50
+ export type DiscussionDecisionEvidence = z.infer<typeof discussionEvidenceSchema>;
51
+ /** Every producer uses this validator before returning a successful finite, bounded receipt. */
52
+ export declare const discussionReportSchema: z.ZodObject<{
53
+ ok: z.ZodLiteral<true>;
54
+ mode: z.ZodEnum<{
55
+ apply: "apply";
56
+ plan: "plan";
57
+ }>;
58
+ approval: z.ZodString;
59
+ item: z.ZodString;
60
+ status: z.ZodString;
61
+ selected: z.ZodNumber;
62
+ created: z.ZodNumber;
63
+ unchanged: z.ZodNumber;
64
+ skipped: z.ZodNumber;
65
+ refused: z.ZodNumber;
66
+ rows: z.ZodArray<z.ZodObject<{
67
+ id: z.ZodString;
68
+ state: z.ZodEnum<{
69
+ create: "create";
70
+ created: "created";
71
+ refused: "refused";
72
+ skipped: "skipped";
73
+ unchanged: "unchanged";
74
+ }>;
75
+ reason: z.ZodEnum<{
76
+ already_captured: "already_captured";
77
+ captured: "captured";
78
+ duplicate_selection: "duplicate_selection";
79
+ foreign_or_edited: "foreign_or_edited";
80
+ invalid_selection: "invalid_selection";
81
+ native_refused: "native_refused";
82
+ selected_marked_span: "selected_marked_span";
83
+ source_changed: "source_changed";
84
+ source_unavailable: "source_unavailable";
85
+ write_failed: "write_failed";
86
+ }>;
87
+ remedy: z.ZodString;
88
+ evidence: z.ZodNullable<z.ZodObject<{
89
+ type: z.ZodLiteral<"github.discussion-decision.v1">;
90
+ repo: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
91
+ issue: z.ZodNumber;
92
+ comment: z.ZodNumber;
93
+ url: z.ZodString;
94
+ revision: z.ZodString;
95
+ author: z.ZodObject<{
96
+ id: z.ZodNumber;
97
+ login: z.ZodString;
98
+ }, z.core.$strict>;
99
+ updatedAt: z.ZodString;
100
+ span: z.ZodObject<{
101
+ start: z.ZodNumber;
102
+ end: z.ZodNumber;
103
+ quote: z.ZodString;
104
+ }, z.core.$strict>;
105
+ }, z.core.$strict>>;
106
+ }, z.core.$strict>>;
107
+ }, z.core.$strict>;
108
+ /** Compact agent receipt includes complete selected quotes, with no unrelated discussion prose. */
109
+ export type DiscussionCaptureReport = z.infer<typeof discussionReportSchema>;
110
+ //# sourceMappingURL=discussion-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discussion-schema.d.ts","sourceRoot":"","sources":["../discussion-schema.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,+GAA+G;AAC/G,eAAO,MAAM,uBAAuB;;;;;;;;;;;kBAGlC,CAAC;AACH,2EAA2E;AAC3E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE7E,wGAAwG;AACxG,eAAO,MAAM,sBAAsB;;;;;;;;;;iBAGjC,CAAC;AAEH,kFAAkF;AAClF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;kBAKnC,CAAC;AACH,8FAA8F;AAC9F,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAElF,gGAAgG;AAChG,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAUjC,CAAC;AACH,mGAAmG;AACnG,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /** Shared bounded contracts for explicit selections, lossless evidence and receipts. */
2
+ import { z } from "zod";
3
+ const integer = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
4
+ const positive = integer.min(1);
5
+ const digest = z.string().regex(/^[a-f0-9]{64}$/);
6
+ const nativeName = z.string().min(1).max(512).regex(/^[^\r\n\u0000/\\]+$/);
7
+ const nativeStatus = z.string().min(1).max(512).regex(/^[^\r\n\u0000]+$/);
8
+ const authorFields = { id: positive, login: z.string().min(1).max(200).regex(/^[A-Za-z0-9_.-]+(?:\[bot\])?$/) };
9
+ const repo = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{0,38}\/(?!\.{1,2}$)[A-Za-z0-9_.-]{1,100}$/).transform(value => value.toLowerCase());
10
+ const selection = z.strictObject({ comment: positive, start: integer.max(65536), end: positive.max(65536), quote: z.string().min(1).max(4096), marked: z.literal(true) });
11
+ /** One strict request schema also validates JSON/TOON-decoded round trips. Offsets count UTF-16 code units. */
12
+ export const discussionRequestSchema = z.strictObject({
13
+ repo,
14
+ issue: positive, item: nativeName, selections: z.array(selection).max(10),
15
+ });
16
+ /** Project the public comment wire envelope through the same author and numeric domains as evidence. */
17
+ export const discussionSourceSchema = z.object({
18
+ id: positive, body: z.string().max(65536), issue_url: z.string().max(512), html_url: z.string().max(512),
19
+ updated_at: z.string().datetime({ offset: true }), user: z.object(authorFields),
20
+ });
21
+ /** Exact quoted bytes are JSON data, never a template, command or instruction. */
22
+ export const discussionEvidenceSchema = z.strictObject({
23
+ type: z.literal("github.discussion-decision.v1"), repo, issue: positive,
24
+ comment: positive, url: z.string().url().max(512), revision: digest,
25
+ author: z.strictObject(authorFields), updatedAt: z.string().datetime({ offset: true }),
26
+ span: z.strictObject({ start: integer.max(65536), end: positive.max(65536), quote: z.string().min(1).max(4096) }).refine(value => value.end > value.start && value.end - value.start === value.quote.length),
27
+ });
28
+ /** Every producer uses this validator before returning a successful finite, bounded receipt. */
29
+ export const discussionReportSchema = z.strictObject({
30
+ ok: z.literal(true), mode: z.enum(["plan", "apply"]), approval: digest, item: nativeName, status: nativeStatus,
31
+ selected: integer.max(10), created: integer.max(10), unchanged: integer.max(10), skipped: integer.max(10), refused: integer.max(10),
32
+ rows: z.array(z.strictObject({
33
+ id: nativeName, state: z.enum(["create", "created", "unchanged", "skipped", "refused"]),
34
+ reason: z.enum(["selected_marked_span", "already_captured", "foreign_or_edited", "duplicate_selection", "source_unavailable", "source_changed", "invalid_selection", "captured", "write_failed", "native_refused"]),
35
+ remedy: z.string().max(300), evidence: discussionEvidenceSchema.nullable(),
36
+ })).max(10),
37
+ }).superRefine((value, ctx) => {
38
+ if (value.rows.length !== value.selected || ["created", "unchanged", "skipped", "refused"].some(state => value[state] !== value.rows.filter(row => row.state === state).length))
39
+ ctx.addIssue({ code: "custom", message: "Receipt counters must equal row states" });
40
+ });
41
+ //# sourceMappingURL=discussion-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discussion-schema.js","sourceRoot":"","sources":["../discussion-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ExtensionCommandSdk } from "@unbrained/pm-cli/sdk/authoring";
2
+ import { type DiscussionCaptureInput, type DiscussionCaptureReport } from "./discussion-schema.ts";
3
+ /** Stable refusals do not echo source text, provider responses or local paths. */
4
+ export type DiscussionRefusalCode = "invalid_selection" | "host_required" | "source_unavailable" | "source_changed" | "target_unavailable" | "stale_plan" | "invalid_output";
5
+ /** Selected comment reader allows real HTTP adapters without SDK mocks. */
6
+ export type DiscussionCommentReader = (repo: string, issue: number, comment: number) => Promise<unknown>;
7
+ /** Apply requires the exact preview digest; omitted approval is a read-only plan. */
8
+ export interface DiscussionCaptureOptions {
9
+ approval?: string;
10
+ maxOutputBytes?: number;
11
+ readComment?: DiscussionCommentReader;
12
+ }
13
+ /** Typed expected failure with one bounded, actionable recovery instruction. */
14
+ export declare function refuseDiscussion(code: DiscussionRefusalCode, remedy: string): never;
15
+ /** Fetch only the selected issue and comment; PR review threads are owned by pm-review. */
16
+ export declare function readGithubDiscussionComment(repo: string, issue: number, comment: number): Promise<unknown>;
17
+ /** Bound and validate every successful producer result before a write or response. */
18
+ export declare function validateDiscussionCaptureReport(value: unknown, maxOutputBytes?: number): DiscussionCaptureReport;
19
+ /**
20
+ * Preview and apply share source preparation, ownership checks and native create options.
21
+ * Independent creates need no frozen journal or compensation. Retry always reads current
22
+ * sources, parent history and each Decision. A workspace transaction would not exclude
23
+ * ordinary SDK writers: the final read-to-create window remains explicitly optimistic.
24
+ */
25
+ export declare function captureGithubDiscussion(pmPath: string, value: DiscussionCaptureInput, sdk: ExtensionCommandSdk | undefined, options?: DiscussionCaptureOptions): Promise<DiscussionCaptureReport>;
26
+ //# sourceMappingURL=discussions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discussions.d.ts","sourceRoot":"","sources":["../discussions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAG3E,OAAO,EAAqG,KAAK,sBAAsB,EAAE,KAAK,uBAAuB,EAAmC,MAAM,wBAAwB,CAAC;AAGvO,kFAAkF;AAClF,MAAM,MAAM,qBAAqB,GAAG,mBAAmB,GAAG,eAAe,GAAG,oBAAoB,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAC7K,2EAA2E;AAC3E,MAAM,MAAM,uBAAuB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AACzG,qFAAqF;AACrF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CAGvC;AACD,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAEnF;AAID,2FAA2F;AAC3F,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWhH;AAmED,sFAAsF;AACtF,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,SAAQ,GAAG,uBAAuB,CAM/G;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,mBAAmB,GAAG,SAAS,EAAE,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAmF3M"}
@@ -0,0 +1,215 @@
1
+ /** Explicit GitHub issue-comment decisions, persisted only through the host-injected SDK. */
2
+ import { createHash } from "node:crypto";
3
+ import { createPmCliExpectedError, getHistoryPath, readHistorySnapshot, normalizeItemId, previewItemMutations, locateItem, readLocatedItem } from "@unbrained/pm-cli/sdk";
4
+ import { readGithubWorkspace } from "./workspace.js";
5
+ import { fetchJSON, githubApiBase, resolveGitHubToken } from "./index.js";
6
+ import { discussionRequestSchema, discussionSourceSchema, discussionEvidenceSchema, discussionReportSchema } from "./discussion-schema.js";
7
+ import { z } from "zod";
8
+ /** Typed expected failure with one bounded, actionable recovery instruction. */
9
+ export function refuseDiscussion(code, remedy) {
10
+ throw createPmCliExpectedError(`GitHub discussion capture: ${code}. ${remedy}`, { exitCode: 2, context: { code, required: remedy } });
11
+ }
12
+ /** Hash exact source bytes and SDK history, never a handwritten native normalizer. */
13
+ function hash(value) { return createHash("sha256").update(JSON.stringify(value)).digest("hex"); }
14
+ /** Fetch only the selected issue and comment; PR review threads are owned by pm-review. */
15
+ export async function readGithubDiscussionComment(repo, issue, comment) {
16
+ try {
17
+ const token = resolveGitHubToken();
18
+ const issueResult = await fetchJSON(`${githubApiBase()}/repos/${repo}/issues/${issue}`, token);
19
+ if (issueResult.status !== 200 || Buffer.byteLength(issueResult.body) > 262144)
20
+ throw new Error("incomplete issue");
21
+ const issueRow = z.object({ number: z.number(), pull_request: z.unknown().optional() }).parse(JSON.parse(issueResult.body));
22
+ if (issueRow.pull_request !== undefined || issueRow.number !== issue)
23
+ throw new Error("not an issue");
24
+ const result = await fetchJSON(`${githubApiBase()}/repos/${repo}/issues/comments/${comment}`, token);
25
+ if (result.status !== 200 || Buffer.byteLength(result.body) > 524288)
26
+ throw new Error("incomplete comment");
27
+ return JSON.parse(result.body);
28
+ }
29
+ catch {
30
+ refuseDiscussion("source_unavailable", "Restore read access to the selected GitHub issue and comment; PR review comments use pm-review.");
31
+ }
32
+ }
33
+ /** Validate remote attribution, exact issue membership and the explicitly marked span. */
34
+ async function evidence(input, selected, reader) {
35
+ let raw;
36
+ try {
37
+ raw = await reader(input.repo, input.issue, selected.comment);
38
+ }
39
+ catch {
40
+ refuseDiscussion("source_unavailable", "Restore read access to this selected issue comment and preview again.");
41
+ }
42
+ const parsed = discussionSourceSchema.safeParse(raw);
43
+ if (!parsed.success)
44
+ refuseDiscussion("source_unavailable", "Fetch a complete bounded comment with author, body and update timestamp; preview again.");
45
+ const source = parsed.data;
46
+ const url = `https://github.com/${input.repo}/issues/${input.issue}#issuecomment-${selected.comment}`;
47
+ if (source.id !== selected.comment || source.issue_url.toLowerCase() !== `https://api.github.com/repos/${input.repo}/issues/${input.issue}` || source.html_url.toLowerCase() !== url) {
48
+ refuseDiscussion("invalid_selection", "Select a comment belonging to the exact repository and issue; cross-issue and PR passages are refused.");
49
+ }
50
+ if (selected.end <= selected.start || source.body.slice(selected.start, selected.end) !== selected.quote || selected.end > source.body.length) {
51
+ refuseDiscussion("source_changed", "Read the current comment and select exact UTF-16 start/end offsets and quote bytes again.");
52
+ }
53
+ return discussionEvidenceSchema.parse({ type: "github.discussion-decision.v1", repo: input.repo, issue: input.issue,
54
+ comment: source.id, url, revision: hash([source.id, source.body, source.issue_url, source.html_url, source.updated_at, source.user.id, source.user.login]), author: source.user, updatedAt: source.updated_at,
55
+ span: { start: selected.start, end: selected.end, quote: selected.quote } });
56
+ }
57
+ /** SDK history length plus exact stream digest prevents content-only ABA approvals. */
58
+ async function revision(pmRoot, id) {
59
+ const snapshot = await readHistorySnapshot(getHistoryPath(pmRoot, id), id);
60
+ if (!snapshot.entries.length)
61
+ refuseDiscussion("target_unavailable", "Restore readable native item history before capturing a related Decision.");
62
+ return `${snapshot.entries.length}:${hash(snapshot.raw)}`;
63
+ }
64
+ /** Native document reads avoid command-level usage recording during a read-only plan. */
65
+ async function nativeItem(workspace, id) {
66
+ const located = await locateItem(workspace.pmRoot, id, workspace.settings.id_prefix, workspace.settings.item_format, workspace.types.type_to_folder);
67
+ return located ? (await readLocatedItem(located, { schema: workspace.settings.schema })).document : undefined;
68
+ }
69
+ /** Read the current deterministic target. Foreign or edited records are preserved individually. */
70
+ async function target(workspace, id, marker, body) {
71
+ try {
72
+ const document = await nativeItem(workspace, id);
73
+ const snapshot = await readHistorySnapshot(getHistoryPath(workspace.pmRoot, id), id);
74
+ if (!document)
75
+ return snapshot.raw === null
76
+ ? { state: "create", revision: null, reason: "selected_marked_span" }
77
+ : { state: "skipped", revision: `${snapshot.entries.length}:${hash(snapshot.raw)}`, reason: "foreign_or_edited" };
78
+ const message = snapshot.entries[0]?.message;
79
+ const owned = snapshot.entries.length === 1 && typeof message === "string" && (message === marker || message.startsWith(`${marker} | `)) && document.body === body && document.metadata.type === "Decision";
80
+ return { state: owned ? "unchanged" : "skipped", revision: owned ? null : await revision(workspace.pmRoot, id), reason: owned ? "already_captured" : "foreign_or_edited" };
81
+ }
82
+ catch {
83
+ return { state: "skipped", revision: "unreadable", reason: "foreign_or_edited" };
84
+ }
85
+ }
86
+ /** One native producer is shared by semantic preview and the actual SDK create. */
87
+ function nativeCreate(id, parent, source, marker, status) {
88
+ return { id, type: "Decision", title: `GitHub issue #${source.issue} decision`, status,
89
+ description: `Selected GitHub issue-comment evidence: ${source.url}`, body: JSON.stringify(source),
90
+ parent, clearDeps: true, unset: ["sprint", "release", "goal", "objective"],
91
+ tags: "github-discussion-decision", message: marker,
92
+ doc: [`path: ${source.url}\nscope: project\nnote: Source revision ${source.revision}`] };
93
+ }
94
+ /** Reconcile final reads and ambiguous create failures through the same current-state verdict. */
95
+ function reconciledTarget(current) {
96
+ return current.state === "create"
97
+ ? { state: "refused", reason: "write_failed", remedy: "Check native tracker health and retry the reviewed capture; successful earlier rows are retained." }
98
+ : { state: current.state, reason: current.reason, remedy: current.state === "skipped" ? "Preserve the existing record; review its native history." : "" };
99
+ }
100
+ /** Bound and validate every successful producer result before a write or response. */
101
+ export function validateDiscussionCaptureReport(value, maxOutputBytes = 65536) {
102
+ const parsed = discussionReportSchema.safeParse(value);
103
+ if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 1024 || maxOutputBytes > 131072 || !parsed.success || Buffer.byteLength(JSON.stringify(parsed.data)) > maxOutputBytes) {
104
+ refuseDiscussion("invalid_output", "Use at most ten spans of 4096 code units and a maxOutputBytes integer from 1024 through 131072; split oversized captures.");
105
+ }
106
+ return parsed.data;
107
+ }
108
+ /**
109
+ * Preview and apply share source preparation, ownership checks and native create options.
110
+ * Independent creates need no frozen journal or compensation. Retry always reads current
111
+ * sources, parent history and each Decision. A workspace transaction would not exclude
112
+ * ordinary SDK writers: the final read-to-create window remains explicitly optimistic.
113
+ */
114
+ export async function captureGithubDiscussion(pmPath, value, sdk, options = {}) {
115
+ const parsed = discussionRequestSchema.safeParse(value);
116
+ if (!parsed.success || options.approval !== undefined && (typeof options.approval !== "string" || !/^[a-f0-9]{64}$/.test(options.approval)))
117
+ refuseDiscussion("invalid_selection", "Supply repo, positive issue, existing item and at most ten dense explicitly marked selections with exact offsets and quotes; approve only a full preview digest.");
118
+ const input = parsed.data;
119
+ if (options.maxOutputBytes !== undefined && (!Number.isSafeInteger(options.maxOutputBytes) || options.maxOutputBytes < 1024 || options.maxOutputBytes > 131072))
120
+ refuseDiscussion("invalid_output", "Set maxOutputBytes to an integer from 1024 through 131072.");
121
+ if (!sdk)
122
+ refuseDiscussion("host_required", "Run with a supported pm extension host or inject its tracker-bound ExtensionCommandSdk.");
123
+ const workspace = await readGithubWorkspace(pmPath);
124
+ const { pmRoot, settings, statuses } = workspace;
125
+ let parent;
126
+ let parentRevision;
127
+ try {
128
+ const document = await nativeItem(workspace, input.item);
129
+ if (!document)
130
+ throw new Error("missing context item");
131
+ parent = document.metadata.id;
132
+ parentRevision = await revision(pmRoot, parent);
133
+ }
134
+ catch {
135
+ refuseDiscussion("target_unavailable", "Select an existing readable native item with complete history in this tracker.");
136
+ }
137
+ await options.onBoundary?.("parent_read", -1);
138
+ const reader = options.readComment ?? readGithubDiscussionComment;
139
+ const rows = [];
140
+ const prepared = [];
141
+ const seen = new Set();
142
+ for (const [index, selected] of input.selections.entries()) {
143
+ try {
144
+ const source = await evidence(input, selected, reader);
145
+ await options.onBoundary?.("source_read", index);
146
+ const key = hash({ parent, source });
147
+ const id = normalizeItemId(`discussion-${key.slice(0, 32)}`, settings.id_prefix);
148
+ const body = JSON.stringify(source);
149
+ const marker = `github discussion capture v1 ${hash({ key, parentRevision })}`;
150
+ const current = await target(workspace, id, marker, body);
151
+ await options.onBoundary?.("target_read", index);
152
+ const duplicate = seen.has(id);
153
+ seen.add(id);
154
+ if (!duplicate && current.state === "create") {
155
+ try {
156
+ await previewItemMutations({ pmRoot, author: "pm-github", transactionId: `discussion-preview-${hash({ id, parentRevision, source, settings })}`,
157
+ mutations: [{ op: "create", id, options: nativeCreate(id, parent, source, marker, statuses.open_status) }] });
158
+ }
159
+ catch {
160
+ rows.push({ id, state: "refused", reason: "native_refused", remedy: "Native SDK semantic preview refused this Decision. Check configured create requirements and tracker health; preview again.", evidence: source });
161
+ continue;
162
+ }
163
+ }
164
+ rows.push({ id, state: duplicate ? "skipped" : current.state, reason: duplicate ? "duplicate_selection" : current.reason, remedy: current.state === "skipped" ? "Preserve the existing record; review its native history." : "", evidence: source });
165
+ prepared.push({ index, selected, source, id, body, marker, current, duplicate });
166
+ }
167
+ catch (error) {
168
+ const code = error.code;
169
+ if (code !== "source_unavailable" && code !== "source_changed" && code !== "invalid_selection")
170
+ throw error;
171
+ rows.push({ id: `selection-${index + 1}`, state: "refused", reason: code, remedy: "Refresh this comment and review its exact marked selection; other records remain independent.", evidence: null });
172
+ }
173
+ }
174
+ const schemaRevision = hash({ settings, statuses: statuses.definitions });
175
+ const approval = hash({ pmRoot, parent, parentRevision, schemaRevision,
176
+ rows: rows.map(row => ({ id: row.id, evidence: row.evidence, refusal: row.state === "refused" ? row.reason : null })),
177
+ targets: prepared.map(row => row.current.revision) });
178
+ if (options.approval !== undefined && options.approval !== approval)
179
+ refuseDiscussion("stale_plan", "Source, target history or schema changed. Preview again and review the new approval digest; no frozen plan is replayed.");
180
+ /** Derive counters from rows for every producer, including partial failure and retry receipts. */
181
+ const report = () => validateDiscussionCaptureReport({ ok: true, mode: options.approval === undefined ? "plan" : "apply", approval, item: parent, status: statuses.open_status,
182
+ selected: rows.length, created: rows.filter(row => row.state === "created").length, unchanged: rows.filter(row => row.state === "unchanged").length,
183
+ skipped: rows.filter(row => row.state === "skipped").length, refused: rows.filter(row => row.state === "refused").length, rows }, options.maxOutputBytes);
184
+ const preview = report();
185
+ if (Buffer.byteLength(JSON.stringify(preview)) + rows.length * 512 > (options.maxOutputBytes ?? 65536))
186
+ refuseDiscussion("invalid_output", "Increase maxOutputBytes or select fewer spans; reserve space for per-record retry and refusal receipts.");
187
+ if (options.approval !== undefined)
188
+ for (const row of prepared) {
189
+ if (row.duplicate || row.current.state !== "create")
190
+ continue;
191
+ await options.onBoundary?.("before_write", row.index);
192
+ const fresh = await evidence(input, row.selected, reader);
193
+ const currentParent = await revision(pmRoot, parent);
194
+ const currentWorkspace = await readGithubWorkspace(pmPath);
195
+ if (hash(fresh) !== hash(row.source) || currentParent !== parentRevision || hash({ settings: currentWorkspace.settings, statuses: currentWorkspace.statuses.definitions }) !== schemaRevision) {
196
+ refuseDiscussion("stale_plan", "A selected source, parent history or schema changed before a write. Preserve successful earlier captures and preview again.");
197
+ }
198
+ const current = await target(workspace, row.id, row.marker, row.body);
199
+ if (current.state !== "create") {
200
+ Object.assign(rows[row.index], reconciledTarget(current));
201
+ continue;
202
+ }
203
+ try {
204
+ await sdk.client.create(nativeCreate(row.id, parent, row.source, row.marker, statuses.open_status));
205
+ Object.assign(rows[row.index], { state: "created", reason: "captured" });
206
+ }
207
+ catch {
208
+ const peer = await target(workspace, row.id, row.marker, row.body);
209
+ Object.assign(rows[row.index], reconciledTarget(peer));
210
+ }
211
+ await options.onBoundary?.("after_write", row.index);
212
+ }
213
+ return report();
214
+ }
215
+ //# sourceMappingURL=discussions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discussions.js","sourceRoot":"","sources":["../discussions.ts"],"names":[],"mappings":"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"}
package/dist/gate.d.ts CHANGED
@@ -98,6 +98,8 @@ export interface TrackerGateInput {
98
98
  readonly itemId: string;
99
99
  readonly fields: Readonly<Record<string, unknown>>;
100
100
  }[];
101
+ /** Scan the same rendered plan without collecting a Git diff (read-only previews). */
102
+ readonly planOnly?: boolean;
101
103
  }
102
104
  /**
103
105
  * Resolve the pm data dir from the `pmRoot` a command handler receives.
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../gate.ts"],"names":[],"mappings":"AAwCA;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,mFAAmF;AACnF,UAAU,SAAS;IACjB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wFAAwF;AACxF,UAAU,UAAU;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;CAC3C;AAED,mFAAmF;AACnF,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,kFAAkF;IAClF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,EAAE,CAAC;CACpH;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AA4JD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CASxF;AAED,oEAAoE;AACpE,UAAU,OAAO;IACf,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AA+FD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,EAAE,CAuDhF;AASD,yEAAyE;AACzE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,EAAE,CAOxE;AA2BD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAqG/D;AAoDD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAUnH;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,mBAAwB,GACrC,UAAU,EAAE,CAqEd;AAMD,+DAA+D;AAC/D,UAAU,cAAc;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,OAAO,EACjB,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAyD,GAC5F,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA6B7B;AAED,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AA2FxE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAwElE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAY7D"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../gate.ts"],"names":[],"mappings":"AAwCA;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;;GAKG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,mFAAmF;AACnF,UAAU,SAAS;IACjB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wFAAwF;AACxF,UAAU,UAAU;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;CAC3C;AAED,mFAAmF;AACnF,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,kFAAkF;IAClF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,EAAE,CAAC;IACnH,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AA6JD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CASxF;AAED,oEAAoE;AACpE,UAAU,OAAO;IACf,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AA+FD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,EAAE,CA6DhF;AASD,yEAAyE;AACzE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,EAAE,CAOxE;AA2BD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAqG/D;AAoDD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAUnH;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,mBAAwB,GACrC,UAAU,EAAE,CAqEd;AAMD,+DAA+D;AAC/D,UAAU,cAAc;IACtB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,OAAO,EACjB,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAyD,GAC5F,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA6B7B;AAED,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AA2FxE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CA2ElE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAY7D"}
package/dist/gate.js CHANGED
@@ -104,8 +104,9 @@ const PERSONAL_DATA_RULES = [
104
104
  // followed directly by a path) names the git service account, not a
105
105
  // person, so the pattern skips exactly that shape; a bare `git@host`
106
106
  // contact address, even before a colon and a space, is still matched.
107
+ // The ssh:// form permits only the git service account with a URL path.
107
108
  // The lookbehind keeps a match from starting inside a local part.
108
- pattern: /(?<![A-Za-z0-9._%+-])(?!git@[A-Za-z0-9.-]+\.[A-Za-z]{2,}:[A-Za-z0-9_~./-])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,
109
+ pattern: /(?<![A-Za-z0-9._%+-])(?!(?<=ssh:\/\/)git@[A-Za-z0-9.-]+\.[A-Za-z]{2,}(?=\/|:\d+\/))(?!git@[A-Za-z0-9.-]+\.[A-Za-z]{2,}:[A-Za-z0-9_~./-])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,
109
110
  // GitHub, GitLab and most mail systems use a "noreply" domain or local part
110
111
  // for automated identities; anything else in imported issue text is a real
111
112
  // person's address and fails closed.
@@ -327,7 +328,7 @@ function quotedSourcePositions(line) {
327
328
  /**
328
329
  * Recognize a bare-root token inside an immediately invoked JavaScript regex.
329
330
  *
330
- * Require an expression boundary and a closing test/exec call without crossing
331
+ * Require an expression boundary and a closed regex expression without crossing
331
332
  * quotes, escapes, newlines or another slash. Actual slash-separated paths
332
333
  * remain findings, including paths inside regex source. Walk the lead-in once
333
334
  * backwards instead of rescanning a whole prefix for every candidate. Quoted
@@ -345,8 +346,8 @@ function isBareRootRegex(line, matched, index, quoted) {
345
346
  let before = index - 1;
346
347
  while (before >= 0 && /[ \t]/.test(line[before]))
347
348
  before--;
348
- return (before < 0 || "=(,:".includes(line[before])) &&
349
- /^[ \t][^/"'`\\\r\n]*\/[dgimsuvy]*\.(?:test|exec)[ \t]*\(/.test(line.slice(index + matched.length));
349
+ return (before < 0 || "=([,:".includes(line[before])) &&
350
+ /^[ \t][^/"'`\\\r\n]*\/[dgimsuvy]*(?:\.(?:test|exec)[ \t]*\(|[ \t]*(?:[,;)]|$))/.test(line.slice(index + matched.length));
350
351
  }
351
352
  /**
352
353
  * Scan one added line with every content rule.
@@ -395,16 +396,22 @@ export function scanLineForRuleHits(line, trackerLine = false) {
395
396
  offsets.push(index);
396
397
  }
397
398
  }
398
- const quoted = quotedSourcePositions(decoded);
399
+ let quoted;
399
400
  // Rule normalization can collapse backslash pairs in raw source. Keep its
400
401
  // original quote state too, so that an escaped quote cannot become a closer.
401
- const originalQuoted = serialized ? [] : quotedSourcePositions(line);
402
+ let originalQuoted;
402
403
  const hits = [];
403
404
  for (const rule of [...CREDENTIAL_RULES, ...PERSONAL_DATA_RULES, ...HOST_PATH_RULES]) {
404
405
  rule.pattern.lastIndex = 0;
405
406
  for (let match = rule.pattern.exec(decoded); match; match = rule.pattern.exec(decoded)) {
406
- if (rule.rule === "absolute-host-path" && isBareRootRegex(decoded, match[0], match.index, quoted[match.index] || originalQuoted[offsets[match.index]] === true))
407
- continue;
407
+ if (rule.rule === "absolute-host-path") {
408
+ // Only this rule needs quote state. Inputs without host-path candidates
409
+ // avoid two full scans, and unchanged decoded text shares the same map.
410
+ quoted ??= quotedSourcePositions(decoded);
411
+ originalQuoted ??= serialized ? [] : decoded === line ? quoted : quotedSourcePositions(line);
412
+ if (isBareRootRegex(decoded, match[0], match.index, quoted[match.index] || originalQuoted[offsets[match.index]] === true))
413
+ continue;
414
+ }
408
415
  if (!rule.confirm || rule.confirm(match[0])) {
409
416
  const matched = rule.rule === "home-username" ? match[0].slice(match[0].indexOf("~")) : match[0];
410
417
  const start = match.index + match[0].length - matched.length;
@@ -922,7 +929,11 @@ export function runTrackerGate(input) {
922
929
  let source;
923
930
  let files;
924
931
  try {
925
- if (input.diffFile) {
932
+ if (input.planOnly) {
933
+ source = "diff";
934
+ files = [];
935
+ }
936
+ else if (input.diffFile) {
926
937
  source = "diff";
927
938
  const diffText = readFileSync(path.resolve(input.diffFile));
928
939
  files = parseUnifiedDiff(diffText);