@sebastienrousseau/dotfiles 0.2.510 → 0.2.512
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/README.md +2 -2
- package/docs/AI.md +2 -1
- package/docs/COPYRIGHT +1 -1
- package/docs/architecture/AI_COST_OPTIMIZATION.md +1 -0
- package/docs/archive/LEGACY_ROADMAP.md +4 -158
- package/docs/articles/.pages +6 -0
- package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +216 -0
- package/docs/articles/2026-07-05-fish-startup-abbr.md +153 -0
- package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +128 -0
- package/docs/articles/index.md +36 -0
- package/docs/manual/00-introduction.md +1 -1
- package/docs/manual/02-tutorials/02-add-wallpaper.md +6 -6
- package/docs/manual/02-tutorials/03-create-profile.md +1 -1
- package/docs/manual/02-tutorials/05-deploy-fleet.md +1 -1
- package/docs/manual/03-reference/02-config-files.md +1 -1
- package/docs/manual/command-index.md +1 -0
- package/docs/operations/ARCHITECTURE_ROADMAP.md +5 -143
- package/docs/operations/COVERAGE.md +27 -4
- package/docs/operations/ROADMAP.md +3 -159
- package/docs/operations/ROADMAP_2026.md +5 -663
- package/docs/operations/ROADMAP_V0_2_503.md +5 -129
- package/docs/reference/THEMES.md +1 -1
- package/docs/reference/TOOLS.md +1 -0
- package/docs/reference/UTILS.md +1 -0
- package/install.sh +5 -5
- package/package.json +1 -1
- package/scripts/diagnostics/aliases-manifest.sh +52 -7
- package/scripts/diagnostics/benchmark.sh +27 -1
- package/scripts/diagnostics/doctor.sh +18 -11
- package/scripts/diagnostics/health.sh +8 -3
- package/scripts/diagnostics/mcp-doctor.sh +3 -0
- package/scripts/diagnostics/secret-governance.sh +7 -1
- package/scripts/diagnostics/security-score.sh +14 -5
- package/scripts/diagnostics/verify_state.sh +15 -3
- package/scripts/diagnostics/version-locks.sh +10 -6
- package/scripts/dot/commands/agent.sh +5 -1
- package/scripts/dot/commands/ai.sh +37 -30
- package/scripts/dot/commands/aliases.sh +28 -4
- package/scripts/dot/commands/appearance.sh +16 -0
- package/scripts/dot/commands/core.sh +17 -0
- package/scripts/dot/commands/diagnostics.sh +19 -0
- package/scripts/dot/commands/fleet.sh +4 -1
- package/scripts/dot/commands/manual.sh +4 -4
- package/scripts/dot/commands/meta.sh +87 -12
- package/scripts/dot/commands/registry.sh +8 -2
- package/scripts/dot/commands/secrets.sh +17 -0
- package/scripts/dot/commands/security.sh +17 -0
- package/scripts/dot/commands/tools.sh +30 -2
- package/scripts/git-hooks/pre-commit-audit.sh +1 -1
- package/scripts/ops/ai-setup.sh +13 -6
- package/scripts/ops/bundle.sh +31 -5
- package/scripts/ops/chezmoi-apply.sh +5 -0
- package/scripts/ops/release.sh +14 -5
- package/scripts/qa/docs-coverage.sh +1 -1
- package/scripts/qa/reliability-audit.sh +2 -2
- package/scripts/secrets/age-init.sh +15 -4
- package/scripts/theme/apply-gnome-theme.sh +6 -2
- package/scripts/theme/extract-theme.py +97 -33
- package/scripts/theme/rebuild-themes.sh +240 -35
- package/scripts/theme/switch.sh +26 -16
- package/scripts/theme/wallpaper-sync.sh +95 -7
- package/scripts/tools/detect-collisions.py +19 -1
- package/scripts/version-sync.sh +87 -43
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Fish Startup in 2026: Cutting Interactive Shell Latency by Half with abbr on Multi-Shell Dotfiles"
|
|
3
|
+
description: Diagnosing and remediating a 232 ms fish cold-start on the .dotfiles multi-shell bridge — one printf format change, one chezmoi hook, half the latency.
|
|
4
|
+
date: 2026-07-05
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Fish Startup in 2026: Cutting Interactive Shell Latency by Half with `abbr` on Multi-Shell Dotfiles
|
|
8
|
+
|
|
9
|
+
*Interactive shells have become the primary interface for AI-augmented development; the difference between a 120 ms and a 230 ms first prompt compounds into measurable engineering-hour loss across a global fleet.*
|
|
10
|
+
|
|
11
|
+
*Sebastien Rousseau · Published 5 Jul 2026 · 10 min read*
|
|
12
|
+
|
|
13
|
+
## Why Interactive Shell Latency Matters in 2026 #
|
|
14
|
+
|
|
15
|
+
The AI-augmented developer opens a terminal dozens of times a day. In fleets running Claude Code, Codex CLI, GitHub Copilot CLI, or agentic frameworks that spawn subshells for every tool call, shell startup latency stops being a personal-comfort metric and becomes a **platform-engineering signal**.
|
|
16
|
+
|
|
17
|
+
The [.dotfiles reference framework](https://github.com/sebastienrousseau/dotfiles) treats sub-second shell startup as an SLO alongside SLSA-signed releases and MCP boundary enforcement. When a shell exceeds its budget, the framework's `dot health` command reports it as a failing check, not a warning — because a slow prompt on a workstation running 18 concurrent AI agents is a supply-chain-throughput problem, not an aesthetic one.
|
|
18
|
+
|
|
19
|
+
This article walks through the diagnosis and fix that took Fish cold-start latency from **231 ms → 119 ms** — a 48% reduction — on a workstation carrying ~900 bridged bash aliases into Fish for cross-shell parity. The remediation is a one-line change to a code-generation printf statement, plus a chezmoi hook that moves the cost out of the interactive path.
|
|
20
|
+
|
|
21
|
+
## The Multi-Shell Bridge 2026 Architecture Lens #
|
|
22
|
+
|
|
23
|
+
Cross-shell parity — the same aliases, functions, environment, and completions across bash, Zsh, Fish, and Nushell — is a distinct architectural property of a mature dotfiles framework. Each layer of that bridge carries its own performance tax:
|
|
24
|
+
|
|
25
|
+
| Layer | Design Decision | Why It Matters | Risk if Mishandled |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| **Source of truth** | Bash-hosted alias library (~900 entries) sourced by `zsh` and `bash` natively | Single canonical location prevents drift; matches how most upstream tooling assumes aliases live | Duplication across shells silently diverges; users on Fish or Nushell get a subtly different alias set |
|
|
28
|
+
| **Fish bridge** | `bash --norc --noprofile` subshell dumps `alias -p`, output translated and cached to `~/.cache/fish/bash-aliases.fish` | Fish has no `bash`-sourcing primitive; the bridge is unavoidable | Bridge runs at every shell start unless cached; cache invalidation timing determines the felt cost |
|
|
29
|
+
| **Cache format** | `abbr --add NAME -- VALUE` (this article's change) instead of `alias NAME=VALUE` | Fish's `alias` builtin allocates a function per entry (~183 µs each × 900 entries = ~165 ms); `abbr` is a command-line-time expansion at ~40 µs | Choosing `alias` for the cache format silently caps Fish cold-start at ~230 ms even on a warm cache |
|
|
30
|
+
| **Cache invalidation** | Compare source mtime + first-line format marker | Alias sources change on every `chezmoi apply`, invalidating the cache and forcing regen on the next shell — the exact moment the user opens a terminal to try their changes | Cache regen on the interactive path punishes the shell that opens right after configuration changes |
|
|
31
|
+
| **Pre-warm hook** | `run_onchange_after_` chezmoi hook rebuilds the cache during apply | Moves the ~200 ms regen cost off the user's first prompt into the apply step | Absence of a pre-warm hook makes the first post-apply shell feel broken |
|
|
32
|
+
|
|
33
|
+
## Key Interactive Shell Performance Signals #
|
|
34
|
+
|
|
35
|
+
| Signal | Operational Benchmark | Reference | Technical Platform Implementation |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| **Fish cold-start** | ≤ 200 ms first-prompt latency | Interactive-response threshold (Nielsen 1993, still the industry norm) | `hyperfine --warmup 2 'fish -i -c exit'` in CI; regression fails a PR if the median crosses threshold |
|
|
38
|
+
| **Fish warm-start** | ≤ 130 ms after cache is populated | Delta between cold/warm reveals cache-invalidation cost | Same command with `--warmup 3`; the mean tracks the fully-cached shell path |
|
|
39
|
+
| **First-post-apply latency** | Warm-shell parity — no cliff after `chezmoi apply` | Signals that regeneration lives outside the shell hot path | `chezmoi apply && hyperfine 'fish -i -c exit'` — cold and warm should be within noise |
|
|
40
|
+
| **Cache-format compatibility** | Auto-heal path when upgrading between cache formats | Ensures long-lived workstations don't inherit stale caches on framework upgrade | Staleness check compares first line of cache to expected format marker |
|
|
41
|
+
| **Bridge throughput** | ~40 µs per abbreviated entry, ~183 µs per aliased entry | Fish internals — measured, not documented | Choice of `abbr` over `alias` in the cache-emission format string |
|
|
42
|
+
|
|
43
|
+
## Diagnosis: Where the Milliseconds Went #
|
|
44
|
+
|
|
45
|
+
`fish --profile-startup=/tmp/f.prof -i -c 'exit'` emits a per-command trace with self-time and cumulative time. Sorted by cumulative time descending, one line dominated the warm-start budget:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Time (µs) Sum (µs) Command
|
|
49
|
+
1687 132211 ----> source "$_alias_cache"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**132 ms of a 231 ms budget** — 57% — spent sourcing a single cache file. Everything else (starship prompt initialisation, mise activation, atuin history bindings, direnv hooks) added up cleanly to the remaining ~85 ms.
|
|
53
|
+
|
|
54
|
+
The cache file itself was well-formed and cache-invalidation was working correctly. The problem lived at the primitive level: what does `alias name='value'` cost when Fish parses and installs it? Ran in isolation:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
$ hyperfine --warmup 2 "fish -c 'source ~/.cache/fish/bash-aliases.fish'"
|
|
58
|
+
Time (mean ± σ): 170.8 ms ± 11.3 ms
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**170 ms just to source 878 alias lines.** Fish's `alias` isn't a shell-level string substitution — it's a function factory. The invocation `alias ll='eza -la --icons'` roughly desugars to:
|
|
62
|
+
|
|
63
|
+
```fish
|
|
64
|
+
function ll --wraps='eza -la --icons' --description 'alias ll=eza -la --icons'
|
|
65
|
+
eza -la --icons $argv
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Every call parses the definition, allocates a function object, installs it in the function table, records the description, and wires the `--wraps` for tab completion. Approximately 183 µs per entry. At 878 entries, the maths is uncompromising: 878 × 183 µs = 161 ms.
|
|
70
|
+
|
|
71
|
+
The cost is O(1) per call, but the call count is the problem, and there is no batching path in Fish's `alias` implementation.
|
|
72
|
+
|
|
73
|
+
## Remediation: `abbr --add` as a Cross-Shell-Bridge Primitive #
|
|
74
|
+
|
|
75
|
+
Fish exposes two ways to give a short name to a longer command:
|
|
76
|
+
|
|
77
|
+
- **`alias`** — function factory. Available in interactive shells, scripts, pipes, subshells, and inside other functions. Costs a function allocation on every source.
|
|
78
|
+
- **`abbr --add`** — abbreviation. Expanded at the interactive command line the moment the user types the abbreviation and hits space or enter. Not available in scripts (they need functions). No function allocation on installation.
|
|
79
|
+
|
|
80
|
+
For bash-alias bridges, the tradeoff is invisible: users don't call `ll` from inside a Fish script — they'd write a proper Fish function for that use case. Abbreviations for this workload are a strict upgrade: identical interactive UX, no function-table pressure, and — as a side benefit — they show the user what actually runs when they type the abbreviation, which improves shell literacy.
|
|
81
|
+
|
|
82
|
+
The code change is a single printf format string in the cache-generator:
|
|
83
|
+
|
|
84
|
+
```diff
|
|
85
|
+
- printf "alias %s=%s\n" "$name" "$val"
|
|
86
|
+
+ printf "abbr --add %s -- %s\n" "$name" "$val"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Measured in isolation:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Benchmark 1: fish -c 'source alias-cache.fish'
|
|
93
|
+
Time (mean ± σ): 170.8 ms ± 11.3 ms
|
|
94
|
+
|
|
95
|
+
Benchmark 2: fish -c 'source abbr-cache.fish'
|
|
96
|
+
Time (mean ± σ): 34.0 ms ± 0.9 ms
|
|
97
|
+
|
|
98
|
+
Summary
|
|
99
|
+
abbr-cache.fish ran 5.02 ± 0.36 times faster than alias-cache.fish
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**5× faster. 137 ms saved on every warm shell start.** End-to-end Fish latency dropped from 231 ms → 119 ms.
|
|
103
|
+
|
|
104
|
+
## The Second-Order Bug: Cache Invalidation Timing #
|
|
105
|
+
|
|
106
|
+
Solving the warm case revealed a distinct failure mode: the *first* Fish shell opened after `chezmoi apply` still measured ~306 ms. The apply step writes new versions of the underlying bash alias source files (updated mtimes). The staleness check inside the Fish bridge sees `source.mtime > cache.mtime`, throws the cache away, and rebuilds it — spawning a subshell, sourcing 40 KB of bash, iterating 878 lines. **~200 ms.**
|
|
107
|
+
|
|
108
|
+
The shell that pays this cost is whichever one the user opens first, which is almost always the shell they opened *because* they wanted to see the effect of the apply.
|
|
109
|
+
|
|
110
|
+
The remediation is architectural, not algorithmic. The regeneration is moved off the interactive path and onto the apply itself via a chezmoi `run_onchange_after_` script:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
#!/usr/bin/env bash
|
|
114
|
+
# Source-hash retrigger keys — script re-runs when any of these change:
|
|
115
|
+
# 90-ux-aliases.sh.tmpl: {{ include "…/90-ux-aliases.sh.tmpl" | sha256sum }}
|
|
116
|
+
# 91-ux-aliases-lazy.sh.tmpl: {{ include "…/91-ux-aliases-lazy.sh.tmpl" | sha256sum }}
|
|
117
|
+
# aliases.fish.tmpl: {{ include "…/aliases.fish.tmpl" | sha256sum }}
|
|
118
|
+
|
|
119
|
+
command -v fish >/dev/null 2>&1 || exit 0
|
|
120
|
+
|
|
121
|
+
rm -f "${HOME}/.cache/fish/bash-aliases.fish"
|
|
122
|
+
fish -i -c 'exit' >/dev/null 2>&1 || true
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The hook invalidates the cache, spawns a throwaway interactive Fish so the bridge's existing regen path fires, then exits. The user's next actual shell finds a valid, up-to-date cache. The 200 ms cost lands where the user expects "compilation work" to happen — during the apply — not on the terminal they open ten seconds later.
|
|
126
|
+
|
|
127
|
+
Cold-start Fish after apply: **306 ms → 120 ms.**
|
|
128
|
+
|
|
129
|
+
## Return on Resilience #
|
|
130
|
+
|
|
131
|
+
At a workstation opening 40 shells per day, saving 112 ms per shell reclaims 4.5 seconds daily; 22 minutes annually. At a small engineering org of 50 developers with the same profile, that's 18 engineering-hours reclaimed per year — measurable but modest.
|
|
132
|
+
|
|
133
|
+
The stronger case is qualitative. Interactive-latency perception is nonlinear: at ~200 ms the user consciously notices lag; at ~120 ms the shell feels immediate. Once the felt lag is gone, the developer stops flinching before opening a terminal — which changes the frequency and length of exploratory shell work, which changes the shape of what they do at the CLI.
|
|
134
|
+
|
|
135
|
+
| Metric | Before | After | Delta |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| Fish warm-start (median) | 231 ms | 119 ms | −112 ms (−48%) |
|
|
138
|
+
| Fish cold-start after apply | 306 ms | 120 ms | −186 ms (−61%) |
|
|
139
|
+
| Cache source cost | 170 ms | 34 ms | −136 ms (−80%) |
|
|
140
|
+
| CI regression threshold | ✗ 231 > 200 | ✓ 119 ≤ 200 | Now under budget |
|
|
141
|
+
| Full test suite | 4703 tests, 0 fail | 4703 tests, 0 fail | Zero regressions |
|
|
142
|
+
|
|
143
|
+
## Takeaways #
|
|
144
|
+
|
|
145
|
+
1. **Profile every interactive shell in CI.** Fish, Zsh, Nushell, Bash — each has its own primitives with different costs. Treat first-prompt latency as a signal with a threshold, not a comfort metric.
|
|
146
|
+
|
|
147
|
+
2. **Prefer `abbr` for interactive-only bridged aliases in Fish.** The distinction between `abbr` (line-time expansion) and `alias` (function factory) is documented; the 5× cost distinction is not. If your users don't call the alias from inside a Fish script — and for bridged bash aliases they don't — `abbr` is a strict upgrade.
|
|
148
|
+
|
|
149
|
+
3. **Move cache regeneration off the interactive path.** Any cache invalidated by a configuration-management action (chezmoi, ansible, dotbot) should be regenerated by that same action, not by whichever shell opens next.
|
|
150
|
+
|
|
151
|
+
4. **Version the cache format itself, not just the source.** The staleness check should include a format marker so upgrading users don't inherit stale caches by mtime luck.
|
|
152
|
+
|
|
153
|
+
The reference implementation lives on `main` at [sebastienrousseau/dotfiles](https://github.com/sebastienrousseau/dotfiles); the change landed as [PR #963](https://github.com/sebastienrousseau/dotfiles/pull/963) and [PR #964](https://github.com/sebastienrousseau/dotfiles/pull/964), shipped in [v0.2.510](https://github.com/sebastienrousseau/dotfiles/releases/tag/v0.2.510).
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Renaming master to main in 2026: A Zero-Downtime Runbook"
|
|
3
|
+
description: A supply-chain-safe procedure for renaming the default branch of a mature open-source repository — 96 in-repo edits, a grace-period mirror workflow, zero broken install URLs.
|
|
4
|
+
date: 2026-07-05
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Renaming `master` to `main` in 2026: A Zero-Downtime Runbook for a Repository at the Heart of an Open-Source Supply Chain
|
|
8
|
+
|
|
9
|
+
*Renaming the default branch of a mature repository is a supply-chain event, not a cosmetic one; done wrong, it strands `curl \| bash` install commands, breaks CI, and severs external distribution channels.*
|
|
10
|
+
|
|
11
|
+
*Sebastien Rousseau · Published 5 Jul 2026 · 12 min read*
|
|
12
|
+
|
|
13
|
+
## Why Default-Branch Naming Matters in 2026 #
|
|
14
|
+
|
|
15
|
+
Every open-source project with a public install path publishes a URL of the form `raw.githubusercontent.com/<owner>/<repo>/<branch>/install.sh`. Every downstream consumer who has copied that URL — into a README, a Slack message, a devcontainer, a company wiki, a StackOverflow answer, a Homebrew tap, an AUR PKGBUILD, an internal Ansible playbook — has taken an implicit dependency on that branch name. Renaming the branch is a **breaking change to the project's public API surface**, whether the maintainer intended one or not.
|
|
16
|
+
|
|
17
|
+
The industry moved off `master` as the default branch name years ago; new repositories default to `main`. Existing repositories, however, live with a naming inconsistency that becomes actively confusing when a maintainer has multiple projects — some on `main`, some still on `master`. The migration is unavoidable, but the operational risk profile is significant enough that most maintainers put it off indefinitely.
|
|
18
|
+
|
|
19
|
+
This article documents the migration of the [.dotfiles](https://github.com/sebastienrousseau/dotfiles) repository — 60+ files with hardcoded branch references, four external distribution channels, three CI providers tracking the default branch, and a public install command bookmarked by an unknown number of downstream users. The migration was **zero-downtime**: no install command broke, no CI job failed, no downstream integration degraded. The blueprint is generalisable to any medium-complexity open-source repository.
|
|
20
|
+
|
|
21
|
+
## The Branch-Rename 2026 Architecture Lens #
|
|
22
|
+
|
|
23
|
+
A default-branch rename is not a single operation. It's a sequence of coordinated changes across a defined dependency graph, each with its own migration mechanism:
|
|
24
|
+
|
|
25
|
+
| Layer | Design Decision | Why It Matters | Risk if Mishandled |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| **GitHub metadata** | Native rename via Settings → Branches or `POST /repos/{owner}/{repo}/branches/{branch}/rename` | GitHub auto-migrates default-branch setting, open PR targets, branch-protection assignment, ruleset targeting, and Pages source | Renaming via manual `git push :old-name` + `git push new-name` skips the auto-migration and orphans PRs |
|
|
28
|
+
| **In-repo workflow triggers** | `.github/workflows/*.yml` `branches:` lists updated pre-rename | Workflows that trigger on `push:` or `pull_request:` targeting the old name silently stop firing after rename | Migration PR itself under-tested — the workflows it edits no longer fire on it |
|
|
29
|
+
| **Grace-period mirror** | New workflow fast-forwards `master` from `main` on every push | Preserves `raw.githubusercontent.com/…/master/…` URLs for downstream consumers who cannot be reached | External `curl \| bash` install commands return HTTP 404 the moment `master` ceases to exist |
|
|
30
|
+
| **Documentation URIs** | `mkdocs.yml` `edit_uri`, README install commands, docs prose | GitHub redirects `github.com/…/blob/master/…` automatically; `raw.githubusercontent.com/…/master/…` does **not** redirect | Docs site edit buttons point at nonexistent branches; install commands 404 |
|
|
31
|
+
| **Rulesets as code** | `.github/rulesets/<branch>.json` file renamed alongside the JSON `target.include` | Machine-readable ruleset files that reference `refs/heads/master` misalign with GitHub's auto-migrated state | Configuration drift between the in-repo policy source of truth and GitHub's live enforcement |
|
|
32
|
+
| **Test-suite assertions** | Regression tests that asserted `/master/` URLs in README updated to assert `/main/` | Tests written before rename fail *after* rename in the exact commit that fixes them | Migration PR shows red CI, blocking merge |
|
|
33
|
+
| **External distribution** | Homebrew tap, Scoop bucket, AUR PKGBUILD — pinned to release tags, not branches | Version-pinning insulates external distribution from branch renames | Branch-pinned distribution manifests break silently on rename |
|
|
34
|
+
|
|
35
|
+
## Key Branch-Rename Migration Signals #
|
|
36
|
+
|
|
37
|
+
| Signal | Operational Benchmark | Reference | Technical Platform Implementation |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| **URL Reachability Post-Rename** | `HTTP 200` on both `main/install.sh` and `master/install.sh` for the full grace period | External-consumer continuity | Mirror workflow: `on: push: branches: [main]` → `git push origin main:refs/heads/master` |
|
|
40
|
+
| **CI Coverage on Migration PR** | Workflow-trigger `branches:` list transitionally includes both `main` and `master` | Migration PR must be tested against the current default | `pull_request: branches: [main, master]` — remove `master` once the mirror retires |
|
|
41
|
+
| **In-Repo URL Consistency** | Zero remaining `/master/` URIs on the head branch, excluding intentional mirror-preservation strings | Doc/install correctness | `git grep 'raw.githubusercontent.com/.../master/'` returns empty (or only test-fixture strings) |
|
|
42
|
+
| **Ruleset File Alignment** | `.github/rulesets/*.json` filename matches its `target.include` refspec | Config-as-code hygiene | File rename via `git mv` + JSON `target.include` update in the same commit |
|
|
43
|
+
| **Grace-Period Retirement Marker** | Calendar-visible tracking item with an explicit sunset date | Operational-debt visibility | GitHub issue with target date in title + calendar event (`.ics` or Google Calendar quick-add URL) |
|
|
44
|
+
|
|
45
|
+
## Diagnosis: Enumerating the Blast Radius #
|
|
46
|
+
|
|
47
|
+
Before touching a single file, an authoritative audit surfaces the full inventory of `master` references. On the .dotfiles repository, that surfaced **~88 mechanical replacements across 60 files**, grouped as:
|
|
48
|
+
|
|
49
|
+
- **24 GitHub Actions workflow files** — trigger lists, `github.ref_name == 'master'` conditionals, `--base master` PR-creating steps, inline `@SHA # master` comments describing what commit was pinned
|
|
50
|
+
- **7 `raw.githubusercontent.com/.../master/…` URLs** — README install command, `install.sh` (referencing itself in its own comment header), `bin/dot-bootstrap`, `docs/index.md`, install guide, MkDocs edit_uri, chezmoi-data JSON `$id` field
|
|
51
|
+
- **~25 documentation files** — `github.com/…/blob/master/…` references in operations runbooks, security docs, architecture decision records
|
|
52
|
+
- **1 ruleset-as-code file** — `.github/rulesets/master.json` with a `target.include: refs/heads/master` field
|
|
53
|
+
- **1 regression test** — asserting the README contains `/master/` (a red-team catch: this test PROTECTS against accidental rename, which now needs its assertion inverted)
|
|
54
|
+
- **4 legitimately-kept references** — the `gbd` bulk-branch-delete script with a `main|master` whitelist regex, the `git-primary-branch` shell function's fallback path, the release-branch check in `scripts/ops/release.sh`, and Scorecard-linter fixtures demonstrating `@master` as an anti-pattern
|
|
55
|
+
|
|
56
|
+
## Remediation Sequence #
|
|
57
|
+
|
|
58
|
+
The rename is executed as a five-phase sequence, each with a distinct commit or GitHub operation:
|
|
59
|
+
|
|
60
|
+
**Phase 1 — Pre-migration content preparation.** A single pull request rewrites all in-repo `master` references while `master` is still the default branch. This PR must merge before any GitHub-side rename. Workflow `pull_request:` triggers gain `[main, master]` (paired) so the PR itself triggers CI against the current default. The ruleset file is renamed via `git mv` and its JSON target updated. The regression test's assertion is inverted from "must contain `/master/`" to "must contain `/main/`".
|
|
61
|
+
|
|
62
|
+
**Phase 2 — GitHub-side rename.** Via UI (`Settings → Branches → Rename`) or API (`POST /repos/{owner}/{repo}/branches/master/rename`). GitHub auto-migrates default-branch setting, PR targets, branch-protection assignment, ruleset targeting, Pages source. Blocked if a branch-protection *rule pattern* targeting the new name already exists — delete the empty rule first via GraphQL:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
gh api graphql -f query='
|
|
66
|
+
mutation {
|
|
67
|
+
deleteBranchProtectionRule(input: { branchProtectionRuleId: "..." }) {
|
|
68
|
+
clientMutationId
|
|
69
|
+
}
|
|
70
|
+
}'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Phase 3 — Mirror workflow activation.** Trigger the pre-committed mirror workflow via `workflow_dispatch` or a small push to `main`. The workflow performs a fast-forward `git push origin main:refs/heads/master`, recreating `master` as a passive mirror. From this point forward, every push to `main` mirrors automatically.
|
|
74
|
+
|
|
75
|
+
**Phase 4 — Local clone update (per-workstation).** Every developer with an active clone runs:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
git branch -m master main
|
|
79
|
+
git fetch origin
|
|
80
|
+
git branch -u origin/main main
|
|
81
|
+
git remote set-head origin -a
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Phase 5 — Retirement scheduling.** A GitHub issue with a title-embedded target date (`[2027-07-05] Retire master mirror + tighten workflow triggers to main-only`) plus a calendar reminder ensures the grace-period mirror doesn't become permanent operational debt.
|
|
85
|
+
|
|
86
|
+
## Verification: URLs, CI, Docs Site #
|
|
87
|
+
|
|
88
|
+
Post-rename smoke tests:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ curl -sI https://raw.githubusercontent.com/sebastienrousseau/dotfiles/main/install.sh | head -1
|
|
92
|
+
HTTP/2 200
|
|
93
|
+
$ curl -sI https://raw.githubusercontent.com/sebastienrousseau/dotfiles/master/install.sh | head -1
|
|
94
|
+
HTTP/2 200
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Both branch names resolve during the grace period. When the mirror is retired in 12 months, `/master/` returns 404 by design — but by then no active install command should still reference it.
|
|
98
|
+
|
|
99
|
+
CI status post-rename: on the .dotfiles repository, the migration PR (`#961`) ran **70 checks green, 0 failed**, driven by the `[main, master]` trigger-list transitional configuration. The follow-up test-coverage PR (`#963`) confirmed no downstream test regression.
|
|
100
|
+
|
|
101
|
+
Docs site: MkDocs `edit_uri` — updated from `edit/master/docs/` to `edit/main/docs/` — resolves correctly. `github.com/…/blob/master/…` links continue to work via GitHub's built-in redirect; `raw.githubusercontent.com/…/master/…` works via the mirror.
|
|
102
|
+
|
|
103
|
+
## Return on Resilience #
|
|
104
|
+
|
|
105
|
+
The commercial value of a supply-chain-safe rename is defensive, not offensive: nothing new is built, but nothing existing breaks.
|
|
106
|
+
|
|
107
|
+
| Metric | Result |
|
|
108
|
+
|---|---|
|
|
109
|
+
| Files updated in migration PR | 97 (96 edits + 1 rename + 1 new workflow) |
|
|
110
|
+
| Grace-period external URL uptime | 100% (both `/main/` and `/master/` return HTTP 200) |
|
|
111
|
+
| CI checks post-rename | 70 green, 0 failed |
|
|
112
|
+
| Downstream distribution channels broken | 0 (Homebrew tap, Scoop bucket, AUR pinned to tags) |
|
|
113
|
+
| Local-clone update commands | 4 lines, ~5 seconds per workstation |
|
|
114
|
+
| Operational debt introduced | 1 mirror workflow, retired via calendar-scheduled task 2027-07-05 |
|
|
115
|
+
|
|
116
|
+
## Takeaways #
|
|
117
|
+
|
|
118
|
+
1. **Land the in-repo edits before the GitHub-side rename.** Merging Phase 1 while `master` is still default gives you both a working CI baseline and a rehearsal.
|
|
119
|
+
|
|
120
|
+
2. **Add the mirror workflow before renaming, not after.** The interval between the GitHub rename and the mirror's first fast-forward push is the window during which `raw.githubusercontent.com/…/master/…` returns 404. Minimising that window is a matter of ordering.
|
|
121
|
+
|
|
122
|
+
3. **Update `pull_request:` triggers transitionally.** `branches: [main, master]` covers the migration PR itself (which targets the pre-rename default) and every future PR (which will target `main`). The grace-period `master` entry retires with the mirror.
|
|
123
|
+
|
|
124
|
+
4. **Track retirement as an issue with an explicit sunset date.** Mirror workflows are the classic case of "temporary" becoming "permanent". A calendar event and a GitHub issue with a date-anchored title enforce end-of-life.
|
|
125
|
+
|
|
126
|
+
5. **Rulesets-as-code files must be renamed alongside their JSON targets.** GitHub auto-migrates the *live* ruleset assignment; the file in your repo is the source-of-truth if you ever reapply. Both must agree.
|
|
127
|
+
|
|
128
|
+
The reference implementation landed as [PR #961](https://github.com/sebastienrousseau/dotfiles/pull/961) with the retirement issue tracked at [#962](https://github.com/sebastienrousseau/dotfiles/issues/962), shipped in [v0.2.510](https://github.com/sebastienrousseau/dotfiles/releases/tag/v0.2.510).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Articles
|
|
3
|
+
description: Long-form writing on the design and operation of the .dotfiles framework.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Articles
|
|
7
|
+
|
|
8
|
+
Long-form writing on the design and operation of the [.dotfiles framework](https://github.com/sebastienrousseau/dotfiles) — deep dives into performance, supply-chain safety, developer experience, and the architectural decisions that shape a mature open-source dotfiles project.
|
|
9
|
+
|
|
10
|
+
<div class="grid cards" markdown>
|
|
11
|
+
|
|
12
|
+
- :material-console:{ .lg .middle } **[Fish Startup in 2026](2026-07-05-fish-startup-abbr.md)**
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
Cutting interactive shell latency by 48% with `abbr` on multi-shell dotfiles. One printf format change + one chezmoi hook = 112 ms saved per fresh terminal.
|
|
17
|
+
|
|
18
|
+
*5 Jul 2026 · 10 min read*
|
|
19
|
+
|
|
20
|
+
- :material-source-branch:{ .lg .middle } **[Renaming `master` to `main`](2026-07-05-master-to-main-rename-runbook.md)**
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
A zero-downtime runbook for a repository at the heart of an open-source supply chain. 96 in-repo edits, a 12-month mirror workflow, zero broken install URLs.
|
|
25
|
+
|
|
26
|
+
*5 Jul 2026 · 12 min read*
|
|
27
|
+
|
|
28
|
+
- :material-palette:{ .lg .middle } **[Custom Documentation Sites in 2026](2026-07-05-custom-mkdocs-material-dark-theme.md)**
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
Building a distinctive dark-themed developer reference on MkDocs Material — three files, no theme forking, WCAG AAA contrast, hash-locked build.
|
|
33
|
+
|
|
34
|
+
*5 Jul 2026 · 11 min read*
|
|
35
|
+
|
|
36
|
+
</div>
|
|
@@ -4,7 +4,7 @@ render_with_liquid: false
|
|
|
4
4
|
|
|
5
5
|
# Introduction
|
|
6
6
|
|
|
7
|
-
This manual describes `.dotfiles` v0.2.
|
|
7
|
+
This manual describes `.dotfiles` v0.2.512 — a trusted agent workstation baseline for macOS, Linux, and WSL.
|
|
8
8
|
|
|
9
9
|
The repository is more than a personal dotfiles collection. It ships as workstation infrastructure: signed, attested, multi-platform, AI-aware, and self-healing. Chezmoi handles templating and platform differences. The `dot` CLI sits on top and coordinates lifecycle operations.
|
|
10
10
|
|
|
@@ -126,10 +126,10 @@ Output:
|
|
|
126
126
|
```
|
|
127
127
|
NAME SOURCE PATH
|
|
128
128
|
---- ------ ----
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
monterey-dark system /System/Library/Desktop Pictures/.thumbnails/Monterey Dark.heic
|
|
130
|
+
monterey-light system /System/Library/Desktop Pictures/.thumbnails/Monterey Light.heic
|
|
131
|
+
tahoe-dark system /System/Library/Desktop Pictures/.thumbnails/Tahoe Dark.heic
|
|
132
|
+
tahoe-light system /System/Library/Desktop Pictures/.thumbnails/Tahoe Light.heic
|
|
133
133
|
sonoma-dark system /System/Library/Desktop Pictures/.thumbnails/Sonoma Dark.heic
|
|
134
134
|
...
|
|
135
135
|
Total: 152 wallpapers
|
|
@@ -138,10 +138,10 @@ Total: 152 wallpapers
|
|
|
138
138
|
Switch to any system wallpaper:
|
|
139
139
|
|
|
140
140
|
```sh
|
|
141
|
-
dot theme
|
|
141
|
+
dot theme monterey-dark
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
The engine extracts
|
|
144
|
+
The engine extracts Monterey Dark's dominant colors, generates a palette, and applies it to every surface.
|
|
145
145
|
|
|
146
146
|
## Verifying the Result
|
|
147
147
|
|
|
@@ -48,7 +48,7 @@ Edit `~/.config/chezmoi/chezmoi.toml`:
|
|
|
48
48
|
```toml
|
|
49
49
|
[data]
|
|
50
50
|
machine = "surface-pro" # choose from .chezmoidata/hardware.toml
|
|
51
|
-
theme = "
|
|
51
|
+
theme = "monterey-dark"
|
|
52
52
|
default_shell = "fish"
|
|
53
53
|
terminal_font_family = "JetBrainsMono Nerd Font"
|
|
54
54
|
terminal_font_size = 11 # larger for HiDPI, smaller for dense screens
|
|
@@ -146,7 +146,7 @@ Each host has its own `~/.config/chezmoi/chezmoi.toml` — use it for things tha
|
|
|
146
146
|
# surface-pro's chezmoi.toml
|
|
147
147
|
[data]
|
|
148
148
|
machine = "surface-pro"
|
|
149
|
-
theme = "
|
|
149
|
+
theme = "monterey-dark" # per-host default
|
|
150
150
|
default_shell = "fish"
|
|
151
151
|
terminal_font_size = 11 # smaller for HiDPI
|
|
152
152
|
```
|
|
@@ -122,7 +122,7 @@ sourceDir = "/Users/you/.dotfiles"
|
|
|
122
122
|
|
|
123
123
|
[data]
|
|
124
124
|
machine = "surface-pro" # selects preset from hardware.toml
|
|
125
|
-
theme = "
|
|
125
|
+
theme = "monterey-dark" # overrides .chezmoidata.toml default
|
|
126
126
|
default_shell = "fish"
|
|
127
127
|
terminal_font_size = 11
|
|
128
128
|
email = "you@example.com"
|
|
@@ -77,6 +77,7 @@ job `lint/command-index` fails when this file is stale.
|
|
|
77
77
|
| `dot history` | Shell history analysis |
|
|
78
78
|
| `dot keys` | Keybindings (sign-check: verify git signing) |
|
|
79
79
|
| `dot keys` | sign-check Verify git commit-signing configuration and key availability |
|
|
80
|
+
| `dot kimi` | Kimi CLI with context patterns |
|
|
80
81
|
| `dot kiro` | Kiro CLI with context patterns |
|
|
81
82
|
| `dot learn` | Start the interactive tour of your new tools |
|
|
82
83
|
| `dot lint` | Lint shell scripts (--fix |
|
|
@@ -1,145 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
title: "Architecture & Roadmap — cross-shell consistency, performance, decoupling"
|
|
3
|
-
date: 2026-07-01
|
|
4
|
-
status: living document
|
|
5
|
-
---
|
|
1
|
+
# Architecture Roadmap
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
Historical architecture planning has been consolidated into the canonical
|
|
4
|
+
[`../../ROADMAP.md`](../../ROADMAP.md).
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
landscape, and a plan to decouple optional subsystems (`dot ai`, MCP, LSP)
|
|
12
|
-
into companion repos around a stable core. It is the source of truth for
|
|
13
|
-
the multi-phase program tracked below.
|
|
14
|
-
|
|
15
|
-
> Honesty policy: every performance number here is **measured** with
|
|
16
|
-
> `hyperfine` (warmed up), reproducible with the harness in
|
|
17
|
-
> `tests/performance/bench.sh` (interactive sessions, all installed shells)
|
|
18
|
-
> and `dot benchmark`. Estimates are labelled as such. The
|
|
19
|
-
> built-in `dot doctor` perf readout historically **understated** real
|
|
20
|
-
> startup because it timed a narrower slice — Phase 0 reconciles that.
|
|
21
|
-
|
|
22
|
-
## 1. Measured performance baseline (2026-07-01, Apple Silicon)
|
|
23
|
-
|
|
24
|
-
Method: `hyperfine -N --warmup 5` on the deployed config; `exit`-on-launch.
|
|
25
|
-
|
|
26
|
-
| Shell | Startup (mean) | rc cost over ~7ms spawn | vs <30ms target |
|
|
27
|
-
|---------|----------------|-------------------------|-----------------|
|
|
28
|
-
| nushell | 24.8 ms | — | meets |
|
|
29
|
-
| bash | 51.1 ms | +43.6 ms | 1.7× over |
|
|
30
|
-
| zsh | 66.3 ms | +59.6 ms | 2.2× over |
|
|
31
|
-
| fish | 128.8 ms | bash-bridge tax | 4.3× over |
|
|
32
|
-
|
|
33
|
-
Baselines (pure process spawn, no rc): `zsh -fc exit` 6.7 ms,
|
|
34
|
-
`bash --norc` 7.5 ms.
|
|
35
|
-
|
|
36
|
-
Cost attribution (uncached tool-init subprocess cost, what `_cached_eval`
|
|
37
|
-
caches away): `mise activate` 17.7 ms, `atuin init` 7.1 ms,
|
|
38
|
-
`starship init` 4.0 ms, `zoxide init` 2.4 ms. `_cached_eval` **is**
|
|
39
|
-
working (cache files fresh; `zcompdump` is `zcompile`d), which is why zsh
|
|
40
|
-
is 66 ms and not ~97 ms.
|
|
41
|
-
|
|
42
|
-
**<30ms verdict (honest):** not reachable for the *full eager stack*
|
|
43
|
-
(mise + starship + atuin + zoxide + fzf + zinit + ~97 alias files + ~53
|
|
44
|
-
functions + compinit) on zsh/bash without tradeoffs. It **is** reachable
|
|
45
|
-
as a tunable "fast profile" + first-prompt deferral. nushell already
|
|
46
|
-
meets it; fish (bash-bridge) is the worst and the biggest opportunity.
|
|
47
|
-
|
|
48
|
-
## 2. Cross-shell consistency
|
|
49
|
-
|
|
50
|
-
- bash/zsh are native + single-source; **fish and nushell are bash
|
|
51
|
-
*bridges*** — they filter aliases and wrap functions via `bash -c`
|
|
52
|
-
subshells, adding a runtime bash dependency and silent parity loss.
|
|
53
|
-
- Parity gap: bash/zsh ~53 functions; fish 27 native; nushell 0 native;
|
|
54
|
-
~26 functions have no native impl; behaviour drifts (e.g. `goto` loses
|
|
55
|
-
directory grouping in fish/nu).
|
|
56
|
-
- Duplication: eza-detection logic in bash + 7 fish files + nu wrappers;
|
|
57
|
-
`_cached_eval` reimplemented four times.
|
|
58
|
-
- Direction: a **manifest-driven single source of truth** (one
|
|
59
|
-
alias/function spec → per-shell generators). This also removes the
|
|
60
|
-
class of parse-time collision that produced the zsh alias-shim bug.
|
|
61
|
-
|
|
62
|
-
## 3. Decoupling architecture
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
dotfiles (CORE)
|
|
66
|
-
dot CLI · lib/dot/ui.sh · utils.sh · chezmoi base · plugin API
|
|
67
|
-
| | | |
|
|
68
|
-
dotfiles-ai dotfiles-mcp dotfiles-lsp (future)
|
|
69
|
-
dot ai, registry, dot/alias/
|
|
70
|
-
cockpit, policy, chezmoi-template
|
|
71
|
-
gateway mcp-doctor completions
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Readiness (from the coupling audit):
|
|
75
|
-
|
|
76
|
-
| Subsystem | Coupling | Effort | Notes |
|
|
77
|
-
|-----------|----------|--------|-------|
|
|
78
|
-
| MCP | low (declarative JSON + one `cmd_mcp`) | low | isolated by design |
|
|
79
|
-
| LSP | none (one nvim plugin file) | trivial | already a lazy.nvim plugin |
|
|
80
|
-
| `dot ai` | high (ui.sh, utils.sh, dispatcher, chezmoi hooks) | high | needs the two contracts below |
|
|
81
|
-
|
|
82
|
-
Two foundational contracts must exist before AI can move cleanly:
|
|
83
|
-
|
|
84
|
-
1. **Extract `lib/dot/ui.sh` into a versioned shared lib** — AI *and* MCP
|
|
85
|
-
depend on it; without this, decoupling means duplication.
|
|
86
|
-
2. **A `dot` plugin/extension API** — manifest-registered subcommands so
|
|
87
|
-
companion repos add `dot ai` / `dot mcp` without forking the
|
|
88
|
-
dispatcher.
|
|
89
|
-
|
|
90
|
-
## 4. 2026 landscape — gaps worth adopting (highest value first)
|
|
91
|
-
|
|
92
|
-
- **`dotfiles-mcp` with a secrets-redaction + allowlist policy layer** — a
|
|
93
|
-
genuine gap no existing dotfiles-MCP fills; reuses the gitleaks / Atuin
|
|
94
|
-
`history_filter` posture. Expose introspection via MCP **Resources**,
|
|
95
|
-
actions via **Tools**.
|
|
96
|
-
- **`dotfiles-lsp`** = `dot` subcommand completions + alias awareness +
|
|
97
|
-
**chezmoi-template-data-aware** completions → a novel *combination*
|
|
98
|
-
(weekend-scale MVP using just-lsp / tcl-lsp patterns).
|
|
99
|
-
- Password-manager templating (1Password/Bitwarden), SOPS for shared
|
|
100
|
-
secrets, **Bats** tests (reviewer lingua franca), devcontainer/Codespaces
|
|
101
|
-
fast install path.
|
|
102
|
-
|
|
103
|
-
Context: chezmoi has won the dotfiles category; mise is baseline; Starship
|
|
104
|
-
has overtaken Powerlevel10k (maintenance-only); MCP spec 2025-11-25 is
|
|
105
|
-
under the Linux Foundation and safe to build on.
|
|
106
|
-
|
|
107
|
-
## 5. Staged roadmap
|
|
108
|
-
|
|
109
|
-
Each phase ships as its own reviewed PR with before/after benchmarks.
|
|
110
|
-
|
|
111
|
-
| Phase | Work | Risk | Target payoff |
|
|
112
|
-
|-------|------|------|---------------|
|
|
113
|
-
| **0** | Honest benchmark harness in-repo; make `dot doctor` report real numbers | low | truth in metrics |
|
|
114
|
-
| **1** | Perf quick-wins audit (deferral, compinit, zcompile, mise ordering) | low | verify + record baseline |
|
|
115
|
-
| **2** | Extract `lib/dot/ui.sh` → versioned shared lib | med | unblocks decoupling |
|
|
116
|
-
| **3** | `dot` plugin API + carve out `dotfiles-mcp` (lowest-risk repo) | med | proves the model |
|
|
117
|
-
| **4** | Cross-shell manifest (single source → per-shell generators); de-bash-bridge fish | high | consistency + fish speed |
|
|
118
|
-
| **5** | `dotfiles-ai` as a plugin repo | high | the decoupling goal |
|
|
119
|
-
| **6** | `dotfiles-lsp` MVP | low | differentiation |
|
|
120
|
-
| **7** | Docs + `examples/` + published honest benchmarks | med | completeness |
|
|
121
|
-
|
|
122
|
-
### Status
|
|
123
|
-
|
|
124
|
-
- **Phase 0 — done** (`feat/v0.2.509`): `tests/performance/bench.sh` now times
|
|
125
|
-
every shell *interactively* (fish was measured non-interactively, faking
|
|
126
|
-
~12ms vs the real ~118ms) and includes nushell; `dot doctor` reports the
|
|
127
|
-
real medians.
|
|
128
|
-
- **Phase 1 — done (audit)** (`feat/v0.2.509`): the documented quick-wins are
|
|
129
|
-
**already implemented** in the deployed config, verified:
|
|
130
|
-
- `compinit` deferred to first prompt, `-C` + daily-audit cache
|
|
131
|
-
(`~/.config/zsh/rc.d/30-options.zsh`).
|
|
132
|
-
- Eagerly-sourced hub files are `zcompile`d (`.zwc` present).
|
|
133
|
-
- Plugins turbo-deferred (`zinit ice wait lucid`), fzf backgrounded, and
|
|
134
|
-
mise/atuin/starship/zoxide inits deferred to post-prompt hydration and
|
|
135
|
-
cached via `_cached_eval`.
|
|
136
|
-
- `mise activate` ordering is a non-issue here: zsh uses `add-zsh-hook`
|
|
137
|
-
(appends, no overwrite) and bash manages `PROMPT_COMMAND` explicitly.
|
|
138
|
-
- Net: `zsh -ic exit` (which runs before the prompt, so it excludes the
|
|
139
|
-
deferred inits) is ~66ms of *eager* rc — dominated by sourcing the large
|
|
140
|
-
aggregated alias/function hubs. No safe further quick-win remains.
|
|
141
|
-
- **Consequence:** sub-30ms is not reachable by tuning; it needs Phase 4
|
|
142
|
-
(manifest → cut the eager alias/function volume) or a lean profile.
|
|
143
|
-
fish (~118ms) is the biggest single opportunity (bash-bridge), also
|
|
144
|
-
Phase 4.
|
|
145
|
-
- Phases 2–7 — planned; sequencing subject to review.
|
|
6
|
+
Current architecture decisions belong in `docs/architecture/`; future roadmap
|
|
7
|
+
items belong in the root roadmap or in GitHub issues and milestones.
|
|
@@ -43,17 +43,40 @@ matches and emits standard `lcov.info` that Codecov ingests natively.
|
|
|
43
43
|
|
|
44
44
|
| Surface | What runs |
|
|
45
45
|
|---|---|
|
|
46
|
-
| **PR + push to main** | `.github/workflows/coverage.yml` → `Coverage / kcov` job → uploads lcov.info to Codecov and fails the build below `MIN_COVERAGE_PCT` (currently `
|
|
46
|
+
| **PR + push to main** | `.github/workflows/coverage.yml` → `Coverage / kcov` job → uploads lcov.info to Codecov and fails the build below `MIN_COVERAGE_PCT` (currently `49`, ratcheted up after measured integer-floor gains). |
|
|
47
47
|
| **Local dev** | `bash tools/ci/run-coverage.sh` — works on Linux + macOS (xtrace is a bash primitive, no platform tools needed). |
|
|
48
|
-
| **macOS dev** | Supported. xtrace-based instrumentation runs on macOS bash 3.2+ and Homebrew bash 5.x. |
|
|
48
|
+
| **macOS dev** | Supported. xtrace-based instrumentation runs on macOS bash 3.2+ and Homebrew bash 5.x, with a Perl alarm fallback when GNU `timeout`/`gtimeout` is unavailable. |
|
|
49
49
|
|
|
50
50
|
## The current floor
|
|
51
51
|
|
|
52
|
-
`MIN_COVERAGE_PCT=
|
|
52
|
+
`MIN_COVERAGE_PCT=49` in `.github/workflows/coverage.yml`. Slice 1
|
|
53
53
|
of [#883](https://github.com/sebastienrousseau/dotfiles/issues/883)
|
|
54
54
|
established the baseline at **~2.7% measured** (~613 of ~22 500 lines
|
|
55
55
|
across 231 files). Successive slices raised it; the current measured
|
|
56
|
-
value sits at
|
|
56
|
+
value sits at **50.16%** (`6205/12371` lines, re-measured on the merged tree; gate floored at 49 for local<->CI drift + run variance) after the eighth core
|
|
57
|
+
coverage-ratchet slice added `jwt` portability coverage and
|
|
58
|
+
branch-driving function coverage for `apihealth`, `apiload`, and
|
|
59
|
+
`apilatency`. This builds on the prior helper slice that drove
|
|
60
|
+
`scripts/dot/commands/restore.sh` to 75.17%,
|
|
61
|
+
`scripts/dot/commands/meta.sh` to 66.88%, `lib/dot/log.sh` to 59.56%,
|
|
62
|
+
and `scripts/dot/commands/diagnostics.sh` to 49.63%, with additional
|
|
63
|
+
git AI, hashsum, regex, jsonv, gl, and hex helper branch coverage.
|
|
64
|
+
This builds on the prior core slice (`scripts/dot/commands/init.sh` at 72.09%,
|
|
65
|
+
`scripts/dot/commands/manual.sh` at 62.50%,
|
|
66
|
+
`scripts/dot/commands/core.sh` at 55.86%, and
|
|
67
|
+
`scripts/dot/commands/secrets.sh` at 54.97%), the prior
|
|
68
|
+
AI command slice (`defaults/dot_local/bin/executable_dot-ai-proxy` at
|
|
69
|
+
76.00%, `scripts/dot/commands/agents.sh` at 66.15%, and
|
|
70
|
+
`scripts/dot/commands/completion.sh` at 45.68%), the registry slice
|
|
71
|
+
(`scripts/dot/commands/registry.sh` at 65.03%) and the macOS
|
|
72
|
+
coverage-runner Perl timeout fallback, the aliases slice
|
|
73
|
+
(`scripts/dot/commands/aliases.sh` at 70.00%), the tools/version-sync
|
|
74
|
+
slice (`scripts/dot/commands/tools.sh` at 72.85%, `lib/dot/utils.sh` at
|
|
75
|
+
73.24%, and `scripts/version-sync.sh` at 36.53%), the first core slice
|
|
76
|
+
for `lib/dot/ui.sh`, and the #954 deep-branch pass for
|
|
77
|
+
`scripts/theme/switch.sh`,
|
|
78
|
+
`scripts/diagnostics/mcp-doctor.sh`, and Linux/WSL branches in
|
|
79
|
+
`scripts/diagnostics/doctor.sh`.
|
|
57
80
|
|
|
58
81
|
To tighten:
|
|
59
82
|
|