a6d655048390d3b09ca76d121b881023472d8099
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a6d6550483 |
fix(ui): walk the eleven dangling-style reports — two were real
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 19s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 57s
CI & Build / Build & push image (push) Successful in 45s
#2444. Each needed reading rather than a batch fix, and the split was 2 real losses, 4 false reports, 5 wrappers that are bare on purpose. REAL: .system-card was a flex row, and every child still says so — .system-swatch and .system-actions are flex-shrink: 0, .system-body and .system-form--inline are flex: 1. align-items: flex-start is why the swatch carries margin-top: 0.3rem: nudged onto the first line of text. .systems-list no rule AT ALL, so the systems list rendered with browser bullets and indent. Invisible to the check — see below. .graph-embed the panel is a flex column whose header is flex-shrink: 0, so this is the item that takes the remaining height. Without it the `height: 100%` on the line below resolves against auto and does nothing, which left the comment above it specifying a rule that could not work. FALSE REPORTS, and the checker was wrong rather than the code: `.pane.empty` and `td.num` are base rules for the element that carries those classes — the check read any compound with more than a lone class as a modifier. It now records a compound's whole class SET and clears an element carrying all of them, which is exact: recording the classes individually would have cleared `.pane` everywhere on the strength of a rule that only applies alongside `.empty`. Four reports gone, and a check with false reports is one that gets skimmed. BARE ON PURPOSE — .rb, .topic-group, .new-topic, .sub-list, .dash-head, and both .detail-row rows. Each namespaces descendant rules and assumes nothing about layout, which is the tell that separates them from a deleted base. All seven now carry a comment saying so, so the next reader doesn't re-litigate them and a NEW entry in the report means something actually changed. Also recorded in the script: it cannot see a class with no rule anywhere, since that is indistinguishable from a semantic-only hook. `.systems-list` was found by reading the file beside a class that WAS half-styled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs |
||
|
|
bd60d679d9 |
refactor(theme): remove 184 var() fallbacks — every one was unreachable
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 16s
CI & Build / integration (push) Successful in 23s
CI & Build / TypeScript typecheck (push) Successful in 25s
CI & Build / Python tests (push) Successful in 57s
CI & Build / Build & push image (push) Successful in 43s
#2277 counted ~150 "raw colour literals bypassing the tokens". Measuring them told a different story: 184 sat in `var(--token, #fallback)` position, and a check against theme.css shows every one of those tokens IS declared. So the fallbacks could not render. Not drift — vestigial. They were also not this palette. The most common were Tailwind and Flat-UI defaults — #6366f1 indigo, #22c55e green, #f59e0b amber, #3b82f6 blue, #e74c3c and #27ae60 — a second, unsanctioned colour scheme sitting in the codebase looking like the app's colours to anyone reading it. Removing them is not tidying. #2319's lesson is that a fallback is WORSE than a missing token: a missing token renders as nothing and someone eventually notices, while a fallback renders something plausible forever. These 184 were one token rename away from silently repainting the app in Tailwind. The design token check would catch the rename — but the fallback is precisely the thing that would make it invisible if the check were ever bypassed. Literal count 152 -> 45, which matters beyond the number: a report that is mostly unreachable noise is one people stop reading, and then it stops working while still passing. What remains should be genuinely worth looking at. Done with a paren-aware transform, not a regex — `var(--x, rgba(0,0,0,.5))` nests parens and `[^)]+` would cut at the first one and leave `))` behind. Verified after: every changed line is a fallback strip and nothing else, and every var() reference still resolves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs |
||
|
|
7861607fb8 |
feat(rules): project rule + topic suppressions
Lets a project mute individual rules or whole topics from rulebooks it subscribes to, without unsubscribing the rulebook. Two new association tables (migration 0060), 4 MCP tools (suppress/unsuppress × rule/topic), 4 REST endpoints, and an inline "× skip" affordance plus collapsed "Suppressed (N)" section in the project's Rules tab. get_applicable_rules now emits suppressed_rules and suppressed_topics (detail objects with rulebook/topic context, not just IDs) so the UI can render the suppressed list without a follow-up lookup. The main rules projection grew topic_id and rulebook_id columns for the per-row suppress affordance. Project deletion cascades the suppression rows via hard DELETE — they are pure associations with no soft-delete column, and restoring a deleted project should start fresh, not inherit stale mutes. Project-scoped rules (Rule.project_id) are deliberately not suppressible — delete them with delete_rule instead. Implements plan-task #187. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
43a860c3ac |
feat(rules): project-scoped rules (S3)
Rules can now belong to either a rulebook topic OR a single project,
enforced by a CHECK constraint (exactly-one of topic_id/project_id).
Adds the create_project_rule MCP tool + REST endpoint, surfaces
project-scoped rules in get_project/get_task/start_planning under a
new project_rules field, and adds a project Rules tab section with an
inline create form so the operator can author project rules from the
UI without rulebook ceremony.
- migration 0059: rules.project_id (FK projects ON DELETE CASCADE),
topic_id now nullable, CHECK ck_rule_topic_xor_project, index on
project_id
- model: Rule gains project_id; to_dict exposes it
- service: create_project_rule with project-ownership guard; list_rules
with project_id filter UNIONs subscription-derived + project-scoped;
get_applicable_rules adds a project_rules field; get_rule / update_rule
/ delete_rule fetch via a shared _fetch_owned_rule that handles both
rulebook and project ownership paths
- trash: project delete cascades to project-scoped rules
- MCP: create_project_rule tool registered; _INSTRUCTIONS mentions both
create_rule and create_project_rule paths
- REST: POST /api/projects/<id>/rules (statement required, title derived
if omitted)
- frontend: Rule type gains nullable topic_id + project_id; createProjectRule
client; ProjectRulesTab.vue gains a "Project rules" section with inline
create form and per-rule expand/delete
- tests: register count → 18; create_project_rule unit tests (required
fields, title derivation, explicit-title pass-through); applicable_rules
shape tests now include project_rules; trash cascade test updated to
expect 5 executions
S1+S2 (always_on flag + Scribe-first prompt) shipped in
|
||
|
|
9658e9a35c | feat(rulebook): Project Rules tab — applicable rules + subscription chips |