mirror of
https://github.com/hanzoai/insights.git
synced 2026-11-02 14:32:45 +00:00
The React bindings, the shim standing in for their peer, and four dead alias lines all resolved to upstream packages. So did the illustrations, the logo and the typeface, through `@hanzo/brand`. `@hanzo/react` now resolves to `@hanzo/insights-react`, which we publish. Its peer is `@hanzo/insights` by name, so `common/sdk-peer` -- a workspace package named `posthog-js` purely to satisfy the old peer -- is gone, and with it the last thing in the tree carrying that name. The fork exports `Insights*` where upstream exported `PostHog*`, so eight files stop aliasing an upstream identifier on import, and the eight allowlist entries excusing them are dropped. `@hanzo/brand` is removed rather than forked. It is licensed PolyForm Strict 1.0.0: noncommercial use only, no derivative works, no redistribution, and the illustrations are upstream trademarks. Forking it was never available to us, and neither was the commercial use we were already making of it. It carried three separate things, and each ends differently. The illustrations were decoration beside real content, so the 106 call sites keep their component and lose the artwork -- the shape `lib/components/mascots.tsx` already used. Two had been repurposed as real icons; those take the house fallback icon. The logo is real UI chrome, so it is rebuilt on Hanzo's own mark, the same glyph as the favicon: monochrome and `currentColor`, so it inherits the surrounding text colour instead of needing a variant per theme, and resolves inside the toolbar's shadow DOM where the old gradient's `url(#...)` fills did not. The typeface becomes Geist, already vendored here under SIL OFL and already the house face everywhere else. Four alias lines named packages nothing installs. pnpm echoes the override block into the lockfile verbatim, so they put an upstream name there for nothing. `bin/debrand --check` now refuses a manifest naming an upstream package unless it is listed with a reason, keyed by package rather than by file so an exemption cannot cover a whole manifest's future dependencies. Six remain, each with the reason it is still upstream's. The check found two nobody had noticed: `cli` and `rust` rename upstream crates with Cargo's `package =` key, the same aliasing on a different registry. The lockfile goes from 94 upstream references to 36.
429 lines
19 KiB
JSON
429 lines
19 KiB
JSON
{
|
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
"plugins": ["typescript", "unicorn", "react", "react-perf", "jest", "promise", "jsdoc", "oxc", "import"],
|
|
"env": {
|
|
"builtin": true
|
|
},
|
|
"ignorePatterns": [
|
|
"products/desktop",
|
|
"node_modules",
|
|
"dist",
|
|
"build",
|
|
"rust",
|
|
"cli",
|
|
"nodejs",
|
|
".semgrep",
|
|
".github/actions/paths-filter",
|
|
".github/scripts",
|
|
"common/scriptvm/typescript",
|
|
"common/scriptvm/typescript/dist",
|
|
"common/plugin_transpiler/dist",
|
|
"common/scriptvm/__tests__/__snapshots__",
|
|
"common/scriptvm/__tests__/__snapshots__/**",
|
|
"frontend/src/queries/validators.js",
|
|
"frontend/src/generated/**",
|
|
"services/mcp/**/generated.ts",
|
|
"services/mcp/schema/tool-inputs.json",
|
|
"products/**/frontend/generated/**"
|
|
],
|
|
"rules": {
|
|
"no-constant-condition": "off",
|
|
"no-prototype-builtins": "off",
|
|
"no-irregular-whitespace": "off",
|
|
"require-await": "off",
|
|
"no-await-in-loop": "off",
|
|
"react/react-in-jsx-scope": "off",
|
|
"react/no-unescaped-entities": "off",
|
|
"react/jsx-no-target-blank": "off",
|
|
"@typescript-eslint/no-empty-function": "off",
|
|
"@typescript-eslint/no-inferrable-types": "off",
|
|
"@typescript-eslint/ban-ts-comment": "off",
|
|
"@typescript-eslint/no-explicit-any": "off",
|
|
"check-tag-names": "off",
|
|
"no-unused-vars": [
|
|
"error",
|
|
{
|
|
"ignoreRestSiblings": true,
|
|
"argsIgnorePattern": "^_",
|
|
"varsIgnorePattern": "^_",
|
|
"destructuredArrayIgnorePattern": "^_"
|
|
}
|
|
],
|
|
"no-useless-spread": "error",
|
|
"no-accumulating-spread": "error",
|
|
"no-useless-fallback-in-spread": "error",
|
|
"react-hooks/exhaustive-deps": "warn",
|
|
"no-else-return": "warn",
|
|
"react-hooks/rules-of-hooks": "error",
|
|
"react/jsx-curly-brace-presence": [
|
|
"error",
|
|
{
|
|
"props": "never",
|
|
"children": "never",
|
|
"propElementValues": "always"
|
|
}
|
|
],
|
|
"no-console": [
|
|
"error",
|
|
{
|
|
"allow": ["info", "warn", "error"]
|
|
}
|
|
],
|
|
"no-debugger": "error",
|
|
"react/self-closing-comp": [
|
|
"error",
|
|
{
|
|
"component": true,
|
|
"html": true
|
|
}
|
|
],
|
|
"@typescript-eslint/prefer-ts-expect-error": "error",
|
|
"@typescript-eslint/explicit-function-return-type": [
|
|
"error",
|
|
{
|
|
"allowExpressions": true
|
|
}
|
|
],
|
|
"curly": "error",
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"paths": [
|
|
{
|
|
"name": "dayjs",
|
|
"message": "Do not directly import dayjs. Only import the dayjs exported from 'lib/dayjs'."
|
|
},
|
|
{
|
|
"name": "chart.js",
|
|
"message": "Do not directly import chart.js. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "chart.js/auto",
|
|
"message": "Do not directly import chart.js/auto. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "~/queries/schema",
|
|
"message": "Import from 'queries/schema/schema-foo' to avoid Webpack/Sucrase enum export issues."
|
|
},
|
|
{
|
|
"name": "monaco-editor",
|
|
"message": "Value imports of monaco-editor statically couple ~4 MB of editor code into your chunk. Use `import type`, or render via the lazy facade in lib/monaco/CodeEditor.",
|
|
"allowTypeImports": true
|
|
},
|
|
{
|
|
"name": "lib/monaco/CodeEditorImpl",
|
|
"message": "Import CodeEditor from lib/monaco/CodeEditor instead — the lazy facade keeps monaco out of your chunk."
|
|
},
|
|
{
|
|
"name": "~/lib/monaco/CodeEditorImpl",
|
|
"message": "Import CodeEditor from lib/monaco/CodeEditor instead — the lazy facade keeps monaco out of your chunk."
|
|
},
|
|
{
|
|
"name": "@hanzo/brand",
|
|
"message": "This product does not depend on upstream's brand package. Its illustrations are their trademarks under a licence that permits neither commercial use nor redistribution. The logo lives in lib/brand; illustration slots render nothing (lib/brand/hoggies)."
|
|
}
|
|
],
|
|
"patterns": [
|
|
{
|
|
"group": ["@hanzo/brand/*"],
|
|
"message": "This product does not depend on upstream's brand package. Its illustrations are their trademarks under a licence that permits neither commercial use nor redistribution. The logo lives in lib/brand; illustration slots render nothing (lib/brand/hoggies)."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"react/forbid-dom-props": [
|
|
"warn",
|
|
{
|
|
"forbid": [
|
|
{
|
|
"propName": "style",
|
|
"message": "style should be avoided in favor of utility CSS classes - see https://storybook.dev.insights.dev/?path=/docs/elements-utilities--overview"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"no-new-array": "warn",
|
|
"react/forbid-elements": [
|
|
"error",
|
|
{
|
|
"forbid": [
|
|
{
|
|
"element": "Layout",
|
|
"message": "use utility classes instead"
|
|
},
|
|
{
|
|
"element": "Space",
|
|
"message": "use flex or space utility classes instead"
|
|
},
|
|
{
|
|
"element": "Spin",
|
|
"message": "use Spinner instead"
|
|
},
|
|
{
|
|
"element": "InputNumber",
|
|
"message": "use Input with type=\"number\" instead"
|
|
},
|
|
{
|
|
"element": "MonacoEditor",
|
|
"message": "use <CodeEditor> instead"
|
|
},
|
|
{
|
|
"element": "ReactMarkdown",
|
|
"message": "use <Markdown> instead"
|
|
},
|
|
{
|
|
"element": "a",
|
|
"message": "use <Link> instead"
|
|
},
|
|
{
|
|
"element": "Alert",
|
|
"message": "use <Banner> instead"
|
|
},
|
|
{
|
|
"element": "ReactJson",
|
|
"message": "use <JSONViewer> for dark mode support instead"
|
|
},
|
|
{
|
|
"element": "Popconfirm",
|
|
"message": "use <Dialog> instead"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"no-constant-binary-expression": "error",
|
|
"no-useless-rename": "error",
|
|
"no-useless-call": "error",
|
|
"import/no-cycle": [
|
|
"warn",
|
|
{
|
|
"maxDepth": 10
|
|
}
|
|
],
|
|
"jest/no-restricted-matchers": [
|
|
"error",
|
|
{
|
|
"toBeDefined": "Do not use .toBeDefined() in tests, use .toBeTruthy() or .not.toBeUndefined() instead."
|
|
}
|
|
]
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": ["*.stories.tsx"],
|
|
"rules": {
|
|
"react-hooks/rules-of-hooks": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["services/mcp/src/generated/**/*.ts"],
|
|
"rules": {
|
|
"no-useless-escape": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["services/mcp/src/ui-apps/**/*.{ts,tsx}"],
|
|
"rules": {
|
|
"no-console": [
|
|
"error",
|
|
{
|
|
"allow": ["debug", "info", "warn", "error"]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["docs/onboarding/**/*.tsx"],
|
|
"rules": {
|
|
"react/forbid-elements": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["services/stripe-app/src/**/*.{ts,tsx}"],
|
|
"rules": {
|
|
"react/forbid-elements": "off",
|
|
"react/forbid-dom-props": "off",
|
|
"no-restricted-imports": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": ["services/mcp/src/ui-apps/**/*.{ts,tsx}", "products/**/mcp/apps/**/*.{ts,tsx}"],
|
|
"rules": {
|
|
"react/forbid-elements": "off"
|
|
}
|
|
},
|
|
{
|
|
"files": [
|
|
"frontend/src/lib/monaco/**",
|
|
"frontend/src/lib/components/MonacoDiffEditor.tsx",
|
|
"frontend/src/scenes/data-warehouse/editor/sqlEditorLogic.tsx",
|
|
"frontend/src/scenes/insights-functions/configuration/InsightsFunctionTest.tsx"
|
|
],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"paths": [
|
|
{
|
|
"name": "dayjs",
|
|
"message": "Do not directly import dayjs. Only import the dayjs exported from 'lib/dayjs'."
|
|
},
|
|
{
|
|
"name": "chart.js",
|
|
"message": "Do not directly import chart.js. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "chart.js/auto",
|
|
"message": "Do not directly import chart.js/auto. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "~/queries/schema",
|
|
"message": "Import from 'queries/schema/schema-foo' to avoid Webpack/Sucrase enum export issues."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["frontend/src/toolbar/**/*.{ts,tsx}"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"patterns": [
|
|
{
|
|
"group": [
|
|
"scenes/**",
|
|
"~/scenes/**",
|
|
"!scenes/urls",
|
|
"!~/scenes/urls",
|
|
"!scenes/product-tours/stepUtils",
|
|
"!scenes/product-tours/constants",
|
|
"!scenes/product-tours/editor/generateStepHtml"
|
|
],
|
|
"message": "The toolbar ships to customer pages and must not depend on app scenes. Import from lib/, or fetch via toolbarFetch. The listed exceptions are the toolbar's intentional seams; the full transitive boundary is enforced by frontend/bin/check-toolbar-graph.mjs."
|
|
},
|
|
{
|
|
"group": ["~/products", "products/**", "~/products/**"],
|
|
"message": "The toolbar must not import product manifests or product frontends — that pulls the whole product graph into the customer-facing bundle."
|
|
},
|
|
{
|
|
"group": ["layout/**", "~/layout/**", "models/**", "~/models/**"],
|
|
"message": "The toolbar must not import app layout or global models."
|
|
}
|
|
],
|
|
"paths": [
|
|
{
|
|
"name": "lib/api",
|
|
"message": "Toolbar code must use toolbarFetch/toolbarApi (authorized via toolbar params), not the app's api client.",
|
|
"allowTypeImports": true
|
|
},
|
|
{
|
|
"name": "~/lib/api",
|
|
"message": "Toolbar code must use toolbarFetch/toolbarApi (authorized via toolbar params), not the app's api client.",
|
|
"allowTypeImports": true
|
|
},
|
|
{
|
|
"name": "dayjs",
|
|
"message": "Do not directly import dayjs. Only import the dayjs exported from 'lib/dayjs'."
|
|
},
|
|
{
|
|
"name": "chart.js",
|
|
"message": "Do not directly import chart.js. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "chart.js/auto",
|
|
"message": "Do not directly import chart.js/auto. Only import the Chart and friends exported from 'lib/Chart'."
|
|
},
|
|
{
|
|
"name": "~/queries/schema",
|
|
"message": "Import from 'queries/schema/schema-foo' to avoid Webpack/Sucrase enum export issues."
|
|
},
|
|
{
|
|
"name": "monaco-editor",
|
|
"message": "Value imports of monaco-editor statically couple ~4 MB of editor code into your chunk. Use `import type`, or render via the lazy facade in lib/monaco/CodeEditor.",
|
|
"allowTypeImports": true
|
|
},
|
|
{
|
|
"name": "lib/monaco/CodeEditorImpl",
|
|
"message": "Import CodeEditor from lib/monaco/CodeEditor instead — the lazy facade keeps monaco out of your chunk."
|
|
},
|
|
{
|
|
"name": "~/lib/monaco/CodeEditorImpl",
|
|
"message": "Import CodeEditor from lib/monaco/CodeEditor instead — the lazy facade keeps monaco out of your chunk."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["products/insights_ai/frontend/sandbox/**/*.{ts,tsx}"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"patterns": [
|
|
{
|
|
"group": ["**/ee/api/conversation", "**/ee/api/conversation/**"],
|
|
"message": "Sandbox renderer must not import the conversation API. Use products/tasks/frontend/generated/api for task data."
|
|
},
|
|
{
|
|
"group": ["**/api.conversations*"],
|
|
"message": "Sandbox renderer must not import api.conversations. Use api.tasks.* and products/tasks/frontend/generated/api."
|
|
}
|
|
],
|
|
"paths": [
|
|
{
|
|
"name": "scenes/max/maxThreadLogic",
|
|
"message": "Sandbox module must not import maxThreadLogic (conversation orchestration). Forbidden by design boundary."
|
|
},
|
|
{
|
|
"name": "scenes/max/maxContextLogic",
|
|
"message": "Sandbox module must not import maxContextLogic. Forbidden by design boundary."
|
|
},
|
|
{
|
|
"name": "scenes/max/maxLogic",
|
|
"message": "Sandbox module must not import maxLogic. Forbidden by design boundary."
|
|
},
|
|
{
|
|
"name": "scenes/max/maxGlobalLogic",
|
|
"message": "Sandbox module must not import maxGlobalLogic. Forbidden by design boundary."
|
|
},
|
|
{
|
|
"name": "scenes/max/maxTypes",
|
|
"message": "Avoid importing maxTypes from the sandbox module. Extract needed types (e.g. SandboxToolCallMessage) into products/insights_ai/frontend/sandbox/types/ instead.",
|
|
"allowTypeImports": true
|
|
},
|
|
{
|
|
"name": "dayjs",
|
|
"message": "Do not directly import dayjs. Only import the dayjs exported from 'lib/dayjs'."
|
|
},
|
|
{
|
|
"name": "~/queries/schema",
|
|
"message": "Import from 'queries/schema/schema-foo' to avoid Webpack/Sucrase enum export issues."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["frontend/src/lib/components/UniversalFilters/constants.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"paths": [
|
|
{
|
|
"name": "~/types",
|
|
"allowTypeImports": true,
|
|
"message": "constants.ts is a leaf module kept free of ~/types's value-import graph (which circles back through scenes/session-recordings and caused \"Cannot access 'DEFAULT_UNIVERSAL_GROUP_FILTER' before initialization\" TDZ errors). Only `import type` from ~/types is allowed here; import/no-cycle can't catch this because the real cycle is far deeper than its configured maxDepth."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|