fix: two defects that broke famstack on a clean install - #49
Merged
Conversation
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.
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
Two unrelated defects found while bringing the memory and agent stacklets up on the dev rig. Neither is Paperless work; they landed on this branch because they blocked getting there. Each is a standalone commit.
stack memory personcould not run on a normal install. It died withNo module named 'frontmatter'on any host that had not runpip install. The vault loaders imported the third-partypython-frontmatterpackage, which ships only in thetestextra.stack memory correspondentshad the same defect.The reason it shipped is worth recording: the test environment installs a dependency the production host does not, so the suite stayed green while the command was broken for every user.
tests/stacklets/test_memory_host_stdlib.pycloses that hole by blocking the module insys.modules, making a machine that never ranpip installthe thing under test. All four of its tests fail against the old code.Both loaders now use
lib/stack/frontmatter.py, the stdlib-only parser already built for exactly this, keeping the CLI's documented zero-pip-deps promise. List fields go through_fm_listso a single value written where a list belongs can no longer iterate into one entry per character.That surfaced a third thing: the shipped correspondents seed teaches 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. Whether the parser should instead accept flow syntax is a real design question and is deliberately not decided here.A stacklet whose containers are all optional could never finish setup. When
COMPOSE_PROFILESexcludes every service,docker composeexits 1 withno service selected. That is an empty selection, not a failure to start, but the CLI read any non-zero as "Failed to start services" and withheld the setup marker. The ai stacklet is the case that surfaced it:STACK_AI_NO_VOICE=1clears the profile and its only container sits behindvoice, so the documented local-dev opt-out could never complete, which in turn blocked everything that requires ai.The exit code and stderr text pinned in those tests came from a real
docker compose uprun rather than from reading source, so they assert compose's actual contract.