@overscore/cli 0.13.14 → 0.13.15

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/dist/index.js CHANGED
@@ -1608,6 +1608,37 @@ function decidePlatformWrite(fullPath, serverContent, serverHash, lastSyncedHash
1608
1608
  }
1609
1609
  return { action: "skip", reason: "user-modified" };
1610
1610
  }
1611
+ // The Hub platform-rules channel currently serves dashboard content (React
1612
+ // rules, deploy-dashboard/start-dashboard skills, and dashboard flavors of
1613
+ // skills the analysis template ships its own versions of). Syncing it into
1614
+ // an analysis misleads Claude and marks the analysis's own skills as
1615
+ // "user-modified" — so analyses only receive the artifact-neutral files.
1616
+ const ANALYSIS_PLATFORM_ALLOW = [
1617
+ "platform-capabilities.md",
1618
+ "skills/update-platform/",
1619
+ ];
1620
+ function isAnalysisDir(targetDir) {
1621
+ if (fs.existsSync(path.join(targetDir, ".overscore", "analysis.json"))) {
1622
+ return true;
1623
+ }
1624
+ // Pulled bundles don't include .overscore/ — fall back to the CLAUDE.md
1625
+ // heading, the same detection syncClaudeMdImports uses.
1626
+ const claudeMdPath = path.join(targetDir, ".claude", "CLAUDE.md");
1627
+ if (!fs.existsSync(claudeMdPath))
1628
+ return false;
1629
+ return /^#\s+Overscore\s+Analysis/im.test(fs.readFileSync(claudeMdPath, "utf-8"));
1630
+ }
1631
+ function filterPlatformFilesForArtifact(targetDir, files) {
1632
+ if (!isAnalysisDir(targetDir))
1633
+ return files;
1634
+ const kept = {};
1635
+ for (const [relPath, content] of Object.entries(files)) {
1636
+ if (ANALYSIS_PLATFORM_ALLOW.some((p) => relPath === p || relPath.startsWith(p))) {
1637
+ kept[relPath] = content;
1638
+ }
1639
+ }
1640
+ return kept;
1641
+ }
1611
1642
  /**
1612
1643
  * Fetch the latest platform-owned Claude Code rules from the Hub and write
1613
1644
  * them into the project's .claude/ directory. Called from `deploy` (before
@@ -1615,6 +1646,7 @@ function decidePlatformWrite(fullPath, serverContent, serverHash, lastSyncedHash
1615
1646
  * paths). User-owned files (knowledge/, this-dashboard.md) are NOT touched.
1616
1647
  *
1617
1648
  * Preserves user edits via .claude/.platform-meta.json hash tracking.
1649
+ * Analyses only receive the artifact-neutral subset (see ANALYSIS_PLATFORM_ALLOW).
1618
1650
  */
1619
1651
  async function syncPlatformRules(targetDir, baseUrl, apiKey) {
1620
1652
  try {
@@ -1626,10 +1658,11 @@ async function syncPlatformRules(targetDir, baseUrl, apiKey) {
1626
1658
  const data = (await res.json());
1627
1659
  if (!data.files)
1628
1660
  return;
1661
+ const files = filterPlatformFilesForArtifact(targetDir, data.files);
1629
1662
  const meta = readPlatformMeta(targetDir);
1630
1663
  const written = [];
1631
1664
  const preserved = [];
1632
- for (const [relPath, content] of Object.entries(data.files)) {
1665
+ for (const [relPath, content] of Object.entries(files)) {
1633
1666
  const fullPath = path.join(targetDir, ".claude", relPath);
1634
1667
  const serverHash = data.hashes?.[relPath] ?? md5(content);
1635
1668
  const lastSyncedHash = meta.last_synced[relPath] ?? null;
@@ -1695,10 +1728,11 @@ async function platformUpdate(checkOnly = false, force = false) {
1695
1728
  console.error("\n Error: No files in platform-rules response.\n");
1696
1729
  process.exit(1);
1697
1730
  }
1731
+ const files = filterPlatformFilesForArtifact(process.cwd(), data.files);
1698
1732
  const meta = readPlatformMeta(process.cwd());
1699
1733
  const updated = [];
1700
1734
  const preserved = [];
1701
- for (const [relPath, content] of Object.entries(data.files)) {
1735
+ for (const [relPath, content] of Object.entries(files)) {
1702
1736
  const fullPath = path.join(process.cwd(), ".claude", relPath);
1703
1737
  const serverHash = data.hashes?.[relPath] ?? md5(content);
1704
1738
  const lastSyncedHash = meta.last_synced[relPath] ?? null;
@@ -1937,6 +1971,9 @@ const ANALYSIS_PUBLISH_BASELINE_EXCLUDE = new Set([
1937
1971
  ".git",
1938
1972
  ".DS_Store",
1939
1973
  ".overscore",
1974
+ // Raw query-result cache (real warehouse rows) — never publishable, even
1975
+ // if .overscoreignore is edited. Mirrors the dashboard deploy SOURCE_EXCLUDE.
1976
+ "data",
1940
1977
  ]);
1941
1978
  function isBaselineExcluded(name) {
1942
1979
  if (ANALYSIS_PUBLISH_BASELINE_EXCLUDE.has(name))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overscore/cli",
3
- "version": "0.13.14",
3
+ "version": "0.13.15",
4
4
  "description": "CLI for deploying Overscore dashboards and publishing analyses",
5
5
  "bin": {
6
6
  "overscore": "dist/index.js"
@@ -11,7 +11,7 @@ paths:
11
11
 
12
12
  - **Inline all CSS.** No `<link rel="stylesheet">`, no Tailwind CDN, no Google Fonts (or use a `data:` URI / system stack). Use a single `<style>` block in the `<head>`.
13
13
  - **Bake the data into the HTML.** No `fetch()`, no `XMLHttpRequest`, no API calls. The numbers must be visible to anyone who opens the file with no logins, no tokens, no broken external dependencies.
14
- - **Charts are inline.** Inline SVG is the safest option. Embedded base64 PNGs are OK. A self-contained chart library (Recharts/D3 from CDN) is acceptable **only if the data is already baked into the page** and the script tag is inline-loaded — but inline SVG is preferred because it survives indefinitely.
14
+ - **Charts are inline.** Inline SVG is the safest option. Embedded base64 PNGs are OK. **No CDN or external `<script src>` — the published report is served under a CSP that blocks all external scripts**, so a CDN-loaded chart library works in local preview but silently breaks after publish. If you must use a JS chart library, paste its source into an inline `<script>` block — but inline SVG is preferred because it survives indefinitely.
15
15
  - **No `useQuery`, no `@overscore/client`, no React.** This is a static HTML file, not a React app.
16
16
 
17
17
  ## Aesthetic direction