forge-cc 1.0.0 → 1.0.2

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 (144) hide show
  1. package/dist/cli.js +7 -1
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +3 -2
  4. package/dist/gates/codex-gate.d.ts +0 -51
  5. package/dist/gates/codex-gate.js +0 -121
  6. package/dist/gates/codex-gate.js.map +0 -1
  7. package/dist/gates/prd-gate.d.ts +0 -7
  8. package/dist/gates/prd-gate.js +0 -193
  9. package/dist/gates/prd-gate.js.map +0 -1
  10. package/dist/gates/remediation.d.ts +0 -46
  11. package/dist/gates/remediation.js +0 -423
  12. package/dist/gates/remediation.js.map +0 -1
  13. package/dist/gates/review-gate.d.ts +0 -16
  14. package/dist/gates/review-gate.js +0 -479
  15. package/dist/gates/review-gate.js.map +0 -1
  16. package/dist/gates/runtime-gate.d.ts +0 -5
  17. package/dist/gates/runtime-gate.js +0 -99
  18. package/dist/gates/runtime-gate.js.map +0 -1
  19. package/dist/gates/test-analysis.d.ts +0 -21
  20. package/dist/gates/test-analysis.js +0 -394
  21. package/dist/gates/test-analysis.js.map +0 -1
  22. package/dist/gates/visual-capture.d.ts +0 -24
  23. package/dist/gates/visual-capture.js +0 -144
  24. package/dist/gates/visual-capture.js.map +0 -1
  25. package/dist/gates/visual-gate.d.ts +0 -18
  26. package/dist/gates/visual-gate.js +0 -234
  27. package/dist/gates/visual-gate.js.map +0 -1
  28. package/dist/gates/visual-reviewer.d.ts +0 -11
  29. package/dist/gates/visual-reviewer.js +0 -211
  30. package/dist/gates/visual-reviewer.js.map +0 -1
  31. package/dist/go/auto-chain.d.ts +0 -136
  32. package/dist/go/auto-chain.js +0 -389
  33. package/dist/go/auto-chain.js.map +0 -1
  34. package/dist/go/executor.d.ts +0 -137
  35. package/dist/go/executor.js +0 -447
  36. package/dist/go/executor.js.map +0 -1
  37. package/dist/go/finalize.d.ts +0 -108
  38. package/dist/go/finalize.js +0 -331
  39. package/dist/go/finalize.js.map +0 -1
  40. package/dist/go/linear-sync-cli.d.ts +0 -55
  41. package/dist/go/linear-sync-cli.js +0 -192
  42. package/dist/go/linear-sync-cli.js.map +0 -1
  43. package/dist/go/linear-sync.d.ts +0 -112
  44. package/dist/go/linear-sync.js +0 -375
  45. package/dist/go/linear-sync.js.map +0 -1
  46. package/dist/go/prd-queue.d.ts +0 -43
  47. package/dist/go/prd-queue.js +0 -67
  48. package/dist/go/prd-queue.js.map +0 -1
  49. package/dist/go/prd-selector.d.ts +0 -57
  50. package/dist/go/prd-selector.js +0 -101
  51. package/dist/go/prd-selector.js.map +0 -1
  52. package/dist/go/verify-loop.d.ts +0 -64
  53. package/dist/go/verify-loop.js +0 -327
  54. package/dist/go/verify-loop.js.map +0 -1
  55. package/dist/hooks/pre-commit.d.ts +0 -5
  56. package/dist/hooks/pre-commit.js +0 -75
  57. package/dist/hooks/pre-commit.js.map +0 -1
  58. package/dist/linear/issues.d.ts +0 -22
  59. package/dist/linear/issues.js +0 -51
  60. package/dist/linear/issues.js.map +0 -1
  61. package/dist/linear/milestones.d.ts +0 -11
  62. package/dist/linear/milestones.js +0 -32
  63. package/dist/linear/milestones.js.map +0 -1
  64. package/dist/linear/projects.d.ts +0 -16
  65. package/dist/linear/projects.js +0 -51
  66. package/dist/linear/projects.js.map +0 -1
  67. package/dist/reporter/human.d.ts +0 -7
  68. package/dist/reporter/human.js +0 -93
  69. package/dist/reporter/human.js.map +0 -1
  70. package/dist/reporter/json.d.ts +0 -2
  71. package/dist/reporter/json.js +0 -4
  72. package/dist/reporter/json.js.map +0 -1
  73. package/dist/setup/structural-templates.d.ts +0 -12
  74. package/dist/setup/structural-templates.js +0 -288
  75. package/dist/setup/structural-templates.js.map +0 -1
  76. package/dist/setup/templates.d.ts +0 -17
  77. package/dist/setup/templates.js +0 -109
  78. package/dist/setup/templates.js.map +0 -1
  79. package/dist/setup/test-planner.d.ts +0 -38
  80. package/dist/setup/test-planner.js +0 -91
  81. package/dist/setup/test-planner.js.map +0 -1
  82. package/dist/setup/test-scaffold.d.ts +0 -31
  83. package/dist/setup/test-scaffold.js +0 -209
  84. package/dist/setup/test-scaffold.js.map +0 -1
  85. package/dist/setup/test-templates.d.ts +0 -37
  86. package/dist/setup/test-templates.js +0 -313
  87. package/dist/setup/test-templates.js.map +0 -1
  88. package/dist/spec/generator.d.ts +0 -34
  89. package/dist/spec/generator.js +0 -227
  90. package/dist/spec/generator.js.map +0 -1
  91. package/dist/spec/interview.d.ts +0 -142
  92. package/dist/spec/interview.js +0 -287
  93. package/dist/spec/interview.js.map +0 -1
  94. package/dist/spec/linear-sync.d.ts +0 -48
  95. package/dist/spec/linear-sync.js +0 -125
  96. package/dist/spec/linear-sync.js.map +0 -1
  97. package/dist/spec/scanner.d.ts +0 -79
  98. package/dist/spec/scanner.js +0 -566
  99. package/dist/spec/scanner.js.map +0 -1
  100. package/dist/spec/templates.d.ts +0 -375
  101. package/dist/spec/templates.js +0 -95
  102. package/dist/spec/templates.js.map +0 -1
  103. package/dist/state/prd-status.d.ts +0 -62
  104. package/dist/state/prd-status.js +0 -122
  105. package/dist/state/prd-status.js.map +0 -1
  106. package/dist/state/reader.d.ts +0 -7
  107. package/dist/state/reader.js +0 -43
  108. package/dist/state/reader.js.map +0 -1
  109. package/dist/state/writer.d.ts +0 -21
  110. package/dist/state/writer.js +0 -106
  111. package/dist/state/writer.js.map +0 -1
  112. package/dist/team/consensus.d.ts +0 -28
  113. package/dist/team/consensus.js +0 -130
  114. package/dist/team/consensus.js.map +0 -1
  115. package/dist/team/index.d.ts +0 -4
  116. package/dist/team/index.js +0 -5
  117. package/dist/team/index.js.map +0 -1
  118. package/dist/team/lifecycle.d.ts +0 -37
  119. package/dist/team/lifecycle.js +0 -92
  120. package/dist/team/lifecycle.js.map +0 -1
  121. package/dist/team/reviewer.d.ts +0 -10
  122. package/dist/team/reviewer.js +0 -345
  123. package/dist/team/reviewer.js.map +0 -1
  124. package/dist/team/types.d.ts +0 -269
  125. package/dist/team/types.js +0 -70
  126. package/dist/team/types.js.map +0 -1
  127. package/dist/utils/browser.d.ts +0 -10
  128. package/dist/utils/browser.js +0 -96
  129. package/dist/utils/browser.js.map +0 -1
  130. package/dist/utils/platform.d.ts +0 -29
  131. package/dist/utils/platform.js +0 -90
  132. package/dist/utils/platform.js.map +0 -1
  133. package/dist/worktree/identity.d.ts +0 -9
  134. package/dist/worktree/identity.js +0 -32
  135. package/dist/worktree/identity.js.map +0 -1
  136. package/dist/worktree/parallel.d.ts +0 -87
  137. package/dist/worktree/parallel.js +0 -328
  138. package/dist/worktree/parallel.js.map +0 -1
  139. package/dist/worktree/session.d.ts +0 -67
  140. package/dist/worktree/session.js +0 -194
  141. package/dist/worktree/session.js.map +0 -1
  142. package/dist/worktree/state-merge.d.ts +0 -43
  143. package/dist/worktree/state-merge.js +0 -162
  144. package/dist/worktree/state-merge.js.map +0 -1
