@calibrate-ds/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/dist/__tests__/component-slug.test.d.ts +2 -0
  2. package/dist/__tests__/component-slug.test.d.ts.map +1 -0
  3. package/dist/__tests__/component-slug.test.js +54 -0
  4. package/dist/__tests__/component-slug.test.js.map +1 -0
  5. package/dist/__tests__/lock-changes.test.d.ts +2 -0
  6. package/dist/__tests__/lock-changes.test.d.ts.map +1 -0
  7. package/dist/__tests__/lock-changes.test.js +81 -0
  8. package/dist/__tests__/lock-changes.test.js.map +1 -0
  9. package/dist/__tests__/permissions.test.d.ts +2 -0
  10. package/dist/__tests__/permissions.test.d.ts.map +1 -0
  11. package/dist/__tests__/permissions.test.js +67 -0
  12. package/dist/__tests__/permissions.test.js.map +1 -0
  13. package/dist/__tests__/stamp-in-lock.test.d.ts +2 -0
  14. package/dist/__tests__/stamp-in-lock.test.d.ts.map +1 -0
  15. package/dist/__tests__/stamp-in-lock.test.js +102 -0
  16. package/dist/__tests__/stamp-in-lock.test.js.map +1 -0
  17. package/dist/__tests__/status-logic.test.d.ts +2 -0
  18. package/dist/__tests__/status-logic.test.d.ts.map +1 -0
  19. package/dist/__tests__/status-logic.test.js +74 -0
  20. package/dist/__tests__/status-logic.test.js.map +1 -0
  21. package/dist/__tests__/team-roster.test.d.ts +2 -0
  22. package/dist/__tests__/team-roster.test.d.ts.map +1 -0
  23. package/dist/__tests__/team-roster.test.js +97 -0
  24. package/dist/__tests__/team-roster.test.js.map +1 -0
  25. package/dist/ai/claude-provider.d.ts +13 -0
  26. package/dist/ai/claude-provider.d.ts.map +1 -0
  27. package/dist/ai/claude-provider.js +335 -0
  28. package/dist/ai/claude-provider.js.map +1 -0
  29. package/dist/ai/enhance-doc.d.ts +24 -0
  30. package/dist/ai/enhance-doc.d.ts.map +1 -0
  31. package/dist/ai/enhance-doc.js +272 -0
  32. package/dist/ai/enhance-doc.js.map +1 -0
  33. package/dist/ai/openai-provider.d.ts +13 -0
  34. package/dist/ai/openai-provider.d.ts.map +1 -0
  35. package/dist/ai/openai-provider.js +345 -0
  36. package/dist/ai/openai-provider.js.map +1 -0
  37. package/dist/ai/prompt-utils.d.ts +23 -0
  38. package/dist/ai/prompt-utils.d.ts.map +1 -0
  39. package/dist/ai/prompt-utils.js +67 -0
  40. package/dist/ai/prompt-utils.js.map +1 -0
  41. package/dist/commands/ai.d.ts +8 -0
  42. package/dist/commands/ai.d.ts.map +1 -0
  43. package/dist/commands/ai.js +576 -0
  44. package/dist/commands/ai.js.map +1 -0
  45. package/dist/commands/apply.d.ts +4 -0
  46. package/dist/commands/apply.d.ts.map +1 -0
  47. package/dist/commands/apply.js +98 -0
  48. package/dist/commands/apply.js.map +1 -0
  49. package/dist/commands/assign.d.ts +5 -0
  50. package/dist/commands/assign.d.ts.map +1 -0
  51. package/dist/commands/assign.js +180 -0
  52. package/dist/commands/assign.js.map +1 -0
  53. package/dist/commands/ci.d.ts +4 -0
  54. package/dist/commands/ci.d.ts.map +1 -0
  55. package/dist/commands/ci.js +84 -0
  56. package/dist/commands/ci.js.map +1 -0
  57. package/dist/commands/context.d.ts +19 -0
  58. package/dist/commands/context.d.ts.map +1 -0
  59. package/dist/commands/context.js +297 -0
  60. package/dist/commands/context.js.map +1 -0
  61. package/dist/commands/diff.d.ts +2 -0
  62. package/dist/commands/diff.d.ts.map +1 -0
  63. package/dist/commands/diff.js +119 -0
  64. package/dist/commands/diff.js.map +1 -0
  65. package/dist/commands/doctor.d.ts +5 -0
  66. package/dist/commands/doctor.d.ts.map +1 -0
  67. package/dist/commands/doctor.js +348 -0
  68. package/dist/commands/doctor.js.map +1 -0
  69. package/dist/commands/document-system.d.ts +5 -0
  70. package/dist/commands/document-system.d.ts.map +1 -0
  71. package/dist/commands/document-system.js +84 -0
  72. package/dist/commands/document-system.js.map +1 -0
  73. package/dist/commands/document.d.ts +6 -0
  74. package/dist/commands/document.d.ts.map +1 -0
  75. package/dist/commands/document.js +276 -0
  76. package/dist/commands/document.js.map +1 -0
  77. package/dist/commands/export.d.ts +11 -0
  78. package/dist/commands/export.d.ts.map +1 -0
  79. package/dist/commands/export.js +74 -0
  80. package/dist/commands/export.js.map +1 -0
  81. package/dist/commands/generate-components.d.ts +4 -0
  82. package/dist/commands/generate-components.d.ts.map +1 -0
  83. package/dist/commands/generate-components.js +62 -0
  84. package/dist/commands/generate-components.js.map +1 -0
  85. package/dist/commands/generate-composites.d.ts +2 -0
  86. package/dist/commands/generate-composites.d.ts.map +1 -0
  87. package/dist/commands/generate-composites.js +31 -0
  88. package/dist/commands/generate-composites.js.map +1 -0
  89. package/dist/commands/generate-tokens.d.ts +2 -0
  90. package/dist/commands/generate-tokens.d.ts.map +1 -0
  91. package/dist/commands/generate-tokens.js +48 -0
  92. package/dist/commands/generate-tokens.js.map +1 -0
  93. package/dist/commands/help-topics.d.ts +2 -0
  94. package/dist/commands/help-topics.d.ts.map +1 -0
  95. package/dist/commands/help-topics.js +324 -0
  96. package/dist/commands/help-topics.js.map +1 -0
  97. package/dist/commands/implement.d.ts +5 -0
  98. package/dist/commands/implement.d.ts.map +1 -0
  99. package/dist/commands/implement.js +595 -0
  100. package/dist/commands/implement.js.map +1 -0
  101. package/dist/commands/import-tokens.d.ts +2 -0
  102. package/dist/commands/import-tokens.d.ts.map +1 -0
  103. package/dist/commands/import-tokens.js +42 -0
  104. package/dist/commands/import-tokens.js.map +1 -0
  105. package/dist/commands/init.d.ts +6 -0
  106. package/dist/commands/init.d.ts.map +1 -0
  107. package/dist/commands/init.js +410 -0
  108. package/dist/commands/init.js.map +1 -0
  109. package/dist/commands/inspect-component.d.ts +2 -0
  110. package/dist/commands/inspect-component.d.ts.map +1 -0
  111. package/dist/commands/inspect-component.js +146 -0
  112. package/dist/commands/inspect-component.js.map +1 -0
  113. package/dist/commands/log.d.ts +4 -0
  114. package/dist/commands/log.d.ts.map +1 -0
  115. package/dist/commands/log.js +109 -0
  116. package/dist/commands/log.js.map +1 -0
  117. package/dist/commands/onboarding.d.ts +9 -0
  118. package/dist/commands/onboarding.d.ts.map +1 -0
  119. package/dist/commands/onboarding.js +63 -0
  120. package/dist/commands/onboarding.js.map +1 -0
  121. package/dist/commands/plan.d.ts +3 -0
  122. package/dist/commands/plan.d.ts.map +1 -0
  123. package/dist/commands/plan.js +108 -0
  124. package/dist/commands/plan.js.map +1 -0
  125. package/dist/commands/prompt.d.ts +5 -0
  126. package/dist/commands/prompt.d.ts.map +1 -0
  127. package/dist/commands/prompt.js +77 -0
  128. package/dist/commands/prompt.js.map +1 -0
  129. package/dist/commands/prune.d.ts +2 -0
  130. package/dist/commands/prune.d.ts.map +1 -0
  131. package/dist/commands/prune.js +95 -0
  132. package/dist/commands/prune.js.map +1 -0
  133. package/dist/commands/remove.d.ts +2 -0
  134. package/dist/commands/remove.d.ts.map +1 -0
  135. package/dist/commands/remove.js +76 -0
  136. package/dist/commands/remove.js.map +1 -0
  137. package/dist/commands/scaffold.d.ts +2 -0
  138. package/dist/commands/scaffold.d.ts.map +1 -0
  139. package/dist/commands/scaffold.js +47 -0
  140. package/dist/commands/scaffold.js.map +1 -0
  141. package/dist/commands/scan.d.ts +2 -0
  142. package/dist/commands/scan.d.ts.map +1 -0
  143. package/dist/commands/scan.js +91 -0
  144. package/dist/commands/scan.js.map +1 -0
  145. package/dist/commands/stamp.d.ts +11 -0
  146. package/dist/commands/stamp.d.ts.map +1 -0
  147. package/dist/commands/stamp.js +147 -0
  148. package/dist/commands/stamp.js.map +1 -0
  149. package/dist/commands/status.d.ts +7 -0
  150. package/dist/commands/status.d.ts.map +1 -0
  151. package/dist/commands/status.js +219 -0
  152. package/dist/commands/status.js.map +1 -0
  153. package/dist/commands/team.d.ts +7 -0
  154. package/dist/commands/team.d.ts.map +1 -0
  155. package/dist/commands/team.js +173 -0
  156. package/dist/commands/team.js.map +1 -0
  157. package/dist/index.d.ts +3 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +303 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/onboarding/content.d.ts +39 -0
  162. package/dist/onboarding/content.d.ts.map +1 -0
  163. package/dist/onboarding/content.js +82 -0
  164. package/dist/onboarding/content.js.map +1 -0
  165. package/dist/utils/component-slug.d.ts +10 -0
  166. package/dist/utils/component-slug.d.ts.map +1 -0
  167. package/dist/utils/component-slug.js +13 -0
  168. package/dist/utils/component-slug.js.map +1 -0
  169. package/dist/utils/framework-registry.d.ts +41 -0
  170. package/dist/utils/framework-registry.d.ts.map +1 -0
  171. package/dist/utils/framework-registry.js +82 -0
  172. package/dist/utils/framework-registry.js.map +1 -0
  173. package/dist/utils/gitignore.d.ts +4 -0
  174. package/dist/utils/gitignore.d.ts.map +1 -0
  175. package/dist/utils/gitignore.js +67 -0
  176. package/dist/utils/gitignore.js.map +1 -0
  177. package/dist/utils/lock-changes.d.ts +14 -0
  178. package/dist/utils/lock-changes.d.ts.map +1 -0
  179. package/dist/utils/lock-changes.js +26 -0
  180. package/dist/utils/lock-changes.js.map +1 -0
  181. package/dist/utils/logger.d.ts +9 -0
  182. package/dist/utils/logger.d.ts.map +1 -0
  183. package/dist/utils/logger.js +32 -0
  184. package/dist/utils/logger.js.map +1 -0
  185. package/dist/utils/permissions.d.ts +17 -0
  186. package/dist/utils/permissions.d.ts.map +1 -0
  187. package/dist/utils/permissions.js +37 -0
  188. package/dist/utils/permissions.js.map +1 -0
  189. package/dist/utils/status-logic.d.ts +16 -0
  190. package/dist/utils/status-logic.d.ts.map +1 -0
  191. package/dist/utils/status-logic.js +32 -0
  192. package/dist/utils/status-logic.js.map +1 -0
  193. package/dist/utils/storybook-setup.d.ts +5 -0
  194. package/dist/utils/storybook-setup.d.ts.map +1 -0
  195. package/dist/utils/storybook-setup.js +104 -0
  196. package/dist/utils/storybook-setup.js.map +1 -0
  197. package/dist/utils/team-roster.d.ts +35 -0
  198. package/dist/utils/team-roster.d.ts.map +1 -0
  199. package/dist/utils/team-roster.js +99 -0
  200. package/dist/utils/team-roster.js.map +1 -0
  201. package/package.json +44 -0
@@ -0,0 +1,98 @@
1
+ import { loadConfig, loadLatestSnapshot, loadPreviousSnapshot, computeDesignDiff, resolveAffectedFiles, syncManifestWithReport, loadManifest, saveManifest, getGenerator } from "@calibrate-ds/core";
2
+ import { logger } from "../utils/logger.js";
3
+ export async function applyCommand(options = {}) {
4
+ try {
5
+ logger.info("Loading ptb.config.json...");
6
+ const config = await loadConfig();
7
+ logger.info("Loading latest snapshot...");
8
+ const currentModel = await loadLatestSnapshot(config);
9
+ if (!currentModel) {
10
+ logger.warn("No current snapshot found. Please run 'ptb scan' first to establish a baseline.");
11
+ return;
12
+ }
13
+ logger.info("Loading previous snapshot from history...");
14
+ const previousData = await loadPreviousSnapshot(config);
15
+ if (!previousData) {
16
+ logger.warn("No previous snapshot found. Run 'ptb scan' at least twice to compare changes.");
17
+ return;
18
+ }
19
+ const summary = computeDesignDiff(previousData.model, currentModel);
20
+ const plan = resolveAffectedFiles(summary, config);
21
+ const generator = getGenerator(config.framework.name || "react");
22
+ if (plan.components.size === 0 && plan.sharedFiles.length === 0) {
23
+ logger.info("No design changes detected. Reconciling manifest...");
24
+ const report = await generator.writeComponents(currentModel, config);
25
+ await syncManifestWithReport(config, report);
26
+ }
27
+ else {
28
+ logger.info("Applying changes...\n");
29
+ const affectedComponentNames = Array.from(plan.components.keys());
30
+ const report = await generator.writeComponents(currentModel, config, {
31
+ forceOverwriteComponents: affectedComponentNames
32
+ });
33
+ await syncManifestWithReport(config, report);
34
+ if (affectedComponentNames.length > 0) {
35
+ console.log(`\x1b[1mRegenerated components:\x1b[0m`);
36
+ for (const name of affectedComponentNames) {
37
+ console.log(`- ${name}`);
38
+ }
39
+ console.log("");
40
+ }
41
+ if (plan.sharedFiles.length > 0) {
42
+ await generator.writeTokens(currentModel, config, { forceOverwriteTokens: true });
43
+ console.log(`\x1b[1mRegenerated shared files:\x1b[0m`);
44
+ for (const file of plan.sharedFiles) {
45
+ console.log(`- ${file}`);
46
+ }
47
+ console.log("");
48
+ }
49
+ }
50
+ // 5. Detect and warn/prune removals based on manifest
51
+ const manifest = await loadManifest(config);
52
+ const staleEntries = [];
53
+ for (const [id, compData] of Object.entries(manifest.components)) {
54
+ const stillExists = currentModel.components.some(c => c.id === id);
55
+ if (!stillExists) {
56
+ staleEntries.push({ id, data: compData });
57
+ }
58
+ }
59
+ if (staleEntries.length > 0) {
60
+ if (options.prune) {
61
+ logger.info(`Found ${staleEntries.length} stale component${staleEntries.length > 1 ? "s" : ""}. Pruning...`);
62
+ const result = await generator.pruneComponents(config, staleEntries);
63
+ if (result.deleted.length > 0) {
64
+ console.log(`\x1b[1mPruned stale components:\x1b[0m`);
65
+ for (const name of result.deleted) {
66
+ console.log(`- ${name}`);
67
+ const entry = staleEntries.find(e => e.data.name === name);
68
+ if (entry)
69
+ delete manifest.components[entry.id];
70
+ }
71
+ console.log("");
72
+ await saveManifest(config, manifest);
73
+ }
74
+ if (result.skipped.length > 0) {
75
+ console.log(`\x1b[33mSkipped pruning (unexpected files present):\x1b[0m`);
76
+ for (const info of result.skipped) {
77
+ console.log(`- ${info}`);
78
+ }
79
+ console.log("");
80
+ }
81
+ }
82
+ else {
83
+ console.log(`\x1b[33mWarning:\x1b[0m`);
84
+ console.log(`${staleEntries.length} component${staleEntries.length > 1 ? "s" : ""} removed from Figma:`);
85
+ for (const entry of staleEntries) {
86
+ console.log(` - ${entry.data.name}`);
87
+ }
88
+ console.log(`\nRun \x1b[1mptb prune\x1b[0m or \x1b[1mptb apply --prune\x1b[0m to delete stale PTB-managed artifacts.\n`);
89
+ }
90
+ }
91
+ logger.success("Apply complete.\n");
92
+ }
93
+ catch (error) {
94
+ logger.error(error.message || String(error));
95
+ process.exit(1);
96
+ }
97
+ }
98
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/commands/apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function assignCommand(name: string, options?: {
2
+ to?: string;
3
+ clear?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=assign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../src/commands/assign.ts"],"names":[],"mappings":"AAmDA,wBAAsB,aAAa,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,iBAqJjD"}
@@ -0,0 +1,180 @@
1
+ import { loadConfig, resolveDSPaths } from "@calibrate-ds/core";
2
+ import { logger } from "../utils/logger.js";
3
+ import { readRoster, getGitUser, toHandle, findMember, findClosestMember, getCurrentUserRole } from "../utils/team-roster.js";
4
+ import { findComponentSlug } from "../utils/component-slug.js";
5
+ import { canAssignToOther, isSelfAssign, canClearAssignment } from "../utils/permissions.js";
6
+ import * as fs from "node:fs/promises";
7
+ import * as path from "node:path";
8
+ import * as readline from "node:readline";
9
+ function ask(question) {
10
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
11
+ return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans.trim()); }));
12
+ }
13
+ async function resolveAssignee(input, roster) {
14
+ const members = Object.values(roster.members);
15
+ // 1. Exact match
16
+ const exact = findMember(input, roster);
17
+ if (exact)
18
+ return `@${exact.handle}`;
19
+ // 2. No roster yet — use as-is
20
+ if (members.length === 0) {
21
+ return input.startsWith("@") ? input : `@${input}`;
22
+ }
23
+ // 3. Fuzzy match — suggest closest
24
+ const closest = findClosestMember(input, roster);
25
+ if (closest) {
26
+ const answer = await ask(`\x1b[33m '${input}' not found. Did you mean @${closest.member.handle} (${closest.member.name})? (Y/n) \x1b[0m`);
27
+ if (answer === "" || answer.toLowerCase() === "y") {
28
+ return `@${closest.member.handle}`;
29
+ }
30
+ }
31
+ else {
32
+ logger.warn(`'${input}' not found in ptb-team.json.`);
33
+ logger.dim(" Registered team members:");
34
+ for (const m of members)
35
+ logger.dim(` @${m.handle.padEnd(20)} ${m.name} <${m.email}>`);
36
+ }
37
+ // 4. Assign as freeform with a warning (pre-registering someone not yet joined)
38
+ logger.dim(` Assigning as '${input.startsWith("@") ? input : "@" + input}' anyway. Ask them to run 'ptb join'.`);
39
+ return input.startsWith("@") ? input : `@${input}`;
40
+ }
41
+ export async function assignCommand(name, options = {}) {
42
+ try {
43
+ const config = await loadConfig();
44
+ const { workspaceRoot } = resolveDSPaths(config);
45
+ const lockPath = path.join(workspaceRoot, "ptb.lock");
46
+ let lock;
47
+ try {
48
+ lock = JSON.parse(await fs.readFile(lockPath, "utf-8"));
49
+ }
50
+ catch {
51
+ logger.error("ptb.lock not found. Run 'ptb scan' first.");
52
+ process.exit(1);
53
+ }
54
+ const roster = await readRoster(workspaceRoot);
55
+ const myRole = getCurrentUserRole(roster);
56
+ const user = getGitUser();
57
+ // Resolve assignee handle
58
+ let assigneeHandle;
59
+ if (!options.clear) {
60
+ if (options.to) {
61
+ // Only leads can assign to others
62
+ if (!canAssignToOther(myRole)) {
63
+ const me = user ? roster.members[user.email] : undefined;
64
+ const myHandle = me ? `@${me.handle}` : undefined;
65
+ if (!isSelfAssign(options.to, myHandle)) {
66
+ logger.error("Only leads can assign components to others.");
67
+ logger.dim(" You can self-assign: ptb assign <component>");
68
+ logger.dim(" Ask a lead to assign to others, or get promoted: ptb team role <handle> lead");
69
+ process.exit(1);
70
+ }
71
+ }
72
+ assigneeHandle = await resolveAssignee(options.to, roster);
73
+ }
74
+ else {
75
+ if (!user) {
76
+ logger.error("Could not determine assignee. Pass a name or run 'git config user.name'.");
77
+ process.exit(1);
78
+ }
79
+ const me = roster.members[user.email];
80
+ assigneeHandle = me ? `@${me.handle}` : `@${toHandle(user.name)}`;
81
+ if (!me && Object.keys(roster.members).length > 0) {
82
+ logger.warn("You're not in the team roster. Run 'ptb join' to register.");
83
+ }
84
+ }
85
+ }
86
+ const all = Object.keys(lock.components);
87
+ const isAll = name === "." || name === "*";
88
+ const targets = [];
89
+ if (isAll) {
90
+ const pending = all.filter(k => {
91
+ const e = lock.components[k];
92
+ return !e.stampedHash || e.stampedHash !== e.designHash;
93
+ });
94
+ if (pending.length === 0) {
95
+ logger.info("No stale or unimplemented components to assign.");
96
+ return;
97
+ }
98
+ targets.push(...pending);
99
+ }
100
+ else {
101
+ const match = findComponentSlug(name, lock.components);
102
+ if (!match) {
103
+ logger.error(`Component '${name}' not found in ptb.lock.`);
104
+ logger.info("Available components:");
105
+ for (const k of all)
106
+ logger.dim(` - ${lock.components[k].displayName} (${k})`);
107
+ process.exit(1);
108
+ }
109
+ targets.push(match);
110
+ }
111
+ let changed = 0;
112
+ let skipped = 0;
113
+ for (const slug of targets) {
114
+ const entry = lock.components[slug];
115
+ if (!options.clear && assigneeHandle) {
116
+ // Already assigned to same person — skip silently
117
+ if (entry.assignedTo === assigneeHandle) {
118
+ skipped++;
119
+ continue;
120
+ }
121
+ // Component is already implemented — warn leads before reassigning
122
+ if (myRole === "lead" && entry.stampedHash && entry.stampedHash === entry.designHash && process.stdout.isTTY) {
123
+ const answer = await ask(` ${entry.displayName} is already implemented (stamped by ${entry.stampedBy ?? "unknown"}). Reassign anyway? (Y/n) `);
124
+ if (answer.toLowerCase() === "n") {
125
+ logger.dim(` Skipped: ${entry.displayName}`);
126
+ skipped++;
127
+ continue;
128
+ }
129
+ }
130
+ // Already assigned to someone else
131
+ if (entry.assignedTo && entry.assignedTo !== assigneeHandle) {
132
+ if (myRole !== "lead") {
133
+ // Members cannot take a component assigned to someone else
134
+ logger.warn(` ${entry.displayName} is already assigned to ${entry.assignedTo}. Ask a lead to reassign it.`);
135
+ skipped++;
136
+ continue;
137
+ }
138
+ // Leads get a confirmation prompt before reassigning
139
+ if (process.stdout.isTTY) {
140
+ const answer = await ask(` ${entry.displayName} is already assigned to ${entry.assignedTo}. Reassign to ${assigneeHandle}? (Y/n) `);
141
+ if (answer.toLowerCase() === "n") {
142
+ logger.dim(` Skipped: ${entry.displayName}`);
143
+ skipped++;
144
+ continue;
145
+ }
146
+ }
147
+ }
148
+ lock.components[slug] = { ...entry, assignedTo: assigneeHandle };
149
+ logger.success(` Assigned: ${entry.displayName} → ${assigneeHandle}`);
150
+ }
151
+ else {
152
+ // Members can only clear their own assignments
153
+ if (entry.assignedTo) {
154
+ const me = user ? roster.members[user.email] : undefined;
155
+ const myHandle = me ? `@${me.handle}` : user ? `@${toHandle(user.name)}` : undefined;
156
+ if (!canClearAssignment(myRole, entry.assignedTo, myHandle)) {
157
+ logger.warn(` ${entry.displayName} is assigned to ${entry.assignedTo}. Only leads can clear others' assignments.`);
158
+ skipped++;
159
+ continue;
160
+ }
161
+ }
162
+ const { assignedTo: _removed, ...rest } = entry;
163
+ lock.components[slug] = rest;
164
+ logger.dim(` Cleared: ${entry.displayName}`);
165
+ }
166
+ changed++;
167
+ }
168
+ await fs.writeFile(lockPath, JSON.stringify(lock, null, 2) + "\n", "utf-8");
169
+ const parts = [
170
+ changed > 0 ? `${changed} updated` : "",
171
+ skipped > 0 ? `${skipped} skipped` : "",
172
+ ].filter(Boolean).join(", ");
173
+ logger.info(`\n${parts}. Commit ptb.lock to share with your team.`);
174
+ }
175
+ catch (error) {
176
+ logger.error(error.message || String(error));
177
+ process.exit(1);
178
+ }
179
+ }
180
+ //# sourceMappingURL=assign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.js","sourceRoot":"","sources":["../../src/commands/assign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function ciSetupCommand(options?: {
2
+ force?: boolean;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=ci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.d.ts","sourceRoot":"","sources":["../../src/commands/ci.ts"],"names":[],"mappings":"AAkDA,wBAAsB,cAAc,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,iBAsCrE"}
@@ -0,0 +1,84 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { loadConfig, resolveDSPaths } from "@calibrate-ds/core";
4
+ import { logger } from "../utils/logger.js";
5
+ import { readRoster, getCurrentUserRole } from "../utils/team-roster.js";
6
+ const PTB_WORKFLOW = `name: PTB Design System Check
7
+
8
+ on:
9
+ push:
10
+ branches: [main, master]
11
+ pull_request:
12
+
13
+ jobs:
14
+ test:
15
+ name: Run tests
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: '20'
24
+
25
+ - name: Install dependencies
26
+ run: npm ci
27
+
28
+ - name: Run tests
29
+ run: npm test
30
+
31
+ ptb-status:
32
+ name: Check component freshness
33
+ runs-on: ubuntu-latest
34
+ needs: test
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+
38
+ - name: Setup Node.js
39
+ uses: actions/setup-node@v4
40
+ with:
41
+ node-version: '20'
42
+
43
+ - name: Install dependencies
44
+ run: npm ci
45
+
46
+ - name: PTB status check
47
+ run: npx ptb status --fail-on-stale
48
+ `;
49
+ export async function ciSetupCommand(options = {}) {
50
+ try {
51
+ const cwd = process.cwd();
52
+ // Only leads can set up CI
53
+ const config = await loadConfig().catch(() => null);
54
+ if (config) {
55
+ const { workspaceRoot } = resolveDSPaths(config);
56
+ const roster = await readRoster(workspaceRoot);
57
+ const myRole = getCurrentUserRole(roster);
58
+ if (myRole !== "lead") {
59
+ logger.error("Only leads can set up CI workflows.");
60
+ logger.dim(" Ask a lead to run: ptb ci setup");
61
+ process.exit(1);
62
+ }
63
+ }
64
+ const workflowsDir = path.join(cwd, ".github", "workflows");
65
+ const workflowPath = path.join(workflowsDir, "ptb.yml");
66
+ const exists = await fs.stat(workflowPath).then(() => true).catch(() => false);
67
+ if (exists && !options.force) {
68
+ logger.warn(`${workflowPath} already exists. Use --force to overwrite.`);
69
+ return;
70
+ }
71
+ await fs.mkdir(workflowsDir, { recursive: true });
72
+ await fs.writeFile(workflowPath, PTB_WORKFLOW, "utf-8");
73
+ logger.success(`Created .github/workflows/ptb.yml`);
74
+ console.log("\n This workflow runs \x1b[36mptb status --fail-on-stale\x1b[0m on every push and pull request.");
75
+ console.log(" It will block merges when components are stale.\n");
76
+ console.log(" \x1b[2mCommit it to take effect:\x1b[0m");
77
+ console.log(" \x1b[2mgit add .github/workflows/ptb.yml && git commit -m \"ci: add PTB design freshness check\"\x1b[0m\n");
78
+ }
79
+ catch (error) {
80
+ logger.error(error.message || String(error));
81
+ process.exit(1);
82
+ }
83
+ }
84
+ //# sourceMappingURL=ci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../../src/commands/ci.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEzE,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CpB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA+B,EAAE;IAClE,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE1B,2BAA2B;QAC3B,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBACpD,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;gBAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC;QACL,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAExD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAC/E,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,4CAA4C,CAAC,CAAC;YACzE,OAAO;QACX,CAAC;QAED,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAExD,MAAM,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,kGAAkG,CAAC,CAAC;QAChH,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,6GAA6G,CAAC,CAAC;IAE/H,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare function contextComponentCommand(name: string, options?: {
2
+ json?: boolean;
3
+ }): Promise<void>;
4
+ /**
5
+ * Handler for 'ptb context list'
6
+ * Lists all exported components from the context index.
7
+ */
8
+ export declare function contextListCommand(): Promise<void>;
9
+ /**
10
+ * Handler for 'ptb context resolve <query>'
11
+ * Resolves a component query to the best matching context file.
12
+ */
13
+ export declare function contextResolveCommand(query: string): Promise<void>;
14
+ /**
15
+ * Handler for 'ptb context open <query>'
16
+ * Prints ONLY the path to the resolved context file for AI IDE integration.
17
+ */
18
+ export declare function contextOpenCommand(query: string): Promise<void>;
19
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAKA,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,iBAuL3F;AAcD;;;GAGG;AACH,wBAAsB,kBAAkB,kBAiCvC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,iBAgCxD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,iBAgCrD"}