@henryqw/pi-deps 0.3.7 → 0.3.9
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/README.md +8 -4
- package/docs/adr/0001-prepare-dependencies-at-worktree-creation.md +3 -0
- package/docs/adr/0002-install-dependencies-in-background.md +3 -0
- package/docs/dependency-preparation-flow.html +149 -0
- package/docs/dependency-preparation-flow.svg +132 -0
- package/hooks/post-checkout.mjs +1 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# `@henryqw/pi-deps`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Start locked Node and uv dependency installs whenever Git creates a worktree for an opted-in repository.
|
|
4
4
|
|
|
5
5
|
## Why
|
|
6
6
|
|
|
7
|
-
- **Created for**:
|
|
8
|
-
- **Advantage**:
|
|
7
|
+
- **Created for**: Developers who create worktrees through several tools.
|
|
8
|
+
- **Advantage**: One Git hook prepares every new checkout without adding work to each Pi startup.
|
|
9
9
|
|
|
10
10
|
## Install
|
|
11
11
|
|
|
@@ -17,7 +17,9 @@ Node 22.19 or newer, Git, and each selected package manager must be available on
|
|
|
17
17
|
|
|
18
18
|
## Use
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Run `/deps` in a trusted repository to enable preparation. Create a worktree, then open Pi there.
|
|
21
|
+
|
|
22
|
+
Pi shows install progress and reports the result. Run `/deps` again when you want to disable future preparation.
|
|
21
23
|
|
|
22
24
|
### Enable, disable, and update
|
|
23
25
|
|
|
@@ -36,6 +38,8 @@ Use `/deps` to toggle dependency preparation for future worktrees in the current
|
|
|
36
38
|
|
|
37
39
|
### Background install and status
|
|
38
40
|
|
|
41
|
+

