Skip to content

feat(isolation): add personal-kit template for the scope-layers pattern - #442

Merged
wz-gsa merged 2 commits into
mainfrom
feat/personal-kit-template
Oct 12, 2026
Merged

wz-gsa merged 2 commits into
mainfrom
feat/personal-kit-template

Conversation

@basiliskus

@basiliskus basiliskus commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the personal-kit template for the scope-layers pattern: a copy-and-rename hybrid/v1 mixin for the personal layer, stacked last in ACQ_EXTRA_KITS on top of the global kits and a team kit.
It ships a shell drop-in (acq v4's ~/.profile sources ~/.rc.d in bash login shells, so the kit only delivers it), a git preference, an OpenCode TUI theme through OPENCODE_TUI_CONFIG, and a scripts/verify that asserts the three-layer stack.
Third of three stacked PRs for #421: #476 (examples/ container), #441 (pattern doc and team-kit template), then this one.

Reviewer ask: is the shell guidance right? acq v4.0.0+ sources ~/.rc.d/*.sh from ~/.profile in every bash login shell, scripted bash -lc included, so the template adds no loop of its own. Drop-ins guard interactive-only lines themselves, and the commented exec zsh drop-in guards on $-, a terminal, BASH_EXECUTION_STRING, ZSH_VERSION, and a handoff marker. Also: is the commented Nix tool-install step an acceptable exception to "tools belong in the image" (ADR 0005 records it)?

Eligibility & Accountability

  • I am a federal employee or contractor (PRs merge with @GSA-TTS/agentic-coding-team code-owner approval; eligibility is attested here, not authenticated). Anyone may open issues without this.
  • I understand this change and can explain it in my own words — I am the author of record and accountable for it.
  • By opening this PR, I attest I have the right to release this work under the repository's CC0-1.0 dedication.

AI Assistance Disclosure

  • AI tools were used in this contribution.
  • I verified all AI-generated content: no fabricated/hallucinated APIs, dependencies, citations, or placeholder content; any AI-suggested dependency was confirmed to exist.
  • Any inherited/reused third-party material retains its original license and is identified (not represented as public domain).

Type of Change

  • New tool/editor integration (integrations/)
  • Documentation update

Motivation

The team-kit template covers the layer a team owns. The personal layer on top has its own recurring mistakes: shipping a whole ~/.bashrc or ~/.gitconfig that clobbers the image's, an exec zsh drop-in that swallows scripted runs, binary terminfo payloads, and personal variables that silently shadow the team's. This template is a validated starting point that avoids them.

What lands:

  • acq-kits/examples/personal-kit/: one live, harmless value per extension point (egress example.net, the ~/.rc.d drop-in and tui.jsonc, one git alias, OPENCODE_TUI_CONFIG), commented examples for a ~/.zshrc loop, terminfo compiled with tic, an include.path gitconfig, and Nix-installed personal tools; README, TROUBLESHOOTING, scripts/verify. Teammates apply it through the team kit's env.sh (PERSONAL_KITS).
  • docs/scope-layers.md: the personal-layer rows point at the template, the exec zsh guard is spelled out, and "Neither" names the one personal-tool exception.
  • ADR 0005 and acq-kits/README.md: the template is listed, and the commented Nix step is recorded as a deliberate exception.

Testing

  • Ran make validate locally (all checks pass)
  • Ran make test (if applicable): 448 passed, including scripts/tests/test_kit_rc_d_wiring.py, which fails if any kit or template wires ~/.rc.d into a bash startup file and runs the commented zsh step's detection pattern through the real grep -E
  • Tested with at least one real scenario: examples/personal-kit/scripts/verify on msb 0.7.7 with acq v4.0.1: 19 passed, 0 failed, 1 skipped (the empty PERSONAL section). It stacks the team-kit template and this template on the pinned built-in bundle and asserts that the global and team layers survive, each live value landed, the drop-in is sourced exactly once by a bash login shell, a scripted bash -lc still runs its command, and both kits' env vars, files, and egress hosts coexist against a denied control host. Not re-run on sbx for this revision (the host's sbx session needed sbx login).
  • Examples are concrete and realistic
  • Commit messages follow Conventional Commits format

Also run: validate-kits.py --strict (All 10 acq-kits + 2 template(s) valid.), acq kit validate on the template, make generate-check, markdownlint.

Safety Checklist

  • No secrets, API keys, tokens, or passwords included
  • No PII (names, emails, SSNs, addresses)
  • No CUI (Controlled Unclassified Information)
  • No internal URLs, hostnames, or system paths
  • No customer data or proprietary information
  • Pattern defines prohibited_content in output contract (if applicable): not applicable, no SKILL.md pattern

Quality Checklist

  • Plain language used (Grade 10 or below preferred)
  • Examples included
  • Prerequisites clearly stated

Validation Results

make validate
✓ All validators passed

Related Issues

Relates to #421 (the personal-kit template)
Depends on #441
Relates to GSA-TTS/agentic-coding-quickstart#482 (acq's ~/.rc.d login hook, which the template relies on)

@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch from 24ddfed to e742469 Compare September 25, 2026 22:43
@basiliskus
basiliskus added this pull request to stack #443 September 25, 2026 22:44
@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch 6 times, most recently from 4a86b4e to b3a91f6 Compare September 28, 2026 15:20
@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch 2 times, most recently from 3169aee to a1822c3 Compare September 28, 2026 20:47

@mogul mogul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address now

  • Blocking: integrations/isolation/acq-kits/examples/personal-kit/spec.yaml:88 uses grep -Eqs '^[^#]*\\\\.rc\\\\.d' "$HOME/.bashrc" to detect whether a lower layer has already wired ~/.rc.d. In ERE, the doubled backslashes make this look for literal backslashes before the characters around rc, so it does not match a normal existing loop such as case $- in *i*) for f in "$HOME"/.rc.d/*.sh; do .... That means the personal kit will append its own loop even when a team kit already wired one, so drop-ins can be sourced twice despite the docs/spec saying the personal kit skips lower-layer loops. The commented zsh example at integrations/isolation/acq-kits/examples/personal-kit/spec.yaml:108 has the same pattern and should be corrected too.
  • Blocking: integrations/isolation/acq-kits/examples/personal-kit/scripts/verify:220 repeats the same over-escaped detection pattern when deciding whether another layer wired the loop. If this template is stacked on a team kit with a normal ~/.rc.d loop and this kit did not add its marker, the verifier reports none instead of other, so it does not validate the documented skip behavior reliably. Please use a single escaped dot in the guest-side grep pattern, e.g. ^[^#]*\\.rc\\.d as the actual script text passed to grep -E.

Track later

  • Consider adding a tiny static regression test for the rc-loop detection pattern, because this is easy to over-escape across YAML, shell, and nested acq exec quoting layers.
  • The live scripts/verify still depends on a sandbox-capable host plus network behavior; CI covers static validation, but not the end-to-end stack.

Checks run

  • Confirmed local HEAD matches GitHub PR head SHA a1822c3c3ea6cbd6d21f8d52d5e33d6a157f9ec1.
  • Reviewed PR timeline/comments/reviews and diff with gh pr view, gh api .../pulls/442/reviews, gh api .../issues/442/timeline --paginate, and gh pr diff.
  • /tmp/opencode/pr442-venv/bin/python scripts/validate_repo.py passed.
  • /tmp/opencode/pr442-venv/bin/python scripts/generate_index.py --check passed.
  • /tmp/opencode/pr442-venv/bin/python integrations/isolation/acq-kits/validate-kits.py --strict passed.
  • /tmp/opencode/pr442-venv/bin/python scripts/scan_unsafe_shell.py integrations/isolation/acq-kits/examples/personal-kit passed.
  • shellcheck -S warning integrations/isolation/acq-kits/examples/personal-kit/scripts/verify integrations/isolation/acq-kits/examples/personal-kit/files/home/.rc.d/50-example.sh passed.
  • bash -n integrations/isolation/acq-kits/examples/personal-kit/scripts/verify && git diff --check passed.
  • Reproduced the grep issue locally: the intended single-backslash ERE matches .rc.d, while the current doubled-backslash ERE misses it.

@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch 2 times, most recently from 4d38a5b to dfec5b5 Compare October 7, 2026 05:20
@basiliskus
basiliskus marked this pull request as ready for review October 7, 2026 05:21
@basiliskus
basiliskus requested a review from a team as a code owner October 7, 2026 05:21
@basiliskus basiliskus self-assigned this Oct 7, 2026
@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch 2 times, most recently from 8c14645 to 42d1c47 Compare October 8, 2026 23:06

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-assisted review (OpenCode), advisory — needs a human to confirm before it drives a change. Reviewed head 42d1c47d, stacked on patterns#441 at 7e4c2031.

The two blockers from mogul's Oct 1 review are fixed. The rc-loop regex now carries the correct single escaped dots through both quoting layers, and the new 11-case regression test executes the real grep -E against bash/zsh loops, comments, and a wildcard lookalike. shellcheck and bash -n are clean. I also exercised the commented zsh-handoff guard under real Bash 3.2 modes; it behaves as documented:

bash -lc                         -> command runs, no handoff
bash -ic without a TTY           -> command runs, no handoff
bash -ic with a TTY              -> command runs, no handoff (BASH_EXECUTION_STRING)
plain interactive bash with TTY  -> hands off to zsh
plain interactive + handoff mark -> stays bash

One new blocker remains because the quickstart contract changed after this stack was authored.

Blocker — quickstart v4.0.0 already owns the neutral ~/.rc.d bridge; this template now sources every drop-in twice on MSB login

The PR's central premise is now stale. docs/scope-layers.md:211 says:

Neither the image nor the global layer sources ~/.rc.d, so one kit must wire the loop

and spec.yaml:81-95 appends an interactive loop to ~/.bashrc when .bashrc itself does not mention .rc.d.

But GSA-TTS/agentic-coding-quickstart#482 is closed/completed and shipped in quickstart v4.0.0 through GSA-TTS/agentic-coding-quickstart#474. Current acq now owns a backend-neutral bridge on both backends:

  • common.sh:1180-1200 emits acq_login_profile_rc_block, which directly sources every readable ~/.rc.d/*.sh in C-collation order.
  • msb.sh:3789-3852 writes .profile with both:
    1. . "$HOME/.bashrc"
    2. the direct rc.d block immediately after it.
  • sbx.sh:650-704 writes the same direct rc.d block into .profile.
  • docs/CONCEPTS.md:314-372 documents the shipped contract and explicitly says old team-kit .bashrc append steps should be dropped once the built-in bridge exists.

The personal template only searches .bashrc, so it does not see acq's .profile bridge and appends its own loop. On MSB login, acq then sources .bashrc (first copy) and immediately sources .rc.d itself (second copy).

I reproduced the actual startup chain locally using the current origin/main acq_login_profile_rc_block plus this PR's .bashrc loop and a drop-in that increments a counter:

$ HOME=<fixture> bash --rcfile <generated-current-msb-profile> -ic 'echo RC_COUNT=$RC_COUNT'
RC_COUNT=2

This is exactly the outcome the PR's docs say must not happen: aliases may be harmless, but PATH edits, hooks, shell options, prompt functions, tool initialization, and the commented exec zsh handoff can all have non-idempotent behavior. It also means the new regex test proves the obsolete append-if-absent mechanism rather than the current acq integration.

Fix direction

The template should consume the v4.0.0 neutral bridge rather than install a second one:

  1. Remove the live startup command that appends the bash .rc.d loop.
  2. Update docs/scope-layers.md, the personal README, troubleshooting, and ADR 0005 to state that current acq owns the bash login bridge on both backends. The template only delivers snippets.
  3. Change the verifier from bash -ic / inspecting its own marker to the real supported contract: a login bash invocation (bash -lic ...) sees the drop-in through acq's .profile bridge, while scripted bash -lc and command-string bash -ic do not get hijacked by the optional exec zsh drop-in.
  4. Retain zsh-native wiring as a documented optional step where needed: quickstart's current contract says bash is built-in, while zsh-capable images must wire the same directory from native zsh startup files.
  5. Replace the current regex regression test with one that prevents the duplicate bridge from returning — e.g. assert the personal template has no active .bashrc loop command and that docs point to the acq-owned bridge. The old over-escaping test no longer protects a live mechanism after this change.

If backward compatibility with pre-v4 acq is required, make that an explicit versioned compatibility path rather than unconditional .bashrc mutation; as written the template targets acq v4.0.1 in its own test record, so the built-in bridge is available.

Reviewer ask: Nix personal-tool exception

The exception is acceptably bounded as documentation, not live config: the entire step is commented; only personal, not team-wide, tools qualify; it requires an image that already ships Nix; it pins the image's exact NIXPKGS_REV; runs at startup rather than install; checks the binary name separately for package/binary mismatches; treats failure as non-fatal; and registers dependent git config only when the tool is present. ADR 0005 records the exception, so it is not an undocumented erosion of "toolchains in the image."

One operational cost remains by design: nix profile install can still make every startup slow or noisy if the binary name/pin is wrong, but the comments call out the package-vs-binary trap and the step is opt-in. No finding on this part.

Checks

  • test_personal_kit_rc_loop_pattern.py: 11/11 pass.
  • shellcheck --severity=warning on scripts/verify and 50-example.sh: clean.
  • bash -n scripts/verify: clean.
  • Strict kit validator: all 10 kits + 2 templates valid.
  • Repo validators: pass.
  • Nested verifier quoting reproduced locally: personal guarded loop -> n; lower-layer loop -> other; comment/lookalike -> none; unguarded personal marker -> y.
  • No existing issue duplicates this exact conflict. quickstart#482 is the completed dependency whose landing created it; patterns#421 is the parent template proposal. This fix belongs in the PR, not a new issue.

Unverified: no live sandbox here. The reported 18-pass MSB run predates or does not reflect the current duplicate-bridge integration; I did not rerun it. SBX was not live-tested by the author for this revision either.

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocker — current acq already owns the backend-neutral ~/.rc.d login bridge, so this template sources every drop-in twice. The two regex findings from the prior review are fixed at head 42d1c47da; this is a separate cross-repo integration defect.

Quickstart main now defines acq_login_profile_rc_block() in acq.backends/common.sh:1180-1201 as the single shared bridge for both backends. MSB writes .profile with this sequence (msb.sh:3843-3853): source .bashrc, then execute that bridge, which sources every readable ~/.rc.d/*.sh. SBX installs the same bytes through _acq_sbx_ensure_rc_bridge (sbx.sh:651-692).

This template’s startup command checks only $HOME/.bashrc (spec.yaml:88), so it cannot see the existing bridge in .profile; it appends its own .bashrc loop. On the supported MSB login path the resulting order is: .profile sources .bashrc → the personal-kit loop sources each drop-in once → control returns to .profile → acq’s bridge sources each drop-in again. Non-idempotent PATH edits, hooks, prompt setup, and the example exec zsh handoff can therefore run twice. This contradicts scope-layers.md:211 and the template README’s claim that exactly one layer wires the directory.

The verifier misses it because scripts/verify:252-266 probes bash -ic and searches .bashrc, bypassing the acq-owned login path in .profile entirely.

Suggested fix: remove the active bash startup command and rely on acq’s v4 backend-neutral login bridge; retain only optional native-zsh wiring if needed. Change verification to exercise a login shell, and replace/revise scripts/tests/test_personal_kit_rc_loop_pattern.py, which currently protects the obsolete .bashrc mechanism. Also update the docs that tell a personal kit to own the loop.

Evidence was read against quickstart main, not inferred: the shared bridge is explicitly documented as the ONE text used by both MSB and SBX. All seven PR checks pass, but none models this cross-repo login chain. AI-assisted review (OpenCode), requesting changes with the maintainer’s explicit authorization.

@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch 2 times, most recently from 63aedf2 to e8f30b7 Compare October 9, 2026 21:13
basiliskus added a commit that referenced this pull request Oct 9, 2026
acq v4.0.0 and later writes ~/.profile so every bash login shell sources
~/.rc.d/*.sh on both backends. A kit that also appends a loop to ~/.bashrc
makes every drop-in run twice, so the pattern doc no longer tells a kit to
wire one. acq's loop has no interactive guard, so drop-ins must be safe in
scripted bash -lc runs.

Reported in review of #442.
basiliskus added a commit that referenced this pull request Oct 9, 2026
acq v4.0.0 and later sources ~/.rc.d/*.sh from ~/.profile in every bash
login shell on both backends, after sourcing ~/.bashrc. The template's
startup step appended a second loop to ~/.bashrc, so on msb every drop-in
ran twice in a login shell (reproduced on msb 0.7.7 with acq v4.0.1).

- Drop the .bashrc loop step; keep the commented zsh step, since acq's loop
  runs only in bash.
- verify: check the drop-in in a bash login shell, count how many times it
  is sourced (exactly once), and check a scripted bash -lc still runs,
  instead of probing bash -ic and the template's own loop.
- Docs: acq's loop has no interactive guard, so drop-ins also run in
  scripted bash -lc and must guard interactive-only lines themselves.
- Test: no kit or template wires ~/.rc.d into a bash startup file; the zsh
  step's grep pattern keeps its regression cases.

Reported in review of #442.
@basiliskus
basiliskus force-pushed the feat/personal-kit-template branch from e8f30b7 to 05bcf97 Compare October 9, 2026 22:11
@basiliskus

Copy link
Copy Markdown
Contributor Author

Thanks — confirmed and fixed. I reproduced it live on msb 0.7.7 with acq v4.0.1: a counter drop-in ran twice under bash -lic (once from the template's ~/.bashrc loop, once from acq's ~/.profile loop).

  • feat(isolation): add the scope-layers pattern and a team-kit template #441 (adfbc95): the scope-layers personal-kit rows now say acq's ~/.profile sources ~/.rc.d in every bash login shell, that a kit must not add its own loop, and that the loop has no interactive guard, so drop-ins also run in scripted bash -lc. "Check against your acq" notes that acq leaves an image-owned ~/.profile alone.
  • This PR (05bcf97): the .bashrc loop step is gone (the commented zsh step stays, since acq's loop is bash-only). verify now checks the drop-in in a bash -lic login shell, counts how often it is sourced from bash's xtrace (. FILE lines, so it is independent of the drop-in's content), and checks that a scripted bash -lc still runs its command. Against the old kit the count is 2; now it is 1. test_kit_rc_d_wiring.py replaces the old regex test: it fails if any kit or template wires ~/.rc.d into a bash startup file (it fails on the previous spec) and keeps the zsh pattern's cases.

verify on msb 0.7.7 with acq v4.0.1: personal 19 passed / 0 failed / 1 skipped, team 20 / 0 / 1. make test 448 passed, validators and both kit validators pass. Not re-run on sbx.

@basiliskus
basiliskus requested review from mogul and wz-gsa October 9, 2026 22:15
wz-gsa
wz-gsa previously approved these changes Oct 10, 2026

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of 05bcf970: the duplicate Bash bridge blocker is closed. Approving the stacked personal-kit change, contingent on merging #441 first (this PR's current base is feat/team-kit-template).

Verified:

  • The active .bashrc rc.d append step is gone from spec.yaml.
  • The only remaining startup-file wiring is the commented optional zsh example, which current acq does not provide.
  • README/troubleshooting now state that acq owns the Bash login bridge, warn against adding a second loop, and explain the custom-image .profile caveat.
  • The live verifier uses bash -lic, requires exactly one xtrace source event, and confirms scripted bash -lc completes.
  • The replacement repository-wide regression test scans every kit and template, rejects active rc.d wiring in Bash startup files, asserts discovery is non-empty, and preserves real grep -E positive/negative cases for the zsh pattern.

Executed locally at the current head:

test_kit_rc_d_wiring.py: 19 passed
strict kit validator: all 10 kits + 2 templates valid
repo validators: all pass

The earlier two regex blockers remain fixed, and the optional zsh handoff guard still behaves correctly under Bash 3.2 (bash -lc, bash -ic with/without TTY, plain interactive TTY, and handoff-marker cases were exercised in the prior review).

No remaining finding. Merge order: #441, then retarget/rebase this stacked PR onto main and confirm refreshed CI.

Base automatically changed from feat/team-kit-template to main October 10, 2026 00:11
Add the copy-and-rename template acq-kits/examples/personal-kit/: a
hybrid/v1 mixin stacked last, with a shell drop-in and the ~/.rc.d loop
wired for interactive bash, a git preference, and an OpenCode TUI theme
through OPENCODE_TUI_CONFIG. Its scripts/verify stacks it on a team kit (the
team-kit template by default) and asserts the three-layer stack.

The pattern doc gains the personal-layer guidance the template relies on
(the exec-zsh guards, the one personal-tool exception to "tools belong in
the image"), ADR 0005 records the commented Nix install step as a deliberate
exception, and acq-kits/README.md lists the template.
acq v4.0.0 and later sources ~/.rc.d/*.sh from ~/.profile in every bash
login shell on both backends, after sourcing ~/.bashrc. The template's
startup step appended a second loop to ~/.bashrc, so on msb every drop-in
ran twice in a login shell (reproduced on msb 0.7.7 with acq v4.0.1).

- Drop the .bashrc loop step; keep the commented zsh step, since acq's loop
  runs only in bash.
- verify: check the drop-in in a bash login shell, count how many times it
  is sourced (exactly once), and check a scripted bash -lc still runs,
  instead of probing bash -ic and the template's own loop.
- Docs: acq's loop has no interactive guard, so drop-ins also run in
  scripted bash -lc and must guard interactive-only lines themselves.
- Test: no kit or template wires ~/.rc.d into a bash startup file; the zsh
  step's grep pattern keeps its regression cases.

Reported in review of #442.
@wz-gsa
wz-gsa dismissed their stale review October 10, 2026 00:11

The merge-base changed after approval.

@wz-gsa
wz-gsa force-pushed the feat/personal-kit-template branch from 05bcf97 to 967008f Compare October 10, 2026 00:11

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving retargeted head 967008f7 after #441 merged.

GitHub rewrote the stacked branch onto main; the personal-kit files are byte-identical to reviewed fix 05bcf970:

git diff 05bcf970 967008f7 -- integrations/isolation/acq-kits/examples/personal-kit \
                             scripts/tests/test_kit_rc_d_wiring.py \
                             integrations/isolation/docs/decisions/0005-kit-templates.md
(empty)

The duplicate Bash bridge blocker is closed: no active .bashrc/.profile rc.d loop remains in the kit; acq's v4 login bridge owns Bash sourcing; zsh wiring remains commented/optional; the verifier uses bash -lic, requires exactly one source event, and confirms scripted bash -lc completes. The repository-wide regression suite passes 19/19, strict kit validation passes all 10 kits + 2 templates, and all repo validators pass.

All seven refreshed CI checks pass on this retargeted head. The old changes-requested reviews refer to superseded heads (42d1c47d) and both their regex and duplicate-bridge findings are now fixed.

@wz-gsa

wz-gsa commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

@mogul — #441 is merged and GitHub retargeted this stack to main at 967008f7. Both blockers from your Oct. 1 review are fixed at the current head: the over-escaped rc.d regex was corrected and covered by real grep -E regression cases; the later duplicate-Bash-bridge blocker is fixed by removing the active .bashrc loop entirely and relying on acq v4's built-in login bridge. The replacement suite is 19/19, strict kit validation passes 10 kits + 2 templates, repo validators pass, and all seven refreshed CI checks are green. I posted an approval on the retargeted SHA, but your original CHANGES_REQUESTED review is still active and keeps the PR blocked. Could you dismiss/re-review that superseded review when you get a chance? I am not overriding another reviewer's state.

@wz-gsa
wz-gsa merged commit 8c9e84a into main Oct 12, 2026
7 checks passed
@wz-gsa
wz-gsa deleted the feat/personal-kit-template branch October 12, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants