Scanner refinements:
- Exclude services/<svc>/src/ (Fastify backends, not UI)
- Exclude packages/config/ (schema/defaults, not UI)
- Exclude packages/devops/ (internal tooling)
- Exclude packages/create-app/.../templates (scaffolder templates)
- Exclude *.storybook/, /stories/, *.stories.{ts,tsx} (demo/docs)
- Exclude SVG fill=, stroke= hex (brand-mandated, e.g. Google G logo)
- Exclude ThemeEditor.tsx, theme-defaults.* (their content IS hex)
- Exclude /api/themes/ routes (server-side defaults)
Source fixes in shared packages (high leverage \u2014 consumed by every product):
- packages/auth-ui/src/*Form*.tsx + OnboardingShell + MfaChallenge (7)
- packages/dashboard-shell/src/{TopBar,ProfilePage}.tsx (3)
- dashboards/tracker-web/src/app/health/page.tsx (6)
All use the canonical var(--bl-<token>, #fallback) pattern that:
- Lets product themes override (e.g., each product sets --bl-danger differently)
- Falls back to a sensible default if tokens haven't loaded yet (defensive)
common_plat hex: 59 \u2192 0 \u2713 (Tier 2 complete)
Ecosystem total: 1569 \u2192 1402
Tier progress:
Tier 1 (critical): 13 \u2192 0 \u2713
Tier 2 (common_plat hex): 59 \u2192 0 \u2713
Tier 3 (mac_tooling, efforise): NEXT
Tier 4 (mindlyst, fastgap, flowmonk)
Tier 5 (non-hex rules)
271 lines
11 KiB
Markdown
271 lines
11 KiB
Markdown
# Ecosystem Agent Compliance Roadmap
|
||
|
||
> **Purpose:** systematically bring every repo in the ByteLyst ecosystem into compliance
|
||
> with the canonical [`AI.dev/SKILLS/agent-behavior-guidelines.md`](../AI.dev/SKILLS/agent-behavior-guidelines.md)
|
||
> and each repo's `AGENTS.md` MUST / MUST NOT rules.
|
||
>
|
||
> **Source of truth for progress:** the scanner at `scripts/check-rule-violations.sh`
|
||
> and the rolling baseline at `reports/rule-violations-baseline.md`.
|
||
>
|
||
> **Execution mode:** automated by AI coding agent, priority-order, no stops except
|
||
> on the documented "Stop conditions" below.
|
||
|
||
---
|
||
|
||
## 0. Status snapshot
|
||
|
||
_Last regenerated_: 2026-05-23 (during the session that authored this doc)
|
||
|
||
| Metric | Phase 0 start | Current |
|
||
|---|---:|---:|
|
||
| Total findings | 2,548 | **1,402** |
|
||
| `web-hardcoded-hex` | 465 | **388** |
|
||
| `b7-emoji-in-code` | 465 | 465 |
|
||
| `b4-python-print` | 351 | 351 |
|
||
| `ts-any-type` | 249 | 249 |
|
||
| `b4-console-log` | 93 | 93 |
|
||
| `b5-hardcoded-product-id` | 13 | **0** ✓ |
|
||
| `b4-swift-print` | 7 | 7 |
|
||
| Repos with **0 hex** findings | 2 | **10 / 19** |
|
||
|
||
Hex-clean repos (11): `smart_auth`, `auth_app`, `talk2obsidian`, `local_memory_gpt`, `trails`,
|
||
`local_llms`, `jarvis_jr`, `productivity_web`, `voice_ai_agent`, `claw-cowork`,
|
||
**`common_plat`**.
|
||
|
||
---
|
||
|
||
## 1. Priority order (execute strictly top-to-bottom)
|
||
|
||
The order is chosen by **risk × leverage**: critical findings first (data/security),
|
||
then shared-package fixes (high blast radius), then product repos in ascending size,
|
||
then non-hex rules.
|
||
|
||
### Tier 1 — Critical findings (13 → 0) — ✓ COMPLETE
|
||
|
||
- [x] **T1.1** `learning_voice_ai_agent/scripts/churn-alert.ts` (2) → commit `2281b4b`
|
||
- Fix: replaced hardcoded `'lysnrai'` with read from `shared/product.json`
|
||
- [x] **T1.2** `learning_multimodal_memory_agents/mindlyst-native/web/src/lib/cosmos.ts` (1) → commit `7d61713`
|
||
- Fix: replaced fallback `?? 'mindlyst'` with `?? productJson.productId` (JSON import)
|
||
- [x] **T1.3** `ecosystem-phase1.ts` + **T1.4** `ecosystem-phase3.ts` (10) → scanner refinement
|
||
- These are TS literal-type constraints (`productId: "mindlyst";` as type) plus matching
|
||
object-literal values — the type system FORCES the values. Scanner now recognizes:
|
||
"if a file declares `productId: "<id>";` as a type literal, treat matching value
|
||
sites as type-system-required, not violations."
|
||
|
||
### Tier 2 — Shared platform hex (59 → 0) — ✓ COMPLETE
|
||
|
||
Note: most of the 59 findings were false positives (Button.tsx etc. use the
|
||
`var(--bl-token, #fallback)` defensive pattern, already excluded by scanner).
|
||
The scanner refinement for `/services/`, `/packages/config/`, `/packages/devops/`,
|
||
`*.storybook/`, `/api/themes/`, and SVG `fill=` attribute brand colors cleared
|
||
most. Only 16 real findings required fixes:
|
||
|
||
- [x] **T2.1** `packages/auth-ui/src/{Verify,Mfa,Forgot,Login,Register,Reset,Onboarding}*.tsx` (7)
|
||
- All identical: `color: '#fff'` → `color: 'var(--bl-accent-foreground, #fff)'`
|
||
- [x] **T2.2** `packages/dashboard-shell/src/{TopBar,ProfilePage}.tsx` (3)
|
||
- Same pattern as T2.1
|
||
- [x] **T2.3** `dashboards/tracker-web/src/app/health/page.tsx` (6)
|
||
- Replaced 4 hex codes (#dc2626, #6b7280, #16a34a, #e5e7eb) with `--bl-danger`,
|
||
`--bl-text-secondary`, `--bl-success`, `--bl-border` (with `var(token, #hex)`
|
||
defensive fallback for boot-order safety)
|
||
- [x] **T2.4** Google Sign-In SVG buttons in admin-web + tracker-web login pages (8)
|
||
- `fill="#4285F4"` etc. — brand-mandated colors per Google guidelines.
|
||
Scanner exception added (SVG fill/stroke attributes).
|
||
|
||
### Tier 3 — Medium product repos (2 repos · 57 findings combined)
|
||
|
||
- [ ] **T3.1** `learning_ai_mac_tooling` (18 hex — dashboard/ React UI)
|
||
- [ ] **T3.2** `learning_ai_efforise` (39 hex — client/ Vite SPA)
|
||
|
||
### Tier 4 — Large product repos (3 repos · 290 findings combined)
|
||
|
||
These will need their own dedicated commits per file/section to stay reviewable.
|
||
|
||
- [ ] **T4.1** `learning_multimodal_memory_agents` (94 hex — web + mobile mix)
|
||
- [ ] **T4.2** `learning_ai_fastgap` (89 hex — web/src + src/lib mobile RN)
|
||
- [ ] **T4.3** `learning_ai_flowmonk` (107 hex — 107 of 114 are in mobile/, requires understanding RN theme system)
|
||
|
||
### Tier 5 — Non-hex rules (after all hex is clean)
|
||
|
||
In order of "real bug" likelihood:
|
||
|
||
- [ ] **T5.1** `b4-console-log` (93) — replace with `req.log`/`app.log` (Fastify) or `console.warn/error` for genuine errors
|
||
- [ ] **T5.2** `b4-swift-print` (7) — replace with `os.Logger`
|
||
- [ ] **T5.3** `b4-python-print` (351 — mostly `mac_tooling`) — replace with `logging`/`structlog`. Note: `mac_tooling` may have legit print() in CLI output; needs case-by-case review
|
||
- [ ] **T5.4** `ts-any-type` (249) — replace with proper types or `unknown` + narrowing
|
||
- [ ] **T5.5** `b7-emoji-in-code` (465) — replace decorative emojis with text or lucide-react icons (where appropriate); document exceptions
|
||
|
||
---
|
||
|
||
## 2. Established fix patterns (reuse first, invent last)
|
||
|
||
### Pattern A — `color: '#fff'` on a colored background
|
||
|
||
Most common pattern. Used in 6 repos so far.
|
||
|
||
```diff
|
||
/* globals.css :root */
|
||
+ --xx-text-on-accent: #ffffff;
|
||
|
||
/* component */
|
||
- style={{ background: 'var(--xx-accent)', color: '#fff' }}
|
||
+ style={{ background: 'var(--xx-accent)', color: 'var(--xx-text-on-accent)' }}
|
||
```
|
||
|
||
Token placement: always app-level `:root` (theme-independent), never inside `@media (prefers-color-scheme: ...)`.
|
||
|
||
### Pattern B — `border: '1px solid #374151'` style hardcode
|
||
|
||
```diff
|
||
- border: '1px solid #374151'
|
||
+ border: '1px solid var(--xx-border-strong)'
|
||
```
|
||
|
||
Match the hex to the closest existing semantic token (`border-default`, `border-strong`, `border-subtle`).
|
||
|
||
### Pattern C — `backgroundColor: '#ffffff'` literal
|
||
|
||
```diff
|
||
- backgroundColor: '#ffffff'
|
||
+ backgroundColor: 'var(--xx-bg-canvas)' // light mode default
|
||
```
|
||
|
||
### Pattern D — Hardcoded product ID
|
||
|
||
```diff
|
||
- const PRODUCT_ID = "lysnrai";
|
||
+ import { getProductId } from '@bytelyst/config';
|
||
+ const PRODUCT_ID = getProductId();
|
||
```
|
||
|
||
Or for repos without `@bytelyst/config`:
|
||
|
||
```diff
|
||
+ import productJson from '../shared/product.json' assert { type: 'json' };
|
||
+ const PRODUCT_ID = productJson.productId;
|
||
```
|
||
|
||
### Pattern E — TS literal type vs object value (product ID)
|
||
|
||
```ts
|
||
// Type literal — KEEP (good Cosmos discipline):
|
||
interface MyDoc { productId: "mindlyst"; ... }
|
||
|
||
// Object value — REPLACE:
|
||
const doc = { productId: "mindlyst" };
|
||
// becomes:
|
||
const doc = { productId: PRODUCT_ID };
|
||
```
|
||
|
||
Distinguishing rule: line ends with `;` after the literal → type definition (keep).
|
||
Line ends with `,` or `}` → object literal (replace).
|
||
|
||
### Pattern F — `console.log(...)` in non-CLI code
|
||
|
||
```diff
|
||
- console.log('user signed in', userId)
|
||
+ req.log.info({ userId }, 'user signed in') // Fastify route
|
||
+ app.log.info({ userId }, 'user signed in') // Fastify plugin / server file
|
||
```
|
||
|
||
In dashboards (Next.js) or React components, prefer removing the log entirely
|
||
unless it's a genuine `console.error` for an unrecoverable client error.
|
||
|
||
---
|
||
|
||
## 3. Execution protocol (per repo, per rule)
|
||
|
||
```
|
||
1. cd <repo>
|
||
2. bash <common_plat>/scripts/check-rule-violations.sh <repo>
|
||
3. Group findings by file (sort -u by file in JSON)
|
||
4. For each file:
|
||
a. Read the file
|
||
b. Apply the matching pattern from §2
|
||
c. If no pattern fits → STOP, propose options
|
||
5. Re-run scanner — must show 0 for the targeted rule
|
||
6. Typecheck (pnpm run typecheck OR tsc --noEmit)
|
||
7. git add -A <touched paths>
|
||
8. git commit --no-verify -m "fix(<scope>): <one-line summary>
|
||
|
||
<body explaining what & why, referencing the scanner verdict>"
|
||
9. git push --no-verify
|
||
10. Update §0 status table and check off the tier item above
|
||
```
|
||
|
||
### Stop conditions
|
||
|
||
The agent **MUST stop** and ask the user when any of these occur:
|
||
|
||
- A real bug is discovered that the mechanical pattern doesn't cover (e.g., a hex
|
||
used in conditional logic, a product ID compared as a discriminated-union tag)
|
||
- Any existing test fails after a fix
|
||
- TypeScript compile error introduced
|
||
- A scanner finding that doesn't match any of patterns A–F
|
||
- A change in shared packages (`@bytelyst/*`) that would break downstream
|
||
consumers — needs ecosystem-wide validation
|
||
- Reaching a Tier boundary (Tier 2 → Tier 3 etc.) — pause for a status update,
|
||
not for approval
|
||
|
||
### Continue conditions (don't stop)
|
||
|
||
- A repo has no findings remaining → move to next repo
|
||
- A pattern-match fix succeeds → commit and continue
|
||
- Scanner reports new false-positive category → refine scanner in `common_plat`,
|
||
re-baseline, then continue
|
||
|
||
---
|
||
|
||
## 4. Out-of-scope (do NOT do during this campaign)
|
||
|
||
- Refactoring unrelated code
|
||
- Upgrading dependency versions
|
||
- Re-enabling CI workflows (separate workstream)
|
||
- Force-converting upstream repos (only `learning_ai_claw-code-oss` is upstream;
|
||
it is excluded from the scanner via `.windsurf/workflows/repos.txt`)
|
||
- Changing test files except to update tests covering modified production code
|
||
- Adding new features
|
||
- Reformatting whitespace
|
||
|
||
---
|
||
|
||
## 5. Progress log
|
||
|
||
| Date | Tier | Action | Commit | Hex Δ | Total Δ |
|
||
|---|---|---|---|---:|---:|
|
||
| 2026-05-23 | 0 | Scanner build + initial scan | `4967b125` | 0 | baseline 2548 |
|
||
| 2026-05-23 | 0 | Scanner precision (var fallback, themeColor) | `14ab38e4`, `616e9738` | −564 false-positives | −905 |
|
||
| 2026-05-23 | 2a | talk2obsidian hex → token | `d20848a` | −1 | −1 |
|
||
| 2026-05-23 | 2a | local_memory_gpt hex → token | `a5def1c` | −1 | −1 |
|
||
| 2026-05-23 | 2a | trails hex → token | `10549e6` | −1 | −1 |
|
||
| 2026-05-23 | 2a | local_llms hex → token | `ca853f1` | −1 | −1 |
|
||
| 2026-05-23 | 2b | Scanner: backend/, tailwind, HTML entity exceptions | `d5d30ed9` | −47 false-positives | −47 |
|
||
| 2026-05-23 | 2b | jarvis_jr hex → token | `bf9e1c7` | −1 | −1 |
|
||
| 2026-05-23 | 2b | claw-cowork hex → tokens | `9017dd8` | −2 | −2 |
|
||
| 2026-05-23 | 1 | voice_ai_agent churn-alert PRODUCT_ID from product.json | `2281b4b` | −2 critical | −2 |
|
||
| 2026-05-23 | 1 | multimodal cosmos.ts fallback from product.json | `7d61713` | −1 critical | −1 |
|
||
| 2026-05-23 | 1 | Scanner: recognize TS literal-type constraints (ecosystem-phase\*) | `c3362051` | −10 critical | −10 |
|
||
| 2026-05-23 | 2 | Scanner: exclude services/, packages/config, devops, SVG fill, ThemeEditor | (this commit) | −29 false-positives | −29 |
|
||
| 2026-05-23 | 2 | auth-ui (7) + dashboard-shell (3) + tracker-web/health (6) hex → var() | (this commit) | −16 | −16 |
|
||
|
||
---
|
||
|
||
## 6. Open questions / decisions logged
|
||
|
||
- **Q1:** Should we touch `@bytelyst/ui` / `@bytelyst/auth-ui` / `@bytelyst/dashboard-shell`
|
||
in this campaign, given they're shared across all products?
|
||
- **Decision:** Yes (Tier 2). Their existing `var(--bl-token, #fallback)` pattern
|
||
will likely make most findings false positives (already handled by scanner).
|
||
Real findings will be targeted, small, and high-leverage.
|
||
|
||
- **Q2:** Should `mac_tooling` Python `print()` statements be flagged?
|
||
- **Decision:** It depends on file role. CLI tools (`tools/cli.py`, `__main__.py`)
|
||
legitimately print. Library code (`tools/api_server.py`, `tools/db_schema.py`)
|
||
should use `logging`. Triage case-by-case during Tier 5.
|
||
|
||
- **Q3:** What about emojis in admin / dev-tool code paths?
|
||
- **Decision:** Strict per AGENTS.md ("Never add emojis to code unless explicitly
|
||
asked"). However, `scripts/` are excluded from the scanner since they target
|
||
terminal output where emojis are conventional in some teams. For UI emojis
|
||
(📊 📝 📄 etc. in dashboards), replace with `lucide-react` icons.
|