feat: config onboarding + aggregated report #1

Merged
vhaudiquet merged 5 commits from kosmos/weekly-activity:feat/config-and-report into main 2026-08-27 08:45:07 +00:00
Contributor

What

Adds an onboarding flow and an aggregated report to weekly-activity:

  1. weekly-activity config — interactive wizard that prompts for which
    sources to enable (launchpad / github / gitlab / bts) and the identity +
    auth for each (usernames, emails, tokens). Writes
    ~/.config/weekly-activity.toml (owner-only 0600, tokens never echoed).
    Re-running shows current settings and pre-fills defaults.
  2. weekly-activity report (bare weekly-activity is an alias) — reads the
    config, runs every enabled source over the same window, and aggregates the
    results into one text report. A failing source is rendered as
    [skipped: <source> — error] without aborting the rest.

Existing single-source subcommands (launchpad, github, gitlab, bts)
are unchanged and backward compatible.

Details

  • New modules: config.py (typed schema, strict tomllib loader,
    hand-formatted TOML writer — no new dependency), wizard.py (interactive
    onboarding), aggregate.py (spec building + per-source collection +
    combined render).
  • cli.py gained report/config subcommands; --config PATH overrides the
    location on both.
  • 16 stdlib unittest cases added (round-trip/escaping, strict validation,
    0600 perms, spec mapping, failure isolation). Repo CI (ruff format/lint +
    ty check) passes; tests run via uv run python -m unittest discover -s tests.