@@ -1,51 +0,0 @@
1
- import { LinearClientError } from "./client.js";
2
- /** Valid issue states */
3
- export const ISSUE_STATES = [
4
- "Backlog",
5
- "Todo",
6
- "In Progress",
7
- "In Review",
8
- "Done",
9
- "Canceled",
10
- ];
11
- /** Create an issue under a project milestone */
12
- export async function createMilestoneIssue(client, input) {
13
- return client.createIssue({
14
- title: input.title,
15
- description: input.description,
16
- teamId: input.teamId,
17
- projectId: input.projectId,
18
- milestoneId: input.milestoneId,
19
- priority: input.priority,
20
- });
21
- }
22
- /** Resolve a state name to its UUID for a given team */
23
- export async function resolveStateId(client, teamId, stateName) {
24
- const states = await client.listWorkflowStates(teamId);
25
- const match = states.find((s) => s.name === stateName);
26
- if (!match) {
27
- throw new LinearClientError(`Workflow state "${stateName}" not found for team ${teamId}`);
28
- }
29
- return match.id;
30
- }
31
- /** Transition all issues in a milestone to a target state */
32
- export async function transitionMilestoneIssues(client, projectId, milestoneId, targetState, teamId) {
33
- // Resolve state name to UUID
34
- const stateId = await resolveStateId(client, teamId, targetState);
35
- const issues = await client.listIssues({ projectId, milestoneId });
36
- const updatedIssues = [];
37
- for (const issue of issues) {
38
- if (issue.state !== targetState) {
39
- const updated = await client.updateIssue(issue.id, {
40
- stateId,
41
- });
42
- updatedIssues.push(updated);
43
- }
44
- }
45
- return { updated: updatedIssues.length, issues: updatedIssues };
46
- }
47
- /** Add a progress comment to an issue */
48
- export async function addProgressComment(client, issueId, message) {
49
- await client.createComment(issueId, message);
50
- }
51
- //# sourceMappingURL=issues.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/linear/issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAoB,MAAM,aAAa,CAAC;AAEhF,yBAAyB;AACzB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,SAAS;IACT,MAAM;IACN,aAAa;IACb,WAAW;IACX,MAAM;IACN,UAAU;CACF,CAAC;AAGX,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAoB,EACpB,KAOC;IAED,OAAO,MAAM,CAAC,WAAW,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;AACL,CAAC;AAED,wDAAwD;AACxD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAoB,EACpB,MAAc,EACd,SAAiB;IAEjB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,iBAAiB,CACzB,mBAAmB,SAAS,wBAAwB,MAAM,EAAE,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,MAAoB,EACpB,SAAiB,EACjB,WAAmB,EACnB,WAAmB,EACnB,MAAc;IAEd,6BAA6B;IAC7B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAElE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;IAEnE,MAAM,aAAa,GAAkB,EAAE,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE;gBACjD,OAAO;aACR,CAAC,CAAC;YACH,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAClE,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAoB,EACpB,OAAe,EACf,OAAe;IAEf,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC"}
@@ -1,11 +0,0 @@
1
- import { LinearClient, type LinearMilestone } from "./client.js";
2
- /** Create a milestone under a project */
3
- export declare function createProjectMilestone(client: LinearClient, projectId: string, name: string, description?: string, targetDate?: string): Promise<LinearMilestone>;
4
- /** Get milestone progress: total and completed issue counts */
5
- export declare function getMilestoneProgress(client: LinearClient, projectId: string, milestoneName: string): Promise<{
6
- milestone: LinearMilestone;
7
- totalIssues: number;
8
- completedIssues: number;
9
- }>;
10
- /** Find a milestone by name within a project */
11
- export declare function findMilestoneByName(client: LinearClient, projectId: string, name: string): Promise<LinearMilestone | null>;
@@ -1,32 +0,0 @@
1
- /** Create a milestone under a project */
2
- export async function createProjectMilestone(client, projectId, name, description, targetDate) {
3
- return client.createMilestone({
4
- projectId,
5
- name,
6
- description,
7
- targetDate,
8
- });
9
- }
10
- /** Get milestone progress: total and completed issue counts */
11
- export async function getMilestoneProgress(client, projectId, milestoneName) {
12
- const milestone = await findMilestoneByName(client, projectId, milestoneName);
13
- if (!milestone) {
14
- throw new Error(`Milestone not found: "${milestoneName}" in project ${projectId}`);
15
- }
16
- const issues = await client.listIssues({
17
- projectId,
18
- milestoneId: milestone.id,
19
- });
20
- const completedIssues = issues.filter((i) => i.state === "Done" || i.state === "Canceled").length;
21
- return {
22
- milestone,
23
- totalIssues: issues.length,
24
- completedIssues,
25
- };
26
- }
27
- /** Find a milestone by name within a project */
28
- export async function findMilestoneByName(client, projectId, name) {
29
- const milestones = await client.listMilestones(projectId);
30
- return milestones.find((m) => m.name === name) ?? null;
31
- }
32
- //# sourceMappingURL=milestones.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"milestones.js","sourceRoot":"","sources":["../../src/linear/milestones.ts"],"names":[],"mappings":"AAEA,yCAAyC;AACzC,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAoB,EACpB,SAAiB,EACjB,IAAY,EACZ,WAAoB,EACpB,UAAmB;IAEnB,OAAO,MAAM,CAAC,eAAe,CAAC;QAC5B,SAAS;QACT,IAAI;QACJ,WAAW;QACX,UAAU;KACX,CAAC,CAAC;AACL,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAoB,EACpB,SAAiB,EACjB,aAAqB;IAMrB,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAC9E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,yBAAyB,aAAa,gBAAgB,SAAS,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;QACrC,SAAS;QACT,WAAW,EAAE,SAAS,CAAC,EAAE;KAC1B,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,KAAK,UAAU,CACpD,CAAC,MAAM,CAAC;IAET,OAAO;QACL,SAAS;QACT,WAAW,EAAE,MAAM,CAAC,MAAM;QAC1B,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,SAAiB,EACjB,IAAY;IAEZ,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1D,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC"}
@@ -1,16 +0,0 @@
1
- import { LinearClient, type LinearProject } from "./client.js";
2
- /** Valid project states in forward-only order */
3
- export declare const PROJECT_STATES: readonly ["Backlog", "Planned", "In Progress", "In Review", "Done"];
4
- export type ProjectState = (typeof PROJECT_STATES)[number];
5
- /**
6
- * Validate that a project state transition is forward-only.
7
- * Backlog -> Planned -> In Progress -> In Review -> Done.
8
- * Same-state transitions are not valid (no-op).
9
- */
10
- export declare function isValidTransition(from: string, to: string): boolean;
11
- /** Create a new project in Backlog state (used during triage) */
12
- export declare function createTriageProject(client: LinearClient, name: string, description: string, teamIds: string[]): Promise<LinearProject>;
13
- /** Transition a project to a target state with forward-only validation */
14
- export declare function transitionProject(client: LinearClient, projectId: string, targetState: string): Promise<LinearProject>;
15
- /** Find an existing project by exact name (for dedup during triage) */
16
- export declare function findProjectByName(client: LinearClient, name: string): Promise<LinearProject | null>;
@@ -1,51 +0,0 @@
1
- import { LinearClientError } from "./client.js";
2
- /** Valid project states in forward-only order */
3
- export const PROJECT_STATES = [
4
- "Backlog",
5
- "Planned",
6
- "In Progress",
7
- "In Review",
8
- "Done",
9
- ];
10
- /** State index map for transition validation */
11
- const stateIndex = new Map(PROJECT_STATES.map((s, i) => [s, i]));
12
- /**
13
- * Validate that a project state transition is forward-only.
14
- * Backlog -> Planned -> In Progress -> In Review -> Done.
15
- * Same-state transitions are not valid (no-op).
16
- */
17
- export function isValidTransition(from, to) {
18
- const fromIdx = stateIndex.get(from);
19
- const toIdx = stateIndex.get(to);
20
- if (fromIdx === undefined || toIdx === undefined)
21
- return false;
22
- return toIdx > fromIdx;
23
- }
24
- /** Create a new project in Backlog state (used during triage) */
25
- export async function createTriageProject(client, name, description, teamIds) {
26
- return client.createProject({
27
- name,
28
- description,
29
- teamIds,
30
- state: "Backlog",
31
- });
32
- }
33
- /** Transition a project to a target state with forward-only validation */
34
- export async function transitionProject(client, projectId, targetState) {
35
- // Fetch current project to validate transition
36
- const projects = await client.listProjects();
37
- const project = projects.find((p) => p.id === projectId);
38
- if (!project) {
39
- throw new LinearClientError(`Project not found: ${projectId}`);
40
- }
41
- if (!isValidTransition(project.state, targetState)) {
42
- throw new LinearClientError(`Invalid project transition: ${project.state} -> ${targetState}`);
43
- }
44
- return client.updateProject(projectId, { state: targetState });
45
- }
46
- /** Find an existing project by exact name (for dedup during triage) */
47
- export async function findProjectByName(client, name) {
48
- const projects = await client.listProjects({ query: name });
49
- return projects.find((p) => p.name === name) ?? null;
50
- }
51
- //# sourceMappingURL=projects.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/linear/projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AAElF,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,SAAS;IACT,aAAa;IACb,WAAW;IACX,MAAM;CACE,CAAC;AAGX,gDAAgD;AAChD,MAAM,UAAU,GAAG,IAAI,GAAG,CACxB,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CACrC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,EAAU;IACxD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC/D,OAAO,KAAK,GAAG,OAAO,CAAC;AACzB,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,IAAY,EACZ,WAAmB,EACnB,OAAiB;IAEjB,OAAO,MAAM,CAAC,aAAa,CAAC;QAC1B,IAAI;QACJ,WAAW;QACX,OAAO;QACP,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,SAAiB,EACjB,WAAmB;IAEnB,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,iBAAiB,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,iBAAiB,CACzB,+BAA+B,OAAO,CAAC,KAAK,OAAO,WAAW,EAAE,CACjE,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,IAAY;IAEZ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AACvD,CAAC"}
@@ -1,7 +0,0 @@
1
- import type { PipelineResult } from "../types.js";
2
- import type { Session } from "../worktree/session.js";
3
- export declare function formatHumanReport(result: PipelineResult): string;
4
- /**
5
- * Format a human-readable sessions report as a markdown table.
6
- */
7
- export declare function formatSessionsReport(sessions: Session[]): string;
@@ -1,93 +0,0 @@
1
- export function formatHumanReport(result) {
2
- const lines = [];
3
- // Header
4
- const status = result.passed ? "PASSED" : "FAILED";
5
- lines.push("## Verification Report");
6
- lines.push(`**Status:** ${status}`);
7
- lines.push(`**Iterations:** ${result.iteration}/${result.maxIterations}`);
8
- const totalMs = result.gates.reduce((sum, g) => sum + g.duration_ms, 0);
9
- lines.push(`**Duration:** ${formatDuration(totalMs)}`);
10
- lines.push("");
11
- // Gate results
12
- lines.push("### Gates");
13
- for (const gate of result.gates) {
14
- const icon = gate.passed ? "[x]" : "[ ]";
15
- const statusText = gate.passed ? "PASS" : "FAIL";
16
- const dur = formatDuration(gate.duration_ms);
17
- let suffix = "";
18
- if (!gate.passed && gate.errors.length > 0) {
19
- suffix = ` — ${gate.errors.length} error${gate.errors.length === 1 ? "" : "s"}`;
20
- }
21
- else if (gate.passed && gate.warnings.length > 0) {
22
- suffix = ` — ${gate.warnings.length} warning${gate.warnings.length === 1 ? "" : "s"}`;
23
- }
24
- lines.push(`- ${icon} ${gate.gate}: ${statusText} (${dur})${suffix}`);
25
- }
26
- lines.push("");
27
- // Errors section
28
- const gatesWithErrors = result.gates.filter((g) => g.errors.length > 0);
29
- if (gatesWithErrors.length > 0) {
30
- lines.push("### Errors");
31
- for (const gate of gatesWithErrors) {
32
- lines.push(`#### ${gate.gate}`);
33
- for (const err of gate.errors) {
34
- const loc = err.file
35
- ? `${err.file}${err.line ? `:${err.line}` : ""}`
36
- : "";
37
- const prefix = loc ? `${loc}: ` : "";
38
- lines.push(`- ${prefix}${err.message}`);
39
- if (err.remediation) {
40
- lines.push(` > Fix: ${err.remediation}`);
41
- }
42
- }
43
- lines.push("");
44
- }
45
- }
46
- // Warnings section
47
- const gatesWithWarnings = result.gates.filter((g) => g.warnings.length > 0);
48
- if (gatesWithWarnings.length > 0) {
49
- lines.push("### Warnings");
50
- for (const gate of gatesWithWarnings) {
51
- lines.push(`#### ${gate.gate}`);
52
- for (const warning of gate.warnings) {
53
- lines.push(`- ${warning}`);
54
- }
55
- lines.push("");
56
- }
57
- }
58
- return lines.join("\n");
59
- }
60
- function formatDuration(ms) {
61
- return `${(ms / 1000).toFixed(1)}s`;
62
- }
63
- /**
64
- * Format a human-readable sessions report as a markdown table.
65
- */
66
- export function formatSessionsReport(sessions) {
67
- if (sessions.length === 0) {
68
- return "No active sessions.";
69
- }
70
- const lines = [];
71
- lines.push("### Active Sessions");
72
- lines.push("| Session | User | Skill | Milestone | Branch | Status | Duration | Worktree |");
73
- lines.push("|---------|------|-------|-----------|--------|--------|----------|----------|");
74
- for (const s of sessions) {
75
- const shortId = s.id.slice(0, 8);
76
- const milestone = s.milestone ?? "\u2014";
77
- const elapsed = Date.now() - new Date(s.startedAt).getTime();
78
- const duration = formatSessionDuration(elapsed);
79
- const statusLabel = s.status === "stale" ? "stale \u26A0" : s.status;
80
- lines.push(`| ${shortId} | ${s.user} | ${s.skill} | ${milestone} | ${s.branch} | ${statusLabel} | ${duration} | ${s.worktreePath} |`);
81
- }
82
- return lines.join("\n");
83
- }
84
- function formatSessionDuration(ms) {
85
- const totalMinutes = Math.round(ms / 60_000);
86
- if (totalMinutes < 60) {
87
- return `${totalMinutes}min`;
88
- }
89
- const hours = Math.floor(totalMinutes / 60);
90
- const minutes = totalMinutes % 60;
91
- return `${hours}h${minutes > 0 ? ` ${minutes}min` : ""}`;
92
- }
93
- //# sourceMappingURL=human.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"human.js","sourceRoot":"","sources":["../../src/reporter/human.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import type { PipelineResult } from "../types.js";
2
- export declare function formatJsonReport(result: PipelineResult): string;
@@ -1,4 +0,0 @@
1
- export function formatJsonReport(result) {
2
- return JSON.stringify(result, null, 2);
3
- }
4
- //# sourceMappingURL=json.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/reporter/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -1,12 +0,0 @@
1
- export interface StructuralTestOptions {
2
- sourceDir: string;
3
- testDir: string;
4
- entryPoints?: string[];
5
- }
6
- export declare function circularImportTemplate(sourceDir: string): string;
7
- export declare function fileNamingTemplate(sourceDir: string): string;
8
- export declare function exportBoundaryTemplate(sourceDir: string, entryPoints: string[]): string;
9
- export declare function generateStructuralTests(options: StructuralTestOptions): Array<{
10
- path: string;
11
- content: string;
12
- }>;
@@ -1,288 +0,0 @@
1
- // ── Structural Test Templates ───────────────────────────────────────
2
- // Template functions that generate self-contained structural/architectural
3
- // test files. Each template returns a string of valid TypeScript test code
4
- // using describe/it/expect (vitest/jest compatible).
5
- // ---------------------------------------------------------------------------
6
- // Template: No Circular Imports
7
- // ---------------------------------------------------------------------------
8
- export function circularImportTemplate(sourceDir) {
9
- return `import { describe, it, expect } from "vitest";
10
- import * as fs from "node:fs";
11
- import * as path from "node:path";
12
-
13
- /**
14
- * Structural test: detect circular import dependencies.
15
- * Scans all .ts/.tsx files under the source directory, builds an adjacency
16
- * list of file-level imports, and fails if any cycle is found.
17
- */
18
-
19
- const SOURCE_DIR = ${JSON.stringify(sourceDir)};
20
-
21
- function collectTsFiles(dir: string): string[] {
22
- const results: string[] = [];
23
- const entries = fs.readdirSync(dir, { withFileTypes: true });
24
- for (const entry of entries) {
25
- const full = path.join(dir, entry.name);
26
- if (entry.isDirectory() && entry.name !== "node_modules") {
27
- results.push(...collectTsFiles(full));
28
- } else if (/\\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
29
- results.push(full);
30
- }
31
- }
32
- return results;
33
- }
34
-
35
- function parseImports(filePath: string): string[] {
36
- const content = fs.readFileSync(filePath, "utf-8");
37
- const importRegex = /(?:import|export)\\s.*?from\\s+["'](.+?)["']/g;
38
- const imports: string[] = [];
39
- for (const match of content.matchAll(importRegex)) {
40
- const specifier = match[1];
41
- // Only resolve relative imports
42
- if (!specifier.startsWith(".")) continue;
43
- const dir = path.dirname(filePath);
44
- let resolved = path.resolve(dir, specifier);
45
- // Strip .js extension to match .ts source files
46
- resolved = resolved.replace(/\\.js$/, "");
47
- // Try common extensions
48
- for (const ext of ["", ".ts", ".tsx", "/index.ts", "/index.tsx"]) {
49
- const candidate = resolved + ext;
50
- if (fs.existsSync(candidate)) {
51
- imports.push(candidate);
52
- break;
53
- }
54
- }
55
- }
56
- return imports;
57
- }
58
-
59
- function detectCycles(
60
- graph: Map<string, string[]>,
61
- ): string[][] {
62
- const visited = new Set<string>();
63
- const inStack = new Set<string>();
64
- const cycles: string[][] = [];
65
-
66
- function dfs(node: string, pathSoFar: string[]): void {
67
- if (inStack.has(node)) {
68
- const cycleStart = pathSoFar.indexOf(node);
69
- cycles.push(pathSoFar.slice(cycleStart).concat(node));
70
- return;
71
- }
72
- if (visited.has(node)) return;
73
- visited.add(node);
74
- inStack.add(node);
75
- const neighbors = graph.get(node) ?? [];
76
- for (const neighbor of neighbors) {
77
- dfs(neighbor, [...pathSoFar, node]);
78
- }
79
- inStack.delete(node);
80
- }
81
-
82
- for (const node of graph.keys()) {
83
- dfs(node, []);
84
- }
85
- return cycles;
86
- }
87
-
88
- describe("No Circular Imports", () => {
89
- it("should have no circular import dependencies", () => {
90
- const absSource = path.resolve(SOURCE_DIR);
91
- const files = collectTsFiles(absSource);
92
- const graph = new Map<string, string[]>();
93
-
94
- for (const file of files) {
95
- graph.set(file, parseImports(file));
96
- }
97
-
98
- const cycles = detectCycles(graph);
99
-
100
- if (cycles.length > 0) {
101
- const formatted = cycles
102
- .map((c) => c.map((f) => path.relative(absSource, f)).join(" -> "))
103
- .join("\\n ");
104
- expect.fail(
105
- \`Found \${cycles.length} circular import(s):\\n \${formatted}\`,
106
- );
107
- }
108
- });
109
- });
110
- `;
111
- }
112
- // ---------------------------------------------------------------------------
113
- // Template: Consistent File Naming
114
- // ---------------------------------------------------------------------------
115
- export function fileNamingTemplate(sourceDir) {
116
- return `import { describe, it, expect } from "vitest";
117
- import * as fs from "node:fs";
118
- import * as path from "node:path";
119
-
120
- /**
121
- * Structural test: enforce consistent kebab-case file naming.
122
- * All .ts/.tsx source files must use kebab-case (e.g., my-component.ts).
123
- * index.ts / index.tsx files are allowed.
124
- */
125
-
126
- const SOURCE_DIR = ${JSON.stringify(sourceDir)};
127
-
128
- function collectTsFiles(dir: string): string[] {
129
- const results: string[] = [];
130
- const entries = fs.readdirSync(dir, { withFileTypes: true });
131
- for (const entry of entries) {
132
- const full = path.join(dir, entry.name);
133
- if (entry.isDirectory() && entry.name !== "node_modules") {
134
- results.push(...collectTsFiles(full));
135
- } else if (/\\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
136
- results.push(full);
137
- }
138
- }
139
- return results;
140
- }
141
-
142
- /** Check if a filename (without extension) is valid kebab-case */
143
- function isKebabCase(name: string): boolean {
144
- return /^[a-z0-9]+(-[a-z0-9]+)*$/.test(name);
145
- }
146
-
147
- describe("Consistent File Naming", () => {
148
- it("should use kebab-case for all source file names", () => {
149
- const absSource = path.resolve(SOURCE_DIR);
150
- const files = collectTsFiles(absSource);
151
- const violations: string[] = [];
152
-
153
- for (const file of files) {
154
- const basename = path.basename(file);
155
- const nameWithoutExt = basename.replace(/\\.tsx?$/, "");
156
-
157
- // Allow index files
158
- if (nameWithoutExt === "index") continue;
159
-
160
- if (!isKebabCase(nameWithoutExt)) {
161
- violations.push(path.relative(absSource, file));
162
- }
163
- }
164
-
165
- if (violations.length > 0) {
166
- expect.fail(
167
- \`Found \${violations.length} file(s) not using kebab-case:\\n \${violations.join("\\n ")}\`,
168
- );
169
- }
170
- });
171
- });
172
- `;
173
- }
174
- // ---------------------------------------------------------------------------
175
- // Template: Export Boundary Validation
176
- // ---------------------------------------------------------------------------
177
- export function exportBoundaryTemplate(sourceDir, entryPoints) {
178
- return `import { describe, it, expect } from "vitest";
179
- import * as fs from "node:fs";
180
- import * as path from "node:path";
181
-
182
- /**
183
- * Structural test: validate public API export boundaries.
184
- * Checks that entry point files only re-export from expected local modules,
185
- * and that no internal-only modules are accidentally exposed.
186
- */
187
-
188
- const SOURCE_DIR = ${JSON.stringify(sourceDir)};
189
- const ENTRY_POINTS: string[] = ${JSON.stringify(entryPoints)};
190
-
191
- function parseExports(filePath: string): string[] {
192
- const content = fs.readFileSync(filePath, "utf-8");
193
- const exportRegex = /export\\s.*?from\\s+["'](.+?)["']/g;
194
- const exports: string[] = [];
195
- for (const match of content.matchAll(exportRegex)) {
196
- exports.push(match[1]);
197
- }
198
- return exports;
199
- }
200
-
201
- describe("Export Boundary Validation", () => {
202
- it("entry point files should exist", () => {
203
- const absSource = path.resolve(SOURCE_DIR);
204
- for (const entry of ENTRY_POINTS) {
205
- const fullPath = path.resolve(absSource, entry);
206
- expect(
207
- fs.existsSync(fullPath),
208
- \`Entry point \${entry} does not exist at \${fullPath}\`,
209
- ).toBe(true);
210
- }
211
- });
212
-
213
- it("entry points should only re-export from relative paths", () => {
214
- const absSource = path.resolve(SOURCE_DIR);
215
- const violations: string[] = [];
216
-
217
- for (const entry of ENTRY_POINTS) {
218
- const fullPath = path.resolve(absSource, entry);
219
- if (!fs.existsSync(fullPath)) continue;
220
-
221
- const exports = parseExports(fullPath);
222
- for (const specifier of exports) {
223
- if (!specifier.startsWith(".")) {
224
- violations.push(\`\${entry}: re-exports from non-relative "\${specifier}"\`);
225
- }
226
- }
227
- }
228
-
229
- if (violations.length > 0) {
230
- expect.fail(
231
- \`Found \${violations.length} unexpected re-export(s):\\n \${violations.join("\\n ")}\`,
232
- );
233
- }
234
- });
235
-
236
- it("entry points should not export from deeply nested internal paths", () => {
237
- const absSource = path.resolve(SOURCE_DIR);
238
- const violations: string[] = [];
239
-
240
- for (const entry of ENTRY_POINTS) {
241
- const fullPath = path.resolve(absSource, entry);
242
- if (!fs.existsSync(fullPath)) continue;
243
-
244
- const exports = parseExports(fullPath);
245
- for (const specifier of exports) {
246
- if (!specifier.startsWith(".")) continue;
247
- // Flag paths that go more than two levels deep (e.g., ./a/b/c/internal)
248
- const depth = specifier.split("/").filter((s) => s !== "." && s !== "..").length;
249
- if (depth > 2) {
250
- violations.push(\`\${entry}: deep internal export "\${specifier}"\`);
251
- }
252
- }
253
- }
254
-
255
- if (violations.length > 0) {
256
- expect.fail(
257
- \`Found \${violations.length} deep internal export(s) that may expose internals:\\n \${violations.join("\\n ")}\`,
258
- );
259
- }
260
- });
261
- });
262
- `;
263
- }
264
- // ---------------------------------------------------------------------------
265
- // Main Generator
266
- // ---------------------------------------------------------------------------
267
- export function generateStructuralTests(options) {
268
- const { sourceDir, testDir, entryPoints } = options;
269
- const results = [];
270
- // Always include circular import detection and file naming
271
- results.push({
272
- path: `${testDir}/structural/no-circular-imports.test.ts`,
273
- content: circularImportTemplate(sourceDir),
274
- });
275
- results.push({
276
- path: `${testDir}/structural/file-naming.test.ts`,
277
- content: fileNamingTemplate(sourceDir),
278
- });
279
- // Include export boundary validation if entry points are specified
280
- if (entryPoints && entryPoints.length > 0) {
281
- results.push({
282
- path: `${testDir}/structural/export-boundaries.test.ts`,
283
- content: exportBoundaryTemplate(sourceDir, entryPoints),
284
- });
285
- }
286
- return results;
287
- }
288
- //# sourceMappingURL=structural-templates.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"structural-templates.js","sourceRoot":"","sources":["../../src/setup/structural-templates.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,2EAA2E;AAC3E,2EAA2E;AAC3E,qDAAqD;AAYrD,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO;;;;;;;;;;qBAUY,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2F7C,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO;;;;;;;;;;qBAUY,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8C7C,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,WAAqB;IAErB,OAAO;;;;;;;;;;qBAUY,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;iCACb,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyE3D,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,UAAU,uBAAuB,CACrC,OAA8B;IAE9B,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACpD,MAAM,OAAO,GAA6C,EAAE,CAAC;IAE7D,2DAA2D;IAC3D,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,GAAG,OAAO,yCAAyC;QACzD,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC;KAC3C,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,GAAG,OAAO,iCAAiC;QACjD,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC;KACvC,CAAC,CAAC;IAEH,mEAAmE;IACnE,IAAI,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,GAAG,OAAO,uCAAuC;YACvD,OAAO,EAAE,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,17 +0,0 @@
1
- import type { TestingConfig } from "../types.js";
2
- export interface SetupContext {
3
- projectName: string;
4
- techStack: string;
5
- description: string;
6
- gates: string[];
7
- date: string;
8
- appDir?: string;
9
- testing?: TestingConfig;
10
- /** forge-cc version stamped into .forge.json during setup */
11
- forgeVersion?: string;
12
- }
13
- export declare function forgeConfigTemplate(ctx: SetupContext): string;
14
- export declare function claudeMdTemplate(ctx: SetupContext): string;
15
- export declare function lessonsMdTemplate(ctx: SetupContext): string;
16
- export declare function globalClaudeMdTemplate(): string;
17
- export declare function gitignoreForgeLines(): string;