|
|
42
|
+
|
|
39
43
|
- Worktree creation returns immediately.
|
|
40
44
|
- The hook validates lockfiles synchronously. Conflicting Node lockfiles, `packageManager` mismatches, and unsupported declarations still fail the worktree command fast.
|
|
41
45
|
- A detached installer runs frozen installs in the background.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Prepare dependencies at worktree creation
|
|
2
|
+
|
|
3
|
+
Pi Deps installs through an explicitly enabled repository's shared Git `post-checkout` hook rather than Pi session startup. Git invokes that hook for every `git worktree add` regardless of creator, so failures stay attached to workspace creation and Pi sessions pay no repeated startup cost; global Git hooks and creator-specific integrations were rejected because they either override unrelated hooks or miss other creators.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Install dependencies in the background after worktree creation
|
|
2
|
+
|
|
3
|
+
The `post-checkout` hook validates lockfiles synchronously (so conflicting lockfiles and malformed `packageManager` declarations still fail worktree creation fast), then spawns a detached installer child and exits immediately. The installer records its outcome in `<worktree gitdir>/pi-deps/status.json` with output appended to `install.log` in the same directory. Worktree creation no longer waits for installs; a Pi session opened in the worktree watches the status file and reports progress through an editor widget that auto-dismisses success after five seconds and keeps failures visible. Blocking creation was rejected because multi-minute frozen installs delayed every `git worktree add`; creator-side integrations were rejected because they miss non-Pi creators.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Dependency preparation flow</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&family=Noto+Sans+KR:wght@400;500;600&family=Noto+Serif+KR:wght@400&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
html, body { margin: 0; min-height: 100%; background: #f0eee9; }
|
|
10
|
+
body { display: grid; place-items: center; }
|
|
11
|
+
figure { margin: 0; width: min(100%, 1280px); }
|
|
12
|
+
svg { display: block; width: 100%; height: auto; }
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<figure>
|
|
17
|
+
<svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="dependency-preparation-flow-title dependency-preparation-flow-desc">
|
|
18
|
+
<title id="dependency-preparation-flow-title">Dependency preparation flow</title>
|
|
19
|
+
<desc id="dependency-preparation-flow-desc">Swimlane diagram showing that the shared hook synchronously validates root lockfiles plus packageManager declarations. Conflicting lockfiles, mismatches, and unsupported declarations fail the worktree command. Valid metadata starts detached installs and status reporting, but consumers may use the worktree before dependencies are ready.</desc>
|
|
20
|
+
<defs>
|
|
21
|
+
<style>
|
|
22
|
+
.lane-label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
|
|
23
|
+
.node-name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
|
|
24
|
+
.node-sub { fill: #4c5665; font: 400 9px 'Geist Mono', monospace; text-anchor: middle; }
|
|
25
|
+
.node { fill: #fff; stroke: #101828; stroke-width: 1; }
|
|
26
|
+
.node-input { fill: rgba(76,86,101,.10); stroke: #6a7282; stroke-width: 1; }
|
|
27
|
+
.node-async { fill: rgba(16,24,40,.02); stroke: rgba(16,24,40,.40); stroke-width: 1; stroke-dasharray: 4 3; }
|
|
28
|
+
.node-state { fill: rgba(16,24,40,.05); stroke: #4c5665; stroke-width: 1; }
|
|
29
|
+
.node-failure { fill: rgba(16,24,40,.02); stroke: #6a7282; stroke-width: 1; stroke-dasharray: 4 4; }
|
|
30
|
+
.node-risk { fill: rgba(29,78,216,.08); stroke: #1d4ed8; stroke-width: 1.2; }
|
|
31
|
+
.edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#arrow); }
|
|
32
|
+
.edge-plain { fill: none; stroke: #4c5665; stroke-width: 1.2; }
|
|
33
|
+
.edge-async { fill: none; stroke: #4c5665; stroke-width: 1.2; stroke-dasharray: 5 4; marker-end: url(#arrow); }
|
|
34
|
+
.boundary { fill: none; stroke: #1d4ed8; stroke-width: 1.2; stroke-dasharray: 4 4; }
|
|
35
|
+
.boundary-label { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .12em; }
|
|
36
|
+
.edge-label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .08em; }
|
|
37
|
+
.legend-text { fill: #4c5665; font: 400 9px 'Geist', sans-serif; }
|
|
38
|
+
</style>
|
|
39
|
+
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
40
|
+
<polygon points="0 0,8 3,0 6" fill="#4c5665"/>
|
|
41
|
+
</marker>
|
|
42
|
+
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
43
|
+
<polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
|
|
44
|
+
</marker>
|
|
45
|
+
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
46
|
+
<polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
|
|
47
|
+
</marker>
|
|
48
|
+
</defs>
|
|
49
|
+
|
|
50
|
+
<rect width="1280" height="720" fill="#f0eee9"/>
|
|
51
|
+
|
|
52
|
+
<!-- Swimlanes -->
|
|
53
|
+
<rect x="40" y="40" width="160" height="580" fill="#e6e4de"/>
|
|
54
|
+
<line x1="40" y1="40" x2="1240" y2="40" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
55
|
+
<line x1="40" y1="112" x2="1240" y2="112" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
56
|
+
<line x1="40" y1="212" x2="1240" y2="212" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
57
|
+
<line x1="40" y1="412" x2="1240" y2="412" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
58
|
+
<line x1="40" y1="488" x2="1240" y2="488" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
59
|
+
<line x1="40" y1="620" x2="1240" y2="620" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
60
|
+
<line x1="200" y1="40" x2="200" y2="620" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
61
|
+
<text class="lane-label" x="56" y="80">TRUSTED USER</text>
|
|
62
|
+
<text class="lane-label" x="56" y="164">GIT</text>
|
|
63
|
+
<text class="lane-label" x="56" y="268">SHARED HOOK</text>
|
|
64
|
+
<text class="lane-label" x="56" y="440">DETACHED INSTALLER</text>
|
|
65
|
+
<text class="lane-label" x="56" y="556">STATUS CONSUMERS</text>
|
|
66
|
+
|
|
67
|
+
<!-- Accent 1: the asynchronous handoff -->
|
|
68
|
+
<line class="boundary" x1="888" y1="112" x2="888" y2="488"/>
|
|
69
|
+
<rect x="896" y="124" width="160" height="52" fill="#f0eee9"/>
|
|
70
|
+
<text class="boundary-label" x="900" y="140">ASYNC BOUNDARY</text>
|
|
71
|
+
<text class="boundary-label" x="900" y="156">WORKTREE RETURNS</text>
|
|
72
|
+
<text class="boundary-label" x="900" y="172">INSTALLS CONTINUE</text>
|
|
73
|
+
|
|
74
|
+
<!-- Connectors -->
|
|
75
|
+
<path class="edge" d="M368 76 H376 Q384 76 384 84 V156 Q384 164 392 164"/>
|
|
76
|
+
<path class="edge" d="M552 164 H556 Q560 164 560 168 V272 Q560 280 568 280"/>
|
|
77
|
+
<path class="edge" d="M720 344 V360"/>
|
|
78
|
+
<path class="edge-plain" d="M872 280 H884"/>
|
|
79
|
+
<path class="edge-async" d="M892 272 H976 Q984 272 984 280 V420"/>
|
|
80
|
+
<path class="edge-async" d="M892 288 Q900 288 900 296 V488 Q900 496 908 496 H972 Q980 496 980 504 V516"/>
|
|
81
|
+
<path class="edge" d="M1056 452 H1080"/>
|
|
82
|
+
<path class="edge" d="M1156 484 V500"/>
|
|
83
|
+
<path class="edge" d="M1104 484 V488 Q1104 496 1096 496 H1088 Q1072 496 1072 512 V584 Q1072 592 1080 592"/>
|
|
84
|
+
|
|
85
|
+
<!-- Connector label -->
|
|
86
|
+
<text class="edge-label" x="752" y="352">INVALID</text>
|
|
87
|
+
|
|
88
|
+
<!-- Process nodes -->
|
|
89
|
+
<rect class="node-input" x="224" y="52" width="144" height="48" rx="6"/>
|
|
90
|
+
<text class="node-name" x="296" y="76">Enable /deps</text>
|
|
91
|
+
<text class="node-sub" x="296" y="92">TRUSTED REPOSITORY</text>
|
|
92
|
+
|
|
93
|
+
<rect class="node" x="392" y="136" width="160" height="56" rx="6"/>
|
|
94
|
+
<text class="node-name" x="472" y="160">Create worktree</text>
|
|
95
|
+
<text class="node-sub" x="472" y="180">CALL SHARED POST-CHECKOUT</text>
|
|
96
|
+
|
|
97
|
+
<polygon class="node" points="720,216 872,280 720,344 568,280"/>
|
|
98
|
+
<text class="node-name" x="720" y="264">Synchronous validation</text>
|
|
99
|
+
<text class="node-sub" x="720" y="280">ROOT LOCKFILES + packageManager DECLARATIONS</text>
|
|
100
|
+
<text class="node-sub" x="720" y="296">CONFLICTING LOCKFILES · MISMATCHES</text>
|
|
101
|
+
<text class="node-sub" x="720" y="308">UNSUPPORTED DECLARATIONS?</text>
|
|
102
|
+
|
|
103
|
+
<rect class="node-failure" x="632" y="360" width="176" height="44" rx="6"/>
|
|
104
|
+
<text class="node-name" x="720" y="380">Fail fast</text>
|
|
105
|
+
<text class="node-sub" x="720" y="396">WORKTREE COMMAND</text>
|
|
106
|
+
|
|
107
|
+
<rect x="884" y="268" width="8" height="24" rx="4" fill="#4c5665"/>
|
|
108
|
+
|
|
109
|
+
<rect class="node-async" x="912" y="420" width="144" height="64" rx="6"/>
|
|
110
|
+
<text class="node-name" x="984" y="444">Run frozen installs</text>
|
|
111
|
+
<text class="node-sub" x="984" y="464">NODE + UV · LOCKED</text>
|
|
112
|
+
<text class="node-sub" x="984" y="476">DETACHED</text>
|
|
113
|
+
|
|
114
|
+
<rect class="node-state" x="1080" y="420" width="152" height="64" rx="6"/>
|
|
115
|
+
<text class="node-name" x="1156" y="444">Update status + log</text>
|
|
116
|
+
<text class="node-sub" x="1156" y="464">status.json</text>
|
|
117
|
+
<text class="node-sub" x="1156" y="476">install.log</text>
|
|
118
|
+
|
|
119
|
+
<!-- Accent 2: readiness risk -->
|
|
120
|
+
<rect class="node-risk" x="896" y="516" width="168" height="76" rx="6"/>
|
|
121
|
+
<text class="node-name" x="980" y="540">Worktree may be used</text>
|
|
122
|
+
<text class="node-name" x="980" y="556">before installs finish</text>
|
|
123
|
+
<text class="node-sub" x="980" y="576">READINESS NOT GUARANTEED</text>
|
|
124
|
+
|
|
125
|
+
<rect class="node" x="1080" y="500" width="152" height="48" rx="6"/>
|
|
126
|
+
<text class="node-name" x="1156" y="524">Pi reports status</text>
|
|
127
|
+
<text class="node-sub" x="1156" y="540">THEN REMOVES IT</text>
|
|
128
|
+
|
|
129
|
+
<rect class="node" x="1080" y="568" width="152" height="48" rx="6"/>
|
|
130
|
+
<text class="node-name" x="1156" y="592">Other consumers</text>
|
|
131
|
+
<text class="node-sub" x="1156" y="608">MUST READ IT THEMSELVES</text>
|
|
132
|
+
|
|
133
|
+
<!-- Legend -->
|
|
134
|
+
<line x1="40" y1="636" x2="1240" y2="636" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
135
|
+
<text class="lane-label" x="40" y="664">LEGEND</text>
|
|
136
|
+
<rect class="node" x="124" y="652" width="24" height="16" rx="4"/>
|
|
137
|
+
<text class="legend-text" x="160" y="664">Step</text>
|
|
138
|
+
<polygon class="node" points="272,660 284,652 296,660 284,668"/>
|
|
139
|
+
<text class="legend-text" x="308" y="664">Decision</text>
|
|
140
|
+
<line x1="420" y1="660" x2="456" y2="660" stroke="#4c5665" stroke-width="1.2" stroke-dasharray="5 4" marker-end="url(#arrow)"/>
|
|
141
|
+
<text class="legend-text" x="468" y="664">Detached / async</text>
|
|
142
|
+
<rect class="node-state" x="612" y="652" width="24" height="16" rx="4"/>
|
|
143
|
+
<text class="legend-text" x="648" y="664">State files</text>
|
|
144
|
+
<rect class="node-failure" x="748" y="652" width="24" height="16" rx="4"/>
|
|
145
|
+
<text class="legend-text" x="784" y="664">Synchronous failure</text>
|
|
146
|
+
</svg>
|
|
147
|
+
</figure>
|
|
148
|
+
</body>
|
|
149
|
+
</html>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="dependency-preparation-flow-title dependency-preparation-flow-desc">
|
|
3
|
+
<title id="dependency-preparation-flow-title">Dependency preparation flow</title>
|
|
4
|
+
<desc id="dependency-preparation-flow-desc">Swimlane diagram showing that the shared hook synchronously validates root lockfiles plus packageManager declarations. Conflicting lockfiles, mismatches, and unsupported declarations fail the worktree command. Valid metadata starts detached installs and status reporting, but consumers may use the worktree before dependencies are ready.</desc>
|
|
5
|
+
<defs>
|
|
6
|
+
<style>
|
|
7
|
+
@import url("https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap");
|
|
8
|
+
.lane-label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
|
|
9
|
+
.node-name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
|
|
10
|
+
.node-sub { fill: #4c5665; font: 400 9px 'Geist Mono', monospace; text-anchor: middle; }
|
|
11
|
+
.node { fill: #fff; stroke: #101828; stroke-width: 1; }
|
|
12
|
+
.node-input { fill: rgba(76,86,101,.10); stroke: #6a7282; stroke-width: 1; }
|
|
13
|
+
.node-async { fill: rgba(16,24,40,.02); stroke: rgba(16,24,40,.40); stroke-width: 1; stroke-dasharray: 4 3; }
|
|
14
|
+
.node-state { fill: rgba(16,24,40,.05); stroke: #4c5665; stroke-width: 1; }
|
|
15
|
+
.node-failure { fill: rgba(16,24,40,.02); stroke: #6a7282; stroke-width: 1; stroke-dasharray: 4 4; }
|
|
16
|
+
.node-risk { fill: rgba(29,78,216,.08); stroke: #1d4ed8; stroke-width: 1.2; }
|
|
17
|
+
.edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#arrow); }
|
|
18
|
+
.edge-plain { fill: none; stroke: #4c5665; stroke-width: 1.2; }
|
|
19
|
+
.edge-async { fill: none; stroke: #4c5665; stroke-width: 1.2; stroke-dasharray: 5 4; marker-end: url(#arrow); }
|
|
20
|
+
.boundary { fill: none; stroke: #1d4ed8; stroke-width: 1.2; stroke-dasharray: 4 4; }
|
|
21
|
+
.boundary-label { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .12em; }
|
|
22
|
+
.edge-label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .08em; }
|
|
23
|
+
.legend-text { fill: #4c5665; font: 400 9px 'Geist', sans-serif; }
|
|
24
|
+
</style>
|
|
25
|
+
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
26
|
+
<polygon points="0 0,8 3,0 6" fill="#4c5665"/>
|
|
27
|
+
</marker>
|
|
28
|
+
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
29
|
+
<polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
|
|
30
|
+
</marker>
|
|
31
|
+
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
|
32
|
+
<polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
|
|
33
|
+
</marker>
|
|
34
|
+
</defs>
|
|
35
|
+
|
|
36
|
+
<rect width="1280" height="720" fill="#f0eee9"/>
|
|
37
|
+
|
|
38
|
+
<!-- Swimlanes -->
|
|
39
|
+
<rect x="40" y="40" width="160" height="580" fill="#e6e4de"/>
|
|
40
|
+
<line x1="40" y1="40" x2="1240" y2="40" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
41
|
+
<line x1="40" y1="112" x2="1240" y2="112" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
42
|
+
<line x1="40" y1="212" x2="1240" y2="212" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
43
|
+
<line x1="40" y1="412" x2="1240" y2="412" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
44
|
+
<line x1="40" y1="488" x2="1240" y2="488" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
45
|
+
<line x1="40" y1="620" x2="1240" y2="620" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
46
|
+
<line x1="200" y1="40" x2="200" y2="620" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
47
|
+
<text class="lane-label" x="56" y="80">TRUSTED USER</text>
|
|
48
|
+
<text class="lane-label" x="56" y="164">GIT</text>
|
|
49
|
+
<text class="lane-label" x="56" y="268">SHARED HOOK</text>
|
|
50
|
+
<text class="lane-label" x="56" y="440">DETACHED INSTALLER</text>
|
|
51
|
+
<text class="lane-label" x="56" y="556">STATUS CONSUMERS</text>
|
|
52
|
+
|
|
53
|
+
<!-- Accent 1: the asynchronous handoff -->
|
|
54
|
+
<line class="boundary" x1="888" y1="112" x2="888" y2="488"/>
|
|
55
|
+
<rect x="896" y="124" width="160" height="52" fill="#f0eee9"/>
|
|
56
|
+
<text class="boundary-label" x="900" y="140">ASYNC BOUNDARY</text>
|
|
57
|
+
<text class="boundary-label" x="900" y="156">WORKTREE RETURNS</text>
|
|
58
|
+
<text class="boundary-label" x="900" y="172">INSTALLS CONTINUE</text>
|
|
59
|
+
|
|
60
|
+
<!-- Connectors -->
|
|
61
|
+
<path class="edge" d="M368 76 H376 Q384 76 384 84 V156 Q384 164 392 164"/>
|
|
62
|
+
<path class="edge" d="M552 164 H556 Q560 164 560 168 V272 Q560 280 568 280"/>
|
|
63
|
+
<path class="edge" d="M720 344 V360"/>
|
|
64
|
+
<path class="edge-plain" d="M872 280 H884"/>
|
|
65
|
+
<path class="edge-async" d="M892 272 H976 Q984 272 984 280 V420"/>
|
|
66
|
+
<path class="edge-async" d="M892 288 Q900 288 900 296 V488 Q900 496 908 496 H972 Q980 496 980 504 V516"/>
|
|
67
|
+
<path class="edge" d="M1056 452 H1080"/>
|
|
68
|
+
<path class="edge" d="M1156 484 V500"/>
|
|
69
|
+
<path class="edge" d="M1104 484 V488 Q1104 496 1096 496 H1088 Q1072 496 1072 512 V584 Q1072 592 1080 592"/>
|
|
70
|
+
|
|
71
|
+
<!-- Connector label -->
|
|
72
|
+
<text class="edge-label" x="752" y="352">INVALID</text>
|
|
73
|
+
|
|
74
|
+
<!-- Process nodes -->
|
|
75
|
+
<rect class="node-input" x="224" y="52" width="144" height="48" rx="6"/>
|
|
76
|
+
<text class="node-name" x="296" y="76">Enable /deps</text>
|
|
77
|
+
<text class="node-sub" x="296" y="92">TRUSTED REPOSITORY</text>
|
|
78
|
+
|
|
79
|
+
<rect class="node" x="392" y="136" width="160" height="56" rx="6"/>
|
|
80
|
+
<text class="node-name" x="472" y="160">Create worktree</text>
|
|
81
|
+
<text class="node-sub" x="472" y="180">CALL SHARED POST-CHECKOUT</text>
|
|
82
|
+
|
|
83
|
+
<polygon class="node" points="720,216 872,280 720,344 568,280"/>
|
|
84
|
+
<text class="node-name" x="720" y="264">Synchronous validation</text>
|
|
85
|
+
<text class="node-sub" x="720" y="280">ROOT LOCKFILES + packageManager DECLARATIONS</text>
|
|
86
|
+
<text class="node-sub" x="720" y="296">CONFLICTING LOCKFILES · MISMATCHES</text>
|
|
87
|
+
<text class="node-sub" x="720" y="308">UNSUPPORTED DECLARATIONS?</text>
|
|
88
|
+
|
|
89
|
+
<rect class="node-failure" x="632" y="360" width="176" height="44" rx="6"/>
|
|
90
|
+
<text class="node-name" x="720" y="380">Fail fast</text>
|
|
91
|
+
<text class="node-sub" x="720" y="396">WORKTREE COMMAND</text>
|
|
92
|
+
|
|
93
|
+
<rect x="884" y="268" width="8" height="24" rx="4" fill="#4c5665"/>
|
|
94
|
+
|
|
95
|
+
<rect class="node-async" x="912" y="420" width="144" height="64" rx="6"/>
|
|
96
|
+
<text class="node-name" x="984" y="444">Run frozen installs</text>
|
|
97
|
+
<text class="node-sub" x="984" y="464">NODE + UV · LOCKED</text>
|
|
98
|
+
<text class="node-sub" x="984" y="476">DETACHED</text>
|
|
99
|
+
|
|
100
|
+
<rect class="node-state" x="1080" y="420" width="152" height="64" rx="6"/>
|
|
101
|
+
<text class="node-name" x="1156" y="444">Update status + log</text>
|
|
102
|
+
<text class="node-sub" x="1156" y="464">status.json</text>
|
|
103
|
+
<text class="node-sub" x="1156" y="476">install.log</text>
|
|
104
|
+
|
|
105
|
+
<!-- Accent 2: readiness risk -->
|
|
106
|
+
<rect class="node-risk" x="896" y="516" width="168" height="76" rx="6"/>
|
|
107
|
+
<text class="node-name" x="980" y="540">Worktree may be used</text>
|
|
108
|
+
<text class="node-name" x="980" y="556">before installs finish</text>
|
|
109
|
+
<text class="node-sub" x="980" y="576">READINESS NOT GUARANTEED</text>
|
|
110
|
+
|
|
111
|
+
<rect class="node" x="1080" y="500" width="152" height="48" rx="6"/>
|
|
112
|
+
<text class="node-name" x="1156" y="524">Pi reports status</text>
|
|
113
|
+
<text class="node-sub" x="1156" y="540">THEN REMOVES IT</text>
|
|
114
|
+
|
|
115
|
+
<rect class="node" x="1080" y="568" width="152" height="48" rx="6"/>
|
|
116
|
+
<text class="node-name" x="1156" y="592">Other consumers</text>
|
|
117
|
+
<text class="node-sub" x="1156" y="608">MUST READ IT THEMSELVES</text>
|
|
118
|
+
|
|
119
|
+
<!-- Legend -->
|
|
120
|
+
<line x1="40" y1="636" x2="1240" y2="636" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
|
|
121
|
+
<text class="lane-label" x="40" y="664">LEGEND</text>
|
|
122
|
+
<rect class="node" x="124" y="652" width="24" height="16" rx="4"/>
|
|
123
|
+
<text class="legend-text" x="160" y="664">Step</text>
|
|
124
|
+
<polygon class="node" points="272,660 284,652 296,660 284,668"/>
|
|
125
|
+
<text class="legend-text" x="308" y="664">Decision</text>
|
|
126
|
+
<line x1="420" y1="660" x2="456" y2="660" stroke="#4c5665" stroke-width="1.2" stroke-dasharray="5 4" marker-end="url(#arrow)"/>
|
|
127
|
+
<text class="legend-text" x="468" y="664">Detached / async</text>
|
|
128
|
+
<rect class="node-state" x="612" y="652" width="24" height="16" rx="4"/>
|
|
129
|
+
<text class="legend-text" x="648" y="664">State files</text>
|
|
130
|
+
<rect class="node-failure" x="748" y="652" width="24" height="16" rx="4"/>
|
|
131
|
+
<text class="legend-text" x="784" y="664">Synchronous failure</text>
|
|
132
|
+
</svg>
|
package/hooks/post-checkout.mjs
CHANGED
|
@@ -73,6 +73,7 @@ function nodeCommands() {
|
|
|
73
73
|
throw new Error(`Unsupported packageManager: ${JSON.stringify(declared)}`);
|
|
74
74
|
}
|
|
75
75
|
manager = declared.slice(0, declared.indexOf("@"));
|
|
76
|
+
if (/^yarn@1(?:\D|$)/.test(declared)) throw new Error("Yarn Classic 1.x is not supported");
|
|
76
77
|
if (manager !== locks[0]) {
|
|
77
78
|
throw new Error(`packageManager ${manager} does not match ${locks[0]} lockfile`);
|
|
78
79
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-deps",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Prepare Node and uv dependencies when opted-in Git worktrees are created.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"files": [
|
|
18
18
|
"LICENSE",
|
|
19
|
+
"docs",
|
|
19
20
|
"extensions",
|
|
20
21
|
"hooks",
|
|
21
22
|
"README.md"
|
|
@@ -31,11 +32,11 @@
|
|
|
31
32
|
},
|
|
32
33
|
"repository": {
|
|
33
34
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/HenryQW/pi-
|
|
35
|
-
"directory": "
|
|
35
|
+
"url": "git+https://github.com/HenryQW/pi-harness.git",
|
|
36
|
+
"directory": "extensions/pi-deps"
|
|
36
37
|
},
|
|
37
38
|
"bugs": {
|
|
38
|
-
"url": "https://github.com/HenryQW/pi-
|
|
39
|
+
"url": "https://github.com/HenryQW/pi-harness/issues"
|
|
39
40
|
},
|
|
40
41
|
"publishConfig": {
|
|
41
42
|
"access": "public"
|