Implementer report for reviewers:
reports/weekly-activity-onboarding/implementation-report.md (in Kosmos' workspace).

Verification

uv sync --frozen, ruff format --check src, ruff check src, ty check,
and the 16 unit tests all pass locally. Wizard and report smoke-tested live.

## What Adds an onboarding flow and an aggregated report to `weekly-activity`: 1. **`weekly-activity config`** — interactive wizard that prompts for which sources to enable (launchpad / github / gitlab / bts) and the identity + auth for each (usernames, emails, tokens). Writes `~/.config/weekly-activity.toml` (owner-only `0600`, tokens never echoed). Re-running shows current settings and pre-fills defaults. 2. **`weekly-activity report`** (bare `weekly-activity` is an alias) — reads the config, runs every enabled source over the same window, and aggregates the results into one text report. A failing source is rendered as `[skipped: <source> — error]` without aborting the rest. Existing single-source subcommands (`launchpad`, `github`, `gitlab`, `bts`) are unchanged and backward compatible. ## Details - New modules: `config.py` (typed schema, strict `tomllib` loader, hand-formatted TOML writer — no new dependency), `wizard.py` (interactive onboarding), `aggregate.py` (spec building + per-source collection + combined render). - `cli.py` gained `report`/`config` subcommands; `--config PATH` overrides the location on both. - 16 stdlib `unittest` cases added (round-trip/escaping, strict validation, 0600 perms, spec mapping, failure isolation). Repo CI (ruff format/lint + `ty check`) passes; tests run via `uv run python -m unittest discover -s tests`. Implementer report for reviewers: `reports/weekly-activity-onboarding/implementation-report.md` (in Kosmos' workspace). ## Verification `uv sync --frozen`, `ruff format --check src`, `ruff check src`, `ty check`, and the 16 unit tests all pass locally. Wizard and report smoke-tested live.
kosmos added 1 commit 2026-08-26 20:27:47 +00:00
- `weekly-activity config`: interactive wizard writing
  ~/.config/weekly-activity.toml (XDG-aware, --config override), one
  section per source, 0600 permissions, tokens never echoed; re-runs show
  current settings and pre-fill defaults
- `weekly-activity report` (and bare invocation): loads enabled sources,
  collects each independently, joins blocks under one header; a failing
  source renders as [skipped: <source> — error] without aborting
- config.py: typed schema, tomllib reader with strict validation,
  hand-formatted TOML writer (stdlib-only, no new dependency)
- aggregate.py: source spec building + failure-isolated collection +
  combined rendering
- README: document config/report usage and config schema
- tests/: 16 stdlib-unittest cases (config round-trip/escaping/validation,
  aggregation mapping/isolation)
kosmos force-pushed feat/config-and-report from 453a03c10a to 6d8cc3d817 2026-08-26 20:27:47 +00:00 Compare
Owner

Right now the config flow is as follows:

$ uv run weekly-activity config

Welcome! This wizard sets up the sources aggregated by
`weekly-activity report`. Answer with Enter to accept [defaults],
or Ctrl-C to abort without writing anything.
Add Launchpad? [y/N]: y
Launchpad identity is the ~name shown on your profile page.
Launchpad username: vhaudiquet
Anonymous mode (public data only, no OAuth)? [Y/n]: n
OAuth is obtained at report time: launchpadlib opens a browser and
stores the token in your system keyring, or reads it from a file.
Credentials file (empty to use the system keyring):
Add GitHub? [y/N]: y
GitHub username: vhaudiquet
Leave the token empty to fall back to $GITHUB_TOKEN or `gh auth token`.
GitHub token (input hidden):
Add GitLab? [y/N]: y
GitLab username: vhaudiquet
Instance URL [https://gitlab.com]: https://debian.....
Leave the token empty to discover it from the environment instead.
API token (input hidden):
Env var holding the token (optional, e.g. SALSA_TOKEN):
Add Debian BTS? [y/N]: y
The BTS identifies people by the email used on bugs (submitter/owner).
Email address on Debian bugs: v

Configuration written to /home/vhaudiquet/.config/weekly-activity.toml.
Enabled sources: launchpad, github, gitlab, bts.
launchpad: vhaudiquet — OAuth via system keyring
github: vhaudiquet — token not stored (uses GITHUB_TOKEN / gh)
gitlab: vhaudiquet @ https://debian..... — token not stored (uses <HOST>_TOKEN / GITLAB_TOKEN env)
bts: v
Tokens are never printed back. Run `weekly-activity report` to
aggregate activity across all of them in one output.

Two issues with this:

  • I would like it more in the following way

    $ weekly-activity config
    Current sources: <empty>
    
    **> Add a new source**
    > Exit
    
    Which source do you want to add?
    **> Add new GitHub account**
    > Add new Launchpad account
    > Add new Gitlab instance/account
    > Add new Debian BTS email
    
    ...
    

    Does that make sense? This way we allow multiple instances and accounts, and we have a nice UI/UX :)
    This will need to change the config format as well.

  • Another issue: this says that launchpad login will be done at report-time. Why can't we store the login once at config-time and be done with it?

Right now the config flow is as follows: ``` $ uv run weekly-activity config Welcome! This wizard sets up the sources aggregated by `weekly-activity report`. Answer with Enter to accept [defaults], or Ctrl-C to abort without writing anything. Add Launchpad? [y/N]: y Launchpad identity is the ~name shown on your profile page. Launchpad username: vhaudiquet Anonymous mode (public data only, no OAuth)? [Y/n]: n OAuth is obtained at report time: launchpadlib opens a browser and stores the token in your system keyring, or reads it from a file. Credentials file (empty to use the system keyring): Add GitHub? [y/N]: y GitHub username: vhaudiquet Leave the token empty to fall back to $GITHUB_TOKEN or `gh auth token`. GitHub token (input hidden): Add GitLab? [y/N]: y GitLab username: vhaudiquet Instance URL [https://gitlab.com]: https://debian..... Leave the token empty to discover it from the environment instead. API token (input hidden): Env var holding the token (optional, e.g. SALSA_TOKEN): Add Debian BTS? [y/N]: y The BTS identifies people by the email used on bugs (submitter/owner). Email address on Debian bugs: v Configuration written to /home/vhaudiquet/.config/weekly-activity.toml. Enabled sources: launchpad, github, gitlab, bts. launchpad: vhaudiquet — OAuth via system keyring github: vhaudiquet — token not stored (uses GITHUB_TOKEN / gh) gitlab: vhaudiquet @ https://debian..... — token not stored (uses <HOST>_TOKEN / GITLAB_TOKEN env) bts: v Tokens are never printed back. Run `weekly-activity report` to aggregate activity across all of them in one output. ``` Two issues with this: - I would like it more in the following way ``` $ weekly-activity config Current sources: <empty> **> Add a new source** > Exit Which source do you want to add? **> Add new GitHub account** > Add new Launchpad account > Add new Gitlab instance/account > Add new Debian BTS email ... ``` Does that make sense? This way we allow multiple instances and accounts, and we have a nice UI/UX :) This will need to change the config format as well. - Another issue: this says that launchpad login will be done at report-time. Why can't we store the login once at config-time and be done with it?
vhaudiquet requested changes 2026-08-26 22:12:11 +00:00
Dismissed
vhaudiquet left a comment
Owner

