fix(services): drain the dev-services awaiting-input queue - #107
Merged
Conversation
…existence The existing pair guards on existence alone. A role that already exists without CREATEDB or LOGIN was left exactly as found: the existence query returns 1, the creation is skipped, the run reports zero changed tasks, and REQ-A1.4 is unmet. A green run with an unmet requirement is the failure shape worth two extra tasks. It was also invisible to the verification this bundle planned. test-spec.md pins REQ-C1.2 to Task 6's idempotency re-run, and that second pass runs against a role this file created one task earlier, which by construction already has both attributes. On a fresh host nothing is wrong; the case is a host where someone made a same-named role by hand, which is precisely REQ-C1.2's "already provisioned" condition. This is what community.postgresql's postgresql_user does internally and the reason it is idempotent in the convergent sense rather than the create-once one. D-6 keeps that collection out, so the behaviour is spelled out here instead. Placed after the creation so it reads post-create state; ordered the other way it would predict an ALTER on every fresh host. Grants nothing beyond what the creation already asks for: same two attributes, no superuser, no role membership. Verified against the running server rather than by reading. The query returns `1` for an account holding both attributes and empty for pg_read_all_data, a predefined role with no LOGIN, so the guard is shown to discriminate in both directions rather than merely to pass. Both exits are 0, which is why the `when:` compares stdout and not rc. Claude-Session: https://claude.ai/code/session_01F8oKrXASMQSXMVjSvuJpn9
specs/dev-services REQ-B1.5 is pinned `[test]` in test-spec.md, which spec-format defines as "runs in the repo's CI". Task 5 wrote the script and mutation-tested every assertion, but wiring it edits this file, which is a hard-disqualifier zone and something that task's own REQs did not call for, so it recorded the step instead of applying it. The pin has been inaccurate since: the script existed and nothing ran it. The lint job rather than services (linux): the scan reads tracked files and needs no provisioned service, and lint already gates the whole matrix, so a stale declaration now fails before anything spends a runner. Additions only, so REQ-E1.4 is untouched. Its three dependencies are already present in that job and were checked rather than assumed: git from checkout, python3 from setup-python, and PyYAML transitively from the `pip3 install ansible` step (the script exits early on `import yaml`). The job runs on macos-latest, so the script was also read for GNU-isms — the sed calls are portable and the scanning is done in python3. Claude-Session: https://claude.ai/code/session_01F8oKrXASMQSXMVjSvuJpn9
Four of the five entries no longer describe anything open, and a queue
that lists resolved work is the same defect this bundle's Task 5 existed
to remove: a tracked statement that stopped being true.
Task 2 Entirely about CI creating no workflow run, on the exhausted-
macOS-minutes hypothesis. That was withdrawn — the outage was
runner scarcity and cleared on its own. Task 3's entry already
recorded the correction.
Task 3 Both halves resolved. The runtime clause is now verified in CI
rather than pending on the host: the services (linux) job runs
scripts/postgresql-access-test.sh and passes on main. The
ALTER ROLE finding it recorded is applied in this branch.
Task 5 The REQ-B1.5 [test] wiring it recorded is applied in this
branch, so the operator action it asks for is done.
Task 6 Asks for a re-read of `gh pr checks 103` once macOS capacity
frees. #103 is merged. The osx and upgrade jobs are still red,
but for the standing 30-minute Brewfile timeout that
reproduces on main and has its own observation entry, not for
anything in that task.
Task 1 stays: it needs ~/.config/dotfiles/private-identifiers, which is
machine-local by design and cannot be supplied from here.
spec-validate passes (0 errors, 0 warnings) on the trimmed bundle.
Claude-Session: https://claude.ai/code/session_01F8oKrXASMQSXMVjSvuJpn9
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.
Drains the
specs/dev-servicesAwaiting-input queue, applying the two fixesthat were recorded rather than applied and clearing the entries that no longer
describe anything open. Three commits, each revertable on its own.
1.
fix(services)— converge the role's attributes, not just its existenceThe existing pair guards on existence alone, so a role that already exists
without
CREATEDBorLOGINwas left as found: the existence query returns1, creation is skipped, the run reports zero changed tasks, and REQ-A1.4 is
unmet. A green run with an unmet requirement.
It is also invisible to the verification this bundle planned.
test-spec.mdpins REQ-C1.2 to Task 6's idempotency re-run, and that second pass runs against
a role this file created one task earlier, which by construction already has
both attributes. The uncovered case is a host where someone made a same-named
role by hand — precisely REQ-C1.2's "already provisioned" condition.
This is what
community.postgresql'spostgresql_userdoes internally, and whyit is idempotent in the convergent sense rather than the create-once one. D-6
keeps that collection out, so the behaviour is spelled out here.
Verified against the running server, in both directions:
rolname1pg_read_all_data(predefined, no LOGIN)So the guard is shown to discriminate, not merely to pass. Both exits are 0,
which is why the
when:compares stdout rather than rc.Grants nothing beyond what the creation already asks for: same two attributes,
no superuser, no role membership. Placed after the creation so it reads
post-create state; the other order would predict an ALTER on every fresh host.
2.
feat(ci)— run the stale-declaration scan inlintREQ-B1.5 is pinned
[test], which spec-format defines as "runs in the repo'sCI". Task 5 wrote and mutation-tested the script but could not wire it: that
edits
.github/workflows/test.yml, a hard-disqualifier zone its own REQs nevercalled for. So the pin has been inaccurate — the script existed and nothing ran
it.
lintrather thanservices (linux): the scan reads tracked files and needs noprovisioned service, and
lintalready gates the whole matrix, so a staledeclaration now fails before anything spends a runner. Additions only, so
REQ-E1.4 is untouched.
Its three dependencies were checked rather than assumed:
gitfrom checkout,python3from setup-python, and PyYAML transitively frompip3 install ansible(the script exits early onimport yaml). The job runs onmacos-latest, so the script was also read for GNU-isms — thesedcalls areportable and the scanning happens in python3. It passes locally on this branch.
3.
docs(spec)— clear the resolved entriesFour of five entries no longer describe anything open, and a queue listing
resolved work is the same defect Task 5 existed to remove: a tracked statement
that stopped being true.
runner scarcity and cleared on its own.
(
services (linux)runspostgresql-access-test.shand passes onmain);the ALTER ROLE finding is applied in commit 1.
[test]wiring it recorded is applied in commit 2.gh pr checks 103, which is merged. Theosx/upgradereds are the standing 30-minute Brewfile timeout thatreproduces on
mainand has its own observation entry.Task 1 stays open. It needs
~/.config/dotfiles/private-identifiers, whichis machine-local by design and cannot be supplied from a PR.
spec-validatepasses (0 errors, 0 warnings) on the trimmed bundle.Not in this PR
~/.my.cnfwas present on the Linux host — a symlink dated Jul 24, predatingthe platform split — which fails Task 7's fourth Done-when clause. The Darwin
guard stops it being recreated but nothing removed the existing one. Removed by
hand on the host rather than declared absent in the role, by explicit choice;
worth knowing that another host carrying the same leftover would fail the clause
with no guard to catch it.
Verification
yamllint,gitleaks,syntax-check,ansible-lintpass via pre-commit onevery commit.
spec-validate.shandstale-declarations-test.shboth pass.