- NO auto-commit; ask "Commit with: [msg]?" before every
git commit; wait explicit yes - ALWAYS
git fetch origin && git pull origin mainbefore new branches - NO global tool installs (
brew,npm install -g) without explicit approval - NO Docker container starts without approval
- NO issue/PR/comment without disclaimer:
---\n_This {issue|PR|comment} was created by an AI agent on behalf of @<username>._(get username:gh api user -q .login) - NO suppressing warnings/errors/logs — always ask user
- C4: Clear Concise Correct Complete. No summaries/apologies. Markdown+code blocks.
path/file.ts#L1-10refs.
- Bun only:
bun xnot npx,bun runnot npm run,bun testnot jest/vitest - TypeScript ESM, functional/pure preferred
- Search docs before assuming library behavior (WebSearch or context7 MCP)
- Files <150 lines; small single-responsibility functions
- No
anywithout@typescript-eslint/no-explicit-any+ comment - No barrel files (index.ts re-exports); import directly
- No planning terms ("phase1") in names/comments
bun run lintto check;bun run lint:fixto fix- Error handling: descriptive messages
- Exact file paths+line ranges, git branch/SHA, full error/stack, test counts, build artifact status
- Never make user discover repo structure, branches, tests, deps, labels
bun install # REQUIRED after clone; sets up workspace symlinks
bun run build # all packages via turbo
cd packages/X && bun run build # single package
bun test # tests
bun run lint / lint:fix
packages/workspaces,@fossiq/kebab-casenaming, internal depsworkspace:*- Build order deps:
kql-ast→kql-lezer→kql-to-duckdb→ui - After adding package: dir + package.json + copy tsconfig.json + minimal src/index.ts
ghCLI only- Actions debug:
gh run view <id>→gh run view <id> --job=<jid>→gh run view --log-failed --job=<jid>
- No testing during dev; test after source changes with
bun test cd packages/<pkg> && bun test
Prefer MCP over manual searches when available.
- Generates Lezer
.grammarfiles from TypeScript DSL - dist/index.js = compiled; src/ = sources. dist is what bun uses (resolves via package.json "main")
- BUG FIXED:
convertRegexToLezerstep5(?<!!)\[must be(?<![$!])\[to prevent double-processing$[0-9] - BUG FIXED:
convertRegexToLezerstep3 must replace[0-9]BEFORE\d; doing\d→$[0-9]first then[0-9]→$[0-9]double-converts to$$[0-9] - BUG FIXED:
serializeExprseq case must parenthesizechoicechildren:seq(choice(A,B), C)→(A | B) CnotA | B C $[0-9]= lezer char class syntax;@digit/@asciiLetter= INVALID in lezer-generator CLI (do NOT use)kw("term")→ rawkw<"term">→ expands via macro to@specialize[@name=term]<Identifier, "term">seq(kw("a"), kw("b"))in a rule = two-token compound operator;slice(node)returns"a b"(with whitespace from source)
- Shared AST types only; build with
tsc - Must build BEFORE kql-lezer (kql-lezer imports types)
- KQL parser, no WASM
- Grammar sources (EDIT THESE):
src/grammar/(TypeScript DSL) - Generated (DO NOT EDIT, gitignored):
src/kql.grammar,src/parser.ts,src/parser.terms.ts - Build:
bun run build→ generate:grammar → build:parser → fix:parser → tsc - CST→AST:
src/parser/cst-to-ast/;slice(node)extracts raw source text for operator name StringOpgrammar rule: operators are rule alternatives; compoundmatches regex=seq(kw("matches"), kw("regex"))- BUG FIXED:
sort by col desc— grammar wassort | order by? list(wrong); now(sort|order) by? list; also CST-to-AST looked for non-existentSortDirection/NullsPositionnodes; now usesasc/desc/first/lasttoken names directly - Status: 110 tests passing (154 expects)
- Translates KQL AST → DuckDB SQL
- Translator:
src/translator/expressions/index.ts - Operator string from CST is raw source text (e.g.
"matches regex"with space) matches regex→regexp_matches(col, pattern)[FIXED]contains→LIKE '%val%',startswith→LIKE 'val%',endswith→LIKE '%val'has→REGEXP '\bval\b',in→IN (...),between→BETWEEN x AND ysort/order by col desc→ORDER BY col DESC[FIXED]- Status: 21 tests passing
- SolidJS + Vite + PicoCSS + CodeMirror6 + DuckDB WASM + TanStack Table
- DuckDB files in
public/; theme via DOM classes; grid truncation needsmin-width: 0 - PWA:
public/manifest.json+public/sw.js+index.html - Chrome app icon: Chrome ignores
data:URI icons in manifest. Must be actual file paths (PNG preferred). Usebun run generate-iconsto regeneratepublic/icon-192.png,public/icon-512.png;public/icon.svgfor browser favicon - Icon generation:
packages/ui/scripts/generate-icons.ts(pure TS, no native deps, usesBun.deflateSyncfor PNG encoding) - Status: Core complete (polishing)
| Task | Command |
|---|---|
| Install/link workspace | bun install |
| Build all | bun run build |
| Build pkg | cd packages/<pkg> && bun run build |
| Lint | bun run lint |
| Lint fix | bun run lint:fix |
| Test pkg | cd packages/<pkg> && bun test |
| Changeset | bun run changeset |
| UI dev | cd packages/ui && bun run dev |
| Regen UI icons | cd packages/ui && bun run generate-icons |
bun installREQUIRED on fresh clone; without it@fossiq/*workspace packages resolve to stale npm cache versions instead of local srclezer-grammar-generator/dist/index.jsis what bun actually runs (not src/); if src changes don't take effect, check if dist needs rebuild or edit dist directly- lezer-generator CLI errors on
@digit— use$[0-9]in grammar tokens seq(kw("a"), kw("b"))in StringOp rule → operator string includes whitespace between words; use.replace(/\s+/g, " ").trim()for comparison- DuckDB WASM files (
duckdb-eh.wasm,duckdb-browser-eh.worker.js) must stay inpackages/ui/public/; large files, don't accidentally delete - Template (Eta.js): whitespace-significant; use
<%- %>trim tags; cache compiled templates at module init