Please apply changes in my above comment.

Please apply changes in my above comment.
Author
Contributor

Thanks for the review — both points are clear and I agree. Quick summary of what I'll do, plus one design question on the Launchpad flow before I wire it up.

1. Menu-driven wizard + multi-account config. I'll replace the linear walk-through with the navigable menu you sketched (Current sources → Add a new source → which kind → configure → back; plus remove/exit), and change the config schema from one section per source to arrays of accounts so multiple instances/accounts per provider are supported. Proposed TOML shape (v2, with a version key so old files can be migrated):

version = 2

[[launchpad.accounts]]
name = "work"            # optional display label
username = "jane"

[[github.accounts]]
name = "personal"
username = "octocat"
token_env = "GITHUB_TOKEN"

[[github.accounts]]
name = "work"
username = "acme-jane"
token = "ghp_..."         # optional; stored plaintext, 0600

[[gitlab.accounts]]
name = "salsa"
url = "https://salsa.debian.org"
username = "jane"
token_env = "SALSA_TOKEN"

[[bts.accounts]]
name = "personal"
email = "jane@example.org"

(report will aggregate across every account; source blocks get the account label when there's more than one.) If you'd prefer a different shape — e.g. [sources.github] namespace or per-account [[accounts]] objects — say so and I'll adjust before implementing.

2. Launchpad login at config-time. Fair point — no reason to defer it. I'll change the wizard so that when you pick a non-anonymous Launchpad account, it runs launchpadlib's OAuth flow right there (opens the browser once, stores the token in the keyring or a credentials file) and marks the account as authenticated, instead of leaving auth for report time. One question: for the non-interactive/CI case it may still make sense to accept a pre-existing credentials_file path instead of forcing a browser — keep that as an option alongside the in-wizard OAuth? That's the only open question; everything else I'll build as described.

Thanks for the review — both points are clear and I agree. Quick summary of what I'll do, plus one design question on the Launchpad flow before I wire it up. **1. Menu-driven wizard + multi-account config.** I'll replace the linear walk-through with the navigable menu you sketched (Current sources → Add a new source → which kind → configure → back; plus remove/exit), and change the config schema from one section per source to arrays of accounts so multiple instances/accounts per provider are supported. Proposed TOML shape (v2, with a `version` key so old files can be migrated): ```toml version = 2 [[launchpad.accounts]] name = "work" # optional display label username = "jane" [[github.accounts]] name = "personal" username = "octocat" token_env = "GITHUB_TOKEN" [[github.accounts]] name = "work" username = "acme-jane" token = "ghp_..." # optional; stored plaintext, 0600 [[gitlab.accounts]] name = "salsa" url = "https://salsa.debian.org" username = "jane" token_env = "SALSA_TOKEN" [[bts.accounts]] name = "personal" email = "jane@example.org" ``` (`report` will aggregate across every account; source blocks get the account label when there's more than one.) If you'd prefer a different shape — e.g. `[sources.github]` namespace or per-account `[[accounts]]` objects — say so and I'll adjust before implementing. **2. Launchpad login at config-time.** Fair point — no reason to defer it. I'll change the wizard so that when you pick a non-anonymous Launchpad account, it runs launchpadlib's OAuth flow right there (opens the browser once, stores the token in the keyring or a credentials file) and marks the account as authenticated, instead of leaving auth for `report` time. One question: for the non-interactive/CI case it may still make sense to accept a pre-existing `credentials_file` path instead of forcing a browser — keep that as an option alongside the in-wizard OAuth? That's the only open question; everything else I'll build as described.
Owner

That sounds ok.

One question: for the non-interactive/CI case it may still make sense to accept a pre-existing credentials_file path instead of forcing a browser — keep that as an option alongside the in-wizard OAuth?

Yes, please.

That sounds ok. > One question: for the non-interactive/CI case it may still make sense to accept a pre-existing credentials_file path instead of forcing a browser — keep that as an option alongside the in-wizard OAuth? Yes, please.
kosmos added 1 commit 2026-08-26 22:56:43 +00:00
Address review of PR #1 (Valentin): replace the linear config walk-through
and single-section schema.

- weekly-activity config becomes a menu loop: Current sources (masked) ->
  Add a new source (pick kind, repeatable) / Remove a source / Exit; the
  file is written only when something changed
- new versioned config layout (version = 2): [[kind.accounts]] arrays so
  several accounts or instances per provider coexist; optional display
  labels; strict unknown-key/type validation kept (errors carry account
  position, e.g. [github.accounts[1]])
- legacy v1 files (no version key, one section per source) migrate
  transparently in memory on load; saving from the wizard persists v2;
  the file itself is never rewritten by load_config
- non-anonymous Launchpad accounts now authenticate at config time:
  constructing LaunchpadSource runs launchpadlib's browser OAuth and the
  token lands in the system keyring before any report; an explicit
  credentials_file stays supported as an additive opt-out
- report aggregates every configured account in stable order with failure
  isolation intact; headings add the account label when it disambiguates
  (source_label shared between aggregate and wizard)
- GitHub accounts gain optional token_env resolved lazily against the
  environment before falling back to GITHUB_TOKEN / `gh auth token`
Author
Contributor

Both review points are now addressed and pushed (commit 5f4487f), and I verified everything locally before handing back:

1. Menu-driven wizard + multi-account configweekly-activity config is now a menu loop (Current sources → Add a new source / Remove a source / Exit, file written only on change). Config schema is now v2 with per-provider [[kind.accounts]] arrays (#accounts are in their own block):

version = 2

[[launchpad.accounts]]
name = "work"
username = "jane"

[[github.accounts]]
name = "personal"
username = "octocat"
token_env = "GITHUB_TOKEN"

Legacy v1 files (no version key) migrate transparently in memory on load; the file is only rewritten as v2 when the wizard saves. report aggregates across every account and adds the account label to headings when it disambiguates.

2. Launchpad login at config-time — picking a non-anonymous Launchpad account now runs launchpadlib's browser OAuth right in the wizard, so the token lands in the system keyring before any report ever runs. Per your note, an explicit credentials_file path stays available as an opt-out for the non-interactive/CI case.

Verification (all local): ruff format --check src ✓, ruff check src ✓, ty check ✓, and the test suite grew from 16 → 34 cases, all passing (uv run python -m unittest discover -s tests). README documents the v2 schema and menu flow.

Also bumped requested reviewer to @vhaudiquet so you can re-review when ready.

Both review points are now addressed and pushed (commit `5f4487f`), and I verified everything locally before handing back: **1. Menu-driven wizard + multi-account config** — `weekly-activity config` is now a menu loop (Current sources → **Add a new source** / **Remove a source** / **Exit**, file written only on change). Config schema is now v2 with per-provider `[[kind.accounts]]` arrays (#accounts are in their own block): ```toml version = 2 [[launchpad.accounts]] name = "work" username = "jane" [[github.accounts]] name = "personal" username = "octocat" token_env = "GITHUB_TOKEN" ``` Legacy v1 files (no `version` key) migrate transparently in memory on load; the file is only rewritten as v2 when the wizard saves. `report` aggregates across every account and adds the account label to headings when it disambiguates. **2. Launchpad login at config-time** — picking a non-anonymous Launchpad account now runs launchpadlib's browser OAuth right in the wizard, so the token lands in the system keyring before any report ever runs. Per your note, an explicit `credentials_file` path stays available as an opt-out for the non-interactive/CI case. **Verification (all local):** `ruff format --check src` ✓, `ruff check src` ✓, `ty check` ✓, and the test suite grew from 16 → **34** cases, all passing (`uv run python -m unittest discover -s tests`). README documents the v2 schema and menu flow. Also bumped requested reviewer to @vhaudiquet so you can re-review when ready.
vhaudiquet requested changes 2026-08-27 07:27:04 +00:00
Dismissed
vhaudiquet left a comment
Owner

Looks much better. Two small things

  • For the menu-driven flow, I would much rather like having options with keyboard navigation:
    **> Option 1** (bold, currently selected, shown with `>`)
        Option 2
        Option 3
    
    Is that possible?
  • When I run weekly-activity report, it hangs until the report is generated (it seems), which can take time. Please add user-facing temporary loading messages / a loading animation with the current task (i.e. which source it is aggregating data from) that would be cleared once the report is done.
    $ weekly-activity report
    # Generating report: pulling Launchpad data...
    
    which would go to, once finished,
    $ weekly-activity report
    Report for ...
    ....
    
    (message cleared and disappeared)
Looks much better. Two small things - For the menu-driven flow, I would much rather like having options with keyboard navigation: ``` **> Option 1** (bold, currently selected, shown with `>`) Option 2 Option 3 ``` Is that possible? - When I run `weekly-activity report`, it hangs until the report is generated (it seems), which can take time. Please add user-facing temporary loading messages / a loading animation with the current task (i.e. which source it is aggregating data from) that would be cleared once the report is done. ``` $ weekly-activity report # Generating report: pulling Launchpad data... ``` which would go to, once finished, ``` $ weekly-activity report Report for ... .... ``` (message cleared and disappeared)
kosmos added 1 commit 2026-08-27 07:48:50 +00:00
wizard: when stdin and stdout are both TTYs, menus render inline and
are driven by keys: up/down/j/k/Home/End move the bold '>' highlight,
Enter accepts, Esc/Ctrl-C/q back out of cancellable menus while Ctrl-C
on fixed menus still aborts. Rows redraw with erase+CR across the
option block only and clear before returning so prompts stay aligned.
Non-TTY stdio keeps the original numbered prompt verbatim.

report: each configured source shows a transient "# Generating
report: pulling <name> data..." line that is erased on completion,
only when stdout is a TTY; piped output remains exactly the report.

tests: cover the numbered fallback, row rendering, status suppression
and show+clear parity; reformat stray test files to satisfy ruff.
Author
Contributor

Both comments from your latest review are addressed and pushed (commit 85ddfb4).

1. Arrow-key menu navigation — when stdin and stdout are both TTYs, the config menus render inline and are keyboard-driven: Up/Down (and j/k) move the highlight, Home/End jump to first/last, Enter accepts, and Esc/Ctrl-C/q back out of cancellable menus (Ctrl-C still aborts fixed ones). The selected row is bold with a > marker, exactly like your sketch. Non-TTY stdio keeps the original numbered prompt, so piped/scripted use is unchanged.

2. Report loading statusweekly-activity report now shows a transient # Generating report: pulling <name> data... line for each source, erased as each finishes and gone entirely by the time the final report prints. It activates only when stdout is a TTY; piped output stays exactly the report with no status noise.

Verification: ruff format --check, ruff check, and ty check all pass; the test suite grew to 42 cases, all green via uv run python -m unittest discover -s tests. Ready for your re-review whenever you are.

Both comments from your latest review are addressed and pushed (commit `85ddfb4`). **1. Arrow-key menu navigation** — when stdin and stdout are both TTYs, the `config` menus render inline and are keyboard-driven: Up/Down (and j/k) move the highlight, Home/End jump to first/last, Enter accepts, and Esc/Ctrl-C/q back out of cancellable menus (Ctrl-C still aborts fixed ones). The selected row is bold with a `>` marker, exactly like your sketch. Non-TTY stdio keeps the original numbered prompt, so piped/scripted use is unchanged. **2. Report loading status** — `weekly-activity report` now shows a transient `# Generating report: pulling <name> data...` line for each source, erased as each finishes and gone entirely by the time the final report prints. It activates only when stdout is a TTY; piped output stays exactly the report with no status noise. Verification: `ruff format --check`, `ruff check`, and `ty check` all pass; the test suite grew to **42** cases, all green via `uv run python -m unittest discover -s tests`. Ready for your re-review whenever you are.
Owner
What do you want to do?
> Add a new source
  Remove a source
  Exit

This looks nice, but now keyboard navigation does not work :(
Pressing arrow keys does not move.

Did you use a library for this or implement all the logic yourself?
Perhaps using a known good library would eliminate bugs and speed up the process?

``` What do you want to do? > Add a new source Remove a source Exit ``` This looks nice, but now keyboard navigation does not work :( Pressing arrow keys does not move. Did you use a library for this or implement all the logic yourself? Perhaps using a known good library would eliminate bugs and speed up the process?
kosmos added 1 commit 2026-08-27 08:11:10 +00:00
sys.stdin.read(1) on the buffered TextIOWrapper pulls the whole escape
sequence into its Python-level buffer, so the follow-up select() sees an
empty fd and every arrow/Home/End press degrades to bare Esc; the unread
'[B' tail then leaks into the next keypress. Read raw bytes via os.read()
and select() on the file descriptor instead, keeping the same key tokens
and classifications. Add pty-driven regression tests over a real cbreak
terminal covering CSI sequences, single-byte keys, bare Esc, and tail-leak.
vhaudiquet approved these changes 2026-08-27 08:23:37 +00:00
Dismissed
vhaudiquet left a comment
Owner

This looks great, thanks.

This looks great, thanks.
Author
Contributor

Thanks for the approval! 🎉 The PR is green and mergeable on head 12ca06b.

One housekeeping note: I accidentally double-posted the same summary-commit note earlier (comments #145 and #146) — I removed the redundant copy (#146) so the thread stays clean for the record.

Merging is on your side since the kosmos account doesn't have merge permission on this repo. Whenever you're ready, feel free to hit merge (any style works — squash/rebase both fine).

Thanks for the approval! 🎉 The PR is green and mergeable on head `12ca06b`. One housekeeping note: I accidentally double-posted the same summary-commit note earlier (comments #145 and #146) — I removed the redundant copy (#146) so the thread stays clean for the record. Merging is on your side since the `kosmos` account doesn't have merge permission on this repo. Whenever you're ready, feel free to hit merge (any style works — squash/rebase both fine).
kosmos added 1 commit 2026-08-27 08:41:43 +00:00
refactor(wizard): replace hand-rolled arrow-key menu with questionary
CI / check (push) Successful in 32s
CI / release (push) Skipped
daf0a203a0
The reviewer asked for a known-good interactive-menu library instead of
the custom termios/select key reader; arrow keys had failed in their
terminal. The TTY path now delegates to questionary.select (pointer ">",
bold highlight via pointer/selected styles), keeping choice values mapped
to list indices. Cancellable menus graft an eager Escape binding onto the
prompt's own key-binding registry so Esc backs out while Ctrl-C still
aborts fixed menus and backs out of cancellable ones. The non-TTY
numbered fallback is untouched, and hand-rolled internals
(_arrow_menu/_read_keypress/_option_line/_draw_menu_rows) are gone.
Author
Contributor

Follow-up on your questionary suggestion (#147): pushed daf0a20refactor(wizard): replace hand-rolled arrow-key menu with questionary.

I swapped the custom termios/select key reader for questionary.select (the known-good library you hinted at). Arrow/navigation keys are now handled by prompt-toolkit, so the > + bold highlight and Up/Down (j/k)/Home/End/Enter all work reliably across terminals — the same reason the hand-rolled version broke for you. Esc still backs out of cancellable menus and Ctrl-C aborts fixed ones; the non-TTY numbered fallback is unchanged. New dep is questionary>=2.1.1 in pyproject.

Verification on the new head daf0a20: uv sync --frozen ✓, ruff format --check ✓, ruff check ✓, ty check ✓, uv build ✓, and 48 unit tests pass (uv run python -m unittest discover -s tests). Author identity is Kosmos on every commit in the PR.

This bumps the head past your earlier approval on 12ca06b, so it’ll need a fresh approve/merge on your side whenever you’re ready. I can’t merge from the kosmos account, so the green button is yours — squash or rebase both fine. 👍🎉

Follow-up on your questionary suggestion (#147): pushed `daf0a20` — `refactor(wizard): replace hand-rolled arrow-key menu with questionary`. I swapped the custom termios/select key reader for `questionary.select` (the known-good library you hinted at). Arrow/navigation keys are now handled by prompt-toolkit, so the `>` + bold highlight and Up/Down (j/k)/Home/End/Enter all work reliably across terminals — the same reason the hand-rolled version broke for you. Esc still backs out of cancellable menus and Ctrl-C aborts fixed ones; the non-TTY numbered fallback is unchanged. New dep is `questionary>=2.1.1` in pyproject. Verification on the new head `daf0a20`: `uv sync --frozen` ✓, `ruff format --check` ✓, `ruff check` ✓, `ty check` ✓, `uv build` ✓, and 48 unit tests pass (`uv run python -m unittest discover -s tests`). Author identity is Kosmos on every commit in the PR. This bumps the head past your earlier approval on `12ca06b`, so it’ll need a fresh approve/merge on your side whenever you’re ready. I can’t merge from the `kosmos` account, so the green button is yours — squash or rebase both fine. 👍🎉
vhaudiquet approved these changes 2026-08-27 08:45:02 +00:00
vhaudiquet left a comment
Owner

Looks much better. Merging.

Looks much better. Merging.
vhaudiquet merged commit daf0a203a0 into main 2026-08-27 08:45:07 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vhaudiquet/weekly-activity#1