fix: bring the dev instance back up, and make the checks that prove it - #48
Merged
Conversation
Actionable items move to the board; docs/design-notes.md keeps the reasoning - decisions, rejected approaches, unresolved tensions.
stacktests preflight checks versions, uv.lock, ruff and unit tests in one command - the same checks a release gate needs, so local and CI cannot drift. stacktests help now exists and states which commands are safe to run without a human; before, --help crashed on Python 3.9. Also guards against unpinned container images, which is how Paperless rolled from 2.x to 3.0.2 unattended and broke document filing.
Tests assumed the realm was always test.local. When a container carried a different one, every bot login failed with a bare 403 and no clue why - which is how the dev instance lost all four of its bots. The rig and the demo are now one Simpsons instance on a single realm, read from stack.toml, so the two can no longer disagree.
`stacktests ai [local|mock|external]` flips the rig's model endpoint in one command, so testing against a real model no longer means waiting for the ai stacklet to install and load weights. local is the mode to reach for: a self-hosted endpoint gives real answers at no cost per call, and only costs a little speed. mock stays available for tests that assert on exact model output, but a green mock run proves the wiring, not the behaviour. Endpoints, keys, and model names are read from the environment rather than committed, so no one's infrastructure ends up in the repo.
`stack status` tells you a stacklet is failing. `stack doctor` tells you why, and prints the command that fixes it. It catches the failure that took this instance's bots down: a container keeps the environment it was created with, so editing stack.toml changes nothing until the container is recreated, and every login fails against config that looks correct on disk. Doctor also names exited containers with their exit code and age, and flags a configured AI endpoint that isn't answering. The checks are deliberately generic. Nothing here knows what Matrix is, so the same rules catch the same class of problem for any stacklet. Findings print setting names only, never values, since this environment carries passwords and tokens. Exits non-zero when it finds errors, so scripts can gate on it. Also scope preflight's unit run to `make test-unit`. Re-spelling the pytest arguments had already dropped its --ignore, pulling Docker tests into what is meant to be the offline gate.
When COMPOSE_PROFILES excludes every service in a compose file, docker compose exits 1 with "no service selected". That is an empty selection, not a service that failed to start, but the CLI read any non-zero as "Failed to start services" and refused to write the setup marker. The ai stacklet is the case that surfaced it: STACK_AI_NO_VOICE=1 clears the profile and its only container sits behind "voice", so the documented local-dev opt-out could never complete setup, which in turn blocked everything that requires the ai stacklet.
The command died with "No module named 'frontmatter'" on any host that had not run pip install. It read the vault through loaders that imported the third-party python-frontmatter package, which ships only in the test extra, so the suite stayed green while the command was broken for everyone. stack memory correspondents had the same defect. Both loaders now use lib/stack/frontmatter.py, the stdlib-only parser already built for exactly this, keeping the CLI's zero-pip-deps promise. List fields go through _fm_list so a single value written where a list belongs can no longer iterate into one entry per character. The shipped correspondents seed taught inline "[a, b]" list syntax, which the vault format spec excludes and the parser does not read. Seed and test fixture now use block lists.
The agent shipped with memory_search and memory_person registered and both broken. Four faults, none visible to a unit test: - memory person was missing from the core API allowlist, so every call returned "'memory person' is not allowed" - memory_search passed --backend mem0, a flag that never existed, so every search returned a usage error and the agent looped retrying - stack memory person read the memory source clone, but profiles are generated into the brain projection and purged out of source, so it answered "no profile" for every household member who had one - the agent mounted the source clone at vault/, so its file tools could not see a profile either and it told Homer "there is no vault/homer/about.md" when the page existed Asking Stacky about a family member now cites vault/homer/about.md, the same path stack memory person returns.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the dev instance back up, and fixes what running it exposed.
The agent's vault tools were registered and non-functional. Both shipped that way with a green suite, because all four faults live in components the tools never see:
memory personwas missing from the core API allowlist,memory_tool.pypassed a--backend mem0flag that never existed,stack memory personread the source clone when profiles are generated into the brain projection, and the agent mounted that same source clone atvault/(so it told Homer "there is novault/homer/about.md" about a page that existed).Two defects broke famstack on a clean install.
stack memory personandcorrespondentsdied withNo module named 'frontmatter'on any host that never ranpip install- the loaders used a third-party package that ships only in thetestextra, so the tests carried a dependency users don't have. And a stacklet whose containers are all optional could never finish setup:docker composeexits 1 withno service selected, which is an empty selection, not a failure.Also:
stack doctor(diagnose an instance, print the fix),tools/branch-status(retired 46 stale branches), agent vault tools wired intositecustomize.py, and a stacker-bot credential fix - two paths created the account with two different stored passwords, so the bot could never log in.Notes for review
about.mdpath the CLI returns.vault/is the agent's whole picture of the family. Tool descriptions don't steer it.c57af19came from a Gemini session; its test needed two follow-up corrections.