toj is now on the global PATH as /usr/local/bin/toj, so its scope boundary
had to stop being "the absolute path is inconvenient to type" and start
being a rule. Its repo and settings verbs operate on the workspace root; run
from inside this repo they answer about the wrong tree.
Both spellings are denied, bare and absolute, because a deny with one
spelling left open is decorative.
Co-Authored-By: Claude <noreply@anthropic.com>
No repo here scanned for committed credentials. The hook is self-contained
rather than delegating to a Makefile, because this repo has none and a hook
reaching into a sibling repo breaks the moment this one is cloned elsewhere.
Scans the outgoing range rather than full history: history carries settled
findings — test fixtures, vendored third-party code — and a gate that fails
on something unfixable gets bypassed within a week.
Setting core.hooksPath means pql init must replant its replication shims into
.githooks, which is why they are gitignored here alongside the tracked
pre-push. Same layout pql itself uses.
Co-Authored-By: Claude <noreply@anthropic.com>
Decision ids are per-vault sequences, so they collide by construction
once there is more than one vault -- and every repo now has one. A bare
D-15 here will mean this repo's D-15 the moment this repo records one.
Cross-vault references are therefore qualified: workspace D-15.
Not hypothetical: pql holds D-1 through D-31 while the workspace holds
D-1 through D-21, so every workspace id currently collides with an
unrelated pql one. A bare id is not wrong the day it is written -- it
decays into wrong as the other vault grows, and nothing flags it.
Co-Authored-By: Claude <noreply@anthropic.com>
One agent doc per repo, and it is CLAUDE.md. Written fresh rather than
reformatted. PHILOSOPHY.md linked to the old file, so that pointer moves
with it, and its standing requirement to be read before working here is
carried forward rather than lost in the rewrite.
Two claims did not survive verification. The app is published on 9999,
not the tower:8092 the old file gave, and it pointed at portainer-core
for full-stack documentation -- that repo is deprecated and must not be
used as a source of infra facts.
Establishing what is live needs a different method here: there is no
sys.modules to read, since the container holds a compiled web build
rather than source. A transitive walk of import/export/part directives
from lib/main.dart found 8 of 132 files unreachable, and five of those
are exactly what runs in production. They are conditional-import targets
-- `import 'a.dart' if (dart.library.html) 'b.dart'` -- and a walk that
takes the first string misses the branch. Since this ships as Flutter
web, the _web half is live and the _stub/_native half is dormant. The
naive reading was not merely wrong but inverted.
Of the three genuinely unreferenced files, stack_model.dart is imported
only by its own test, so the suite is green and vouches for a model the
app never uses. permission_gate.dart sits next to an unimplemented auth
redesign and is recorded as undetermined rather than dead.
Co-Authored-By: Claude <noreply@anthropic.com>
Commits a .claude/settings.json rather than leaving permissions to
per-developer local state, and initialises a pql vault for this repo's
tickets and internal decisions.
Every git deny rule appears in both the `git <verb>` and `git * <verb>`
forms. Only the second catches `git -C <path>`, and without it the whole
deny list is decorative -- it looks like a policy and stops nothing.
The allow list carries pql's absolute path alongside the bare name.
pql is installed to ~/.local/bin, which is on the login PATH but not the
one a non-interactive shell gets, so the bare-name rules match nothing on
their own and every call would prompt anyway.
.gitignore now covers .claude/settings.local.json, which is machine-local
and must never be shared. `pql init` contributed the .pql/* rules with an
exception for the changelog, which is the replication log of record and
has to be committed for tickets to travel with a clone.
Co-Authored-By: Claude <noreply@anthropic.com>
CI resolves dependencies fresh (pubspec.lock is gitignored), so the
v1.7.0 build failed when dio 5.10 introduced transformTimeout. A
default clause absorbs future enum additions on either dio version;
unknown keeps identical behavior through it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Network-migration release: default Core API and Tatlock API URLs now
point at the public https schweitz.net domains, and the decommissioned
Netdata / code-server quick links are removed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Netdata was never deployed and code-server was decommissioned on
2026-07-19; their quick links pointed at dead domains. The
portainerUrl/netdataUrl constants had no consumers (quick links
hardcode their own URLs). The Portainer quick link stays — its
portainer.schweitz.net host arrives with the port-lockdown phase.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Browser clients run on machines other than the host, and the homelab is
retiring direct LAN IP:port access (ports move to loopback behind NPM),
so the 192.168.86.149 defaults would stop working. The public domains
work from anywhere; LAN clients bypass Authentik via source-IP rules.
LAN development can still override via --dart-define.
Portainer (9000) and Netdata (19999) defaults are left unchanged: no
*.schweitz.net proxy hosts exist for those services yet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The .internal registry domain is being retired; git.schweitz.net now
serves the registry without SSO on /v2/.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Default API URLs now use LAN IPs (192.168.86.149)
- Auth interceptor skips auth when using LAN endpoints
- Production builds override with --dart-define
Development: flutter run -d chrome (no auth needed on LAN)
Production: flutter build web --dart-define=CORE_API_URL=https://api.schweitz.net🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace manual generate_version.dart script with a custom build_runner
builder that automatically generates lib/version.g.dart from pubspec.yaml
during the build process. This eliminates manual steps and ensures version
info stays in sync.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- docs/ARCHITECTURE.md - Clean Architecture patterns and conventions
- docs/API_INTEGRATION.md - Core API and Tatlock API endpoints
- docs/DEPLOYMENT.md - Docker, NPM, Portainer setup
- docs/DATAGRID.md - DataGrid component specification
- docs/THEMING.md - Material 3 theming guide
Also update seed color to teal for consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Initialize Flutter 3.38 project with all platforms
- Add build-time version generation from pubspec.yaml
- Print version to console on app startup
- Create CHANGELOG.md following Keep a Changelog format
- Update .gitignore for Flutter + generated files
- Basic app scaffold with Material 3 theming
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PHILOSOPHY.md with UI vision and principles
- Add README.md with project overview and operational details
- Add AGENTS.md with LLM agent instructions
- Add PLAN.md with implementation roadmap
- Add .gitignore for Flutter project
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>