oh-my-customcode 0.99.1 → 0.99.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.
package/README.md CHANGED
@@ -222,7 +222,7 @@ Key rules: R010 (orchestrator never writes files), R009 (parallel execution mand
222
222
 
223
223
  ---
224
224
 
225
- ### Guides (38)
225
+ ### Guides (39)
226
226
 
227
227
  Reference documentation covering best practices, architecture decisions, and integration patterns. Located in `guides/` at project root, covering topics from agent design to CI/CD to observability.
228
228
 
@@ -279,7 +279,7 @@ your-project/
279
279
  │ ├── specs/ # Extracted canonical specs
280
280
  │ ├── contexts/ # 4 shared context files
281
281
  │ └── ontology/ # Knowledge graph for RAG
282
- └── guides/ # 38 reference documents
282
+ └── guides/ # 39 reference documents
283
283
  ```
284
284
 
285
285
  ---
package/dist/cli/index.js CHANGED
@@ -2334,7 +2334,7 @@ var init_package = __esm(() => {
2334
2334
  workspaces: [
2335
2335
  "packages/*"
2336
2336
  ],
2337
- version: "0.99.1",
2337
+ version: "0.99.2",
2338
2338
  description: "Batteries-included agent harness for Claude Code",
2339
2339
  type: "module",
2340
2340
  bin: {
@@ -28107,7 +28107,14 @@ async function installSettingsLocal(targetDir, result) {
28107
28107
  await writeJsonFile(settingsPath, existing);
28108
28108
  debug("install.settings_local_merged", {});
28109
28109
  } else {
28110
- debug("install.settings_local_skipped", { reason: "statusLine exists" });
28110
+ const sl = existing.statusLine;
28111
+ if (sl.refreshInterval === undefined) {
28112
+ sl.refreshInterval = statusLineConfig.statusLine.refreshInterval;
28113
+ await writeJsonFile(settingsPath, existing);
28114
+ debug("install.settings_local_refreshInterval_added", {});
28115
+ } else {
28116
+ debug("install.settings_local_skipped", { reason: "statusLine exists" });
28117
+ }
28111
28118
  }
28112
28119
  } catch {
28113
28120
  result.warnings.push("Failed to parse existing settings.local.json, skipping statusLine config");
@@ -31008,6 +31015,32 @@ async function updateEntryDoc(targetDir, config, options) {
31008
31015
  info("update.entry_doc_created", { path: layout.entryFile });
31009
31016
  }
31010
31017
  }
31018
+ async function backfillStatusLineRefreshInterval(targetDir, options) {
31019
+ if (options.dryRun) {
31020
+ return;
31021
+ }
31022
+ const layout = getProviderLayout();
31023
+ const settingsPath = join17(targetDir, layout.rootDir, "settings.local.json");
31024
+ if (!await fileExists(settingsPath)) {
31025
+ return;
31026
+ }
31027
+ try {
31028
+ const existing = await readJsonFile(settingsPath);
31029
+ if (!existing.statusLine) {
31030
+ return;
31031
+ }
31032
+ const sl = existing.statusLine;
31033
+ if (sl.refreshInterval === undefined) {
31034
+ sl.refreshInterval = 10;
31035
+ await writeJsonFile(settingsPath, existing);
31036
+ debug("update.settings_local_refreshInterval_backfilled", {});
31037
+ }
31038
+ } catch {
31039
+ warn("update.settings_local_backfill_failed", {
31040
+ path: settingsPath
31041
+ });
31042
+ }
31043
+ }
31011
31044
  async function runFullUpdatePostProcessing(options, result, config) {
31012
31045
  const isFullUpdate = !options.components || options.components.length === 0;
31013
31046
  if (isFullUpdate) {
@@ -31017,6 +31050,7 @@ async function runFullUpdatePostProcessing(options, result, config) {
31017
31050
  result.removedDeprecatedFiles = removed;
31018
31051
  if (!options.dryRun) {
31019
31052
  await updateEntryDoc(options.targetDir, config, options);
31053
+ await backfillStatusLineRefreshInterval(options.targetDir, options);
31020
31054
  }
31021
31055
  }
31022
31056
  if (!options.dryRun) {
@@ -31597,7 +31631,9 @@ function reportProjectUpdateResult(project, result, currentVersion) {
31597
31631
  }
31598
31632
  async function updateAllProjects(options) {
31599
31633
  const { findProjects: findProjects2 } = await Promise.resolve().then(() => (init_projects(), exports_projects));
31634
+ const { cleanRegistry: cleanRegistry2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
31600
31635
  const currentVersion = package_default.version;
31636
+ await cleanRegistry2();
31601
31637
  console.log(i18n.t("cli.update.allScanning"));
31602
31638
  const projects = await findProjects2();
31603
31639
  if (projects.length === 0) {
package/dist/index.js CHANGED
@@ -1699,7 +1699,14 @@ async function installSettingsLocal(targetDir, result) {
1699
1699
  await writeJsonFile(settingsPath, existing);
1700
1700
  debug("install.settings_local_merged", {});
1701
1701
  } else {
1702
- debug("install.settings_local_skipped", { reason: "statusLine exists" });
1702
+ const sl = existing.statusLine;
1703
+ if (sl.refreshInterval === undefined) {
1704
+ sl.refreshInterval = statusLineConfig.statusLine.refreshInterval;
1705
+ await writeJsonFile(settingsPath, existing);
1706
+ debug("install.settings_local_refreshInterval_added", {});
1707
+ } else {
1708
+ debug("install.settings_local_skipped", { reason: "statusLine exists" });
1709
+ }
1703
1710
  }
1704
1711
  } catch {
1705
1712
  result.warnings.push("Failed to parse existing settings.local.json, skipping statusLine config");
@@ -2007,7 +2014,7 @@ var package_default = {
2007
2014
  workspaces: [
2008
2015
  "packages/*"
2009
2016
  ],
2010
- version: "0.99.1",
2017
+ version: "0.99.2",
2011
2018
  description: "Batteries-included agent harness for Claude Code",
2012
2019
  type: "module",
2013
2020
  bin: {
@@ -4806,6 +4813,32 @@ async function updateEntryDoc(targetDir, config, options) {
4806
4813
  info("update.entry_doc_created", { path: layout.entryFile });
4807
4814
  }
4808
4815
  }
4816
+ async function backfillStatusLineRefreshInterval(targetDir, options) {
4817
+ if (options.dryRun) {
4818
+ return;
4819
+ }
4820
+ const layout = getProviderLayout();
4821
+ const settingsPath = join7(targetDir, layout.rootDir, "settings.local.json");
4822
+ if (!await fileExists(settingsPath)) {
4823
+ return;
4824
+ }
4825
+ try {
4826
+ const existing = await readJsonFile(settingsPath);
4827
+ if (!existing.statusLine) {
4828
+ return;
4829
+ }
4830
+ const sl = existing.statusLine;
4831
+ if (sl.refreshInterval === undefined) {
4832
+ sl.refreshInterval = 10;
4833
+ await writeJsonFile(settingsPath, existing);
4834
+ debug("update.settings_local_refreshInterval_backfilled", {});
4835
+ }
4836
+ } catch {
4837
+ warn("update.settings_local_backfill_failed", {
4838
+ path: settingsPath
4839
+ });
4840
+ }
4841
+ }
4809
4842
  async function runFullUpdatePostProcessing(options, result, config) {
4810
4843
  const isFullUpdate = !options.components || options.components.length === 0;
4811
4844
  if (isFullUpdate) {
@@ -4815,6 +4848,7 @@ async function runFullUpdatePostProcessing(options, result, config) {
4815
4848
  result.removedDeprecatedFiles = removed;
4816
4849
  if (!options.dryRun) {
4817
4850
  await updateEntryDoc(options.targetDir, config, options);
4851
+ await backfillStatusLineRefreshInterval(options.targetDir, options);
4818
4852
  }
4819
4853
  }
4820
4854
  if (!options.dryRun) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "0.99.1",
6
+ "version": "0.99.2",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -246,7 +246,13 @@ if [[ -n "$git_branch" ]] && command -v gh >/dev/null 2>&1; then
246
246
  pr_number="$cached_pr"
247
247
  else
248
248
  # Cache miss — query gh and update cache
249
- pr_number="$(gh pr view --json number -q .number 2>/dev/null || echo "")"
249
+ # Timeout-guarded gh pr view (2 second limit)
250
+ if command -v timeout >/dev/null 2>&1; then
251
+ pr_number="$(timeout 2 gh pr view --json number -q .number 2>/dev/null || echo "")"
252
+ else
253
+ pr_number="$( (gh pr view --json number -q .number 2>/dev/null &
254
+ _pid=$!; (sleep 2; kill $_pid 2>/dev/null) &; wait $_pid 2>/dev/null) || echo "" )"
255
+ fi
250
256
  printf '%s\t%s\n' "$git_branch" "$pr_number" > "$cache_file"
251
257
  fi
252
258
 
@@ -118,7 +118,7 @@ project/
118
118
  | +-- rules/ # 전역 규칙 (R000-R022)
119
119
  | +-- hooks/ # 훅 스크립트 (보안, 검증, HUD)
120
120
  | +-- contexts/ # 컨텍스트 파일 (ecomode)
121
- +-- guides/ # 레퍼런스 문서 (38 토픽)
121
+ +-- guides/ # 레퍼런스 문서 (39 토픽)
122
122
  ```
123
123
 
124
124
  ## 오케스트레이션
@@ -0,0 +1,191 @@
1
+ # Claude Design Handoff Guide
2
+
3
+ Guide for connecting Claude Design (Anthropic's conversational design tool) outputs to Claude Code's `fe-design-expert` workflow.
4
+
5
+ ---
6
+
7
+ ## 1. What is Claude Design?
8
+
9
+ Claude Design is Anthropic's conversational design tool that generates UI design specifications through natural language dialogue. It produces structured design artifacts — component specs, design tokens, layout definitions — intended for direct handoff to a coding workflow.
10
+
11
+ **Key distinction**: Claude Design produces *design intent* (what it should look like, why), not production code. The handoff to Claude Code is where intent becomes implementation.
12
+
13
+ ---
14
+
15
+ ## 2. Artifact Formats
16
+
17
+ Claude Design exports artifacts in two primary forms:
18
+
19
+ ### Design Token JSON
20
+
21
+ ```json
22
+ {
23
+ "tokens": {
24
+ "color": {
25
+ "brand-primary": { "value": "oklch(0.65 0.22 264)", "type": "color" },
26
+ "surface-base": { "value": "oklch(0.98 0.005 264)", "type": "color" },
27
+ "text-primary": { "value": "oklch(0.15 0.01 264)", "type": "color" }
28
+ },
29
+ "spacing": {
30
+ "xs": { "value": "4px", "type": "dimension" },
31
+ "sm": { "value": "8px", "type": "dimension" },
32
+ "md": { "value": "16px", "type": "dimension" },
33
+ "lg": { "value": "24px", "type": "dimension" },
34
+ "xl": { "value": "40px", "type": "dimension" }
35
+ },
36
+ "typography": {
37
+ "heading-xl": { "fontFamily": "Inter", "fontSize": "36px", "fontWeight": "700", "lineHeight": "1.15" },
38
+ "body-md": { "fontFamily": "Inter", "fontSize": "16px", "fontWeight": "400", "lineHeight": "1.6" }
39
+ },
40
+ "radius": {
41
+ "sm": { "value": "4px" },
42
+ "md": { "value": "8px" },
43
+ "lg": { "value": "16px" }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ### Component Specification
50
+
51
+ ```json
52
+ {
53
+ "component": "PrimaryButton",
54
+ "intent": "High-emphasis action trigger",
55
+ "variants": ["default", "hover", "active", "disabled"],
56
+ "tokens": {
57
+ "background": "color.brand-primary",
58
+ "text": "color.surface-base",
59
+ "padding": "spacing.sm spacing.md",
60
+ "radius": "radius.md"
61
+ },
62
+ "motion": {
63
+ "hover": "background lightens 8%, 150ms ease-out",
64
+ "active": "scale(0.97), 80ms ease-in"
65
+ },
66
+ "states": {
67
+ "disabled": "opacity: 0.45, cursor: not-allowed"
68
+ }
69
+ }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 3. Claude Design → Claude Code Handoff Workflow
75
+
76
+ ```
77
+ Claude Design session
78
+ ↓ Export artifacts (tokens JSON + component specs)
79
+
80
+ fe-design-expert receives handoff
81
+ ├── 1. Validate token structure and completeness
82
+ ├── 2. Convert tokens to CSS custom properties
83
+ ├── 3. Implement component specs as framework components
84
+ ├── 4. Run AI Slop Test on generated output
85
+ └── 5. Verify motion specs are purposeful, not decorative
86
+ ```
87
+
88
+ ### Step 1 — Token Validation
89
+
90
+ Before implementing, `fe-design-expert` checks:
91
+
92
+ | Check | Pass Condition |
93
+ |-------|---------------|
94
+ | Color format | OKLCH preferred; hex acceptable with tinting |
95
+ | Typography completeness | At least 2 scale levels (heading + body) |
96
+ | Spacing system | Consistent multiplier (e.g., 4px base) |
97
+ | No pure values | No `#000`, `#fff`, `0px` radius everywhere |
98
+
99
+ ### Step 2 — CSS Custom Properties Conversion
100
+
101
+ ```css
102
+ :root {
103
+ /* Colors */
104
+ --color-brand-primary: oklch(0.65 0.22 264);
105
+ --color-surface-base: oklch(0.98 0.005 264);
106
+ --color-text-primary: oklch(0.15 0.01 264);
107
+
108
+ /* Spacing */
109
+ --spacing-xs: 4px;
110
+ --spacing-sm: 8px;
111
+ --spacing-md: 16px;
112
+ --spacing-lg: 24px;
113
+ --spacing-xl: 40px;
114
+
115
+ /* Typography */
116
+ --font-heading-xl-size: 36px;
117
+ --font-heading-xl-weight: 700;
118
+ --font-heading-xl-line-height: 1.15;
119
+ --font-body-md-size: 16px;
120
+ --font-body-md-line-height: 1.6;
121
+
122
+ /* Radius */
123
+ --radius-sm: 4px;
124
+ --radius-md: 8px;
125
+ --radius-lg: 16px;
126
+ }
127
+ ```
128
+
129
+ ### Step 3 — Component Implementation
130
+
131
+ For each component spec, fe-design-expert maps design intent to framework idioms. The component spec drives the structure; the Impeccable design language guides the aesthetic decisions.
132
+
133
+ ### Step 4 — Slop Test
134
+
135
+ All handoff implementations pass the [AI Slop Test](../impeccable-design/typography.md) before shipping. Common handoff failures:
136
+
137
+ - Generic gradient applied without contextual rationale from the spec
138
+ - Uniform border radius applied to all elements despite spec differentiation
139
+ - Motion added from spec but without checking `prefers-reduced-motion`
140
+
141
+ ---
142
+
143
+ ## 4. fe-design-expert Validation Checklist
144
+
145
+ When receiving a Claude Design handoff, fe-design-expert verifies:
146
+
147
+ **Token Integrity**
148
+ - [ ] Color values use OKLCH or intentionally tinted hex (no pure neutrals)
149
+ - [ ] Spacing values follow a consistent scale (not random)
150
+ - [ ] Typography has clear hierarchy (not all the same weight/size)
151
+
152
+ **Component Fidelity**
153
+ - [ ] All variant states from the spec are implemented (hover, active, disabled)
154
+ - [ ] Token references in code match the CSS custom property names
155
+ - [ ] No hardcoded values where a token exists in the spec
156
+
157
+ **Motion Verification**
158
+ - [ ] Each animation has a functional purpose from the spec intent
159
+ - [ ] `prefers-reduced-motion` media query wraps all transitions
160
+ - [ ] Duration follows the spec; no arbitrary values
161
+
162
+ **Slop Check**
163
+ - [ ] Would a developer immediately identify this as AI-generated? → Must be NO
164
+ - [ ] Are spacing increments varied intentionally, not uniformly 8px everywhere?
165
+ - [ ] Does the color palette have at least one intentional tinted neutral?
166
+
167
+ ---
168
+
169
+ ## 5. Common Handoff Issues
170
+
171
+ | Issue | Symptom | Resolution |
172
+ |-------|---------|------------|
173
+ | Token name mismatch | CSS var not found in component | Reconcile export names with implementation names |
174
+ | Missing states | Hover/disabled not specified | Ask Claude Design to complete the variant set before handoff |
175
+ | Motion without context | Animation in spec but no intent stated | Treat as decorative — remove or add functional justification |
176
+ | Incomplete spacing system | Gaps between spec tokens and layout needs | Interpolate from the existing scale; do not introduce arbitrary values |
177
+ | Font not available | Spec font not on system/CDN | Use the closest available weight/optical size from the same family |
178
+
179
+ ---
180
+
181
+ ## 6. Quick Reference
182
+
183
+ | Artifact | Format | Handled by |
184
+ |----------|--------|-----------|
185
+ | Design tokens | JSON → CSS custom properties | fe-design-expert |
186
+ | Component specs | JSON → framework components | fe-design-expert |
187
+ | Layout definitions | Spatial intent → CSS Grid/Flex | fe-design-expert |
188
+ | Motion specs | Timing intent → CSS transitions/animations | fe-design-expert |
189
+ | Accessibility requirements | WCAG notes → fe-vercel-agent / web-design-guidelines | fe-vercel-agent |
190
+
191
+ **Agent handoff**: `fe-design-expert` handles aesthetics and visual implementation. For accessibility compliance and semantic HTML, pass to `fe-vercel-agent` or invoke the `web-design-guidelines` skill.
@@ -0,0 +1,15 @@
1
+ name: claude-design
2
+ description: Claude Design artifact handoff workflow — connecting Anthropic's conversational design tool outputs to Claude Code's fe-design-expert implementation pipeline
3
+
4
+ source:
5
+ type: internal
6
+
7
+ topics:
8
+ - design-token-export
9
+ - component-spec-handoff
10
+ - css-custom-properties
11
+ - slop-test-validation
12
+ - motion-verification
13
+
14
+ used_by:
15
+ - fe-design-expert
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.99.1",
2
+ "version": "0.99.2",
3
3
  "lastUpdated": "2026-04-18T00:00:00.000Z",
4
4
  "components": [
5
5
  {
@@ -24,7 +24,7 @@
24
24
  "name": "guides",
25
25
  "path": "guides",
26
26
  "description": "Reference documentation",
27
- "files": 38
27
+ "files": 39
28
28
  },
29
29
  {
30
30
  "name": "hooks",