@shardworks/codexes-apparatus 0.1.101
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/LICENSE +15 -0
- package/README.md +278 -0
- package/dist/git.d.ts +39 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +66 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/scriptorium-core.d.ts +68 -0
- package/dist/scriptorium-core.d.ts.map +1 -0
- package/dist/scriptorium-core.js +488 -0
- package/dist/scriptorium-core.js.map +1 -0
- package/dist/scriptorium.d.ts +12 -0
- package/dist/scriptorium.d.ts.map +1 -0
- package/dist/scriptorium.js +41 -0
- package/dist/scriptorium.js.map +1 -0
- package/dist/tools/codex-add.d.ts +13 -0
- package/dist/tools/codex-add.d.ts.map +1 -0
- package/dist/tools/codex-add.js +23 -0
- package/dist/tools/codex-add.js.map +1 -0
- package/dist/tools/codex-list.d.ts +6 -0
- package/dist/tools/codex-list.d.ts.map +1 -0
- package/dist/tools/codex-list.js +17 -0
- package/dist/tools/codex-list.js.map +1 -0
- package/dist/tools/codex-push.d.ts +10 -0
- package/dist/tools/codex-push.d.ts.map +1 -0
- package/dist/tools/codex-push.js +20 -0
- package/dist/tools/codex-push.js.map +1 -0
- package/dist/tools/codex-remove.d.ts +12 -0
- package/dist/tools/codex-remove.d.ts.map +1 -0
- package/dist/tools/codex-remove.js +22 -0
- package/dist/tools/codex-remove.js.map +1 -0
- package/dist/tools/codex-show.d.ts +9 -0
- package/dist/tools/codex-show.d.ts.map +1 -0
- package/dist/tools/codex-show.js +19 -0
- package/dist/tools/codex-show.js.map +1 -0
- package/dist/tools/draft-abandon.d.ts +14 -0
- package/dist/tools/draft-abandon.d.ts.map +1 -0
- package/dist/tools/draft-abandon.js +24 -0
- package/dist/tools/draft-abandon.js.map +1 -0
- package/dist/tools/draft-list.d.ts +9 -0
- package/dist/tools/draft-list.d.ts.map +1 -0
- package/dist/tools/draft-list.js +19 -0
- package/dist/tools/draft-list.js.map +1 -0
- package/dist/tools/draft-open.d.ts +15 -0
- package/dist/tools/draft-open.d.ts.map +1 -0
- package/dist/tools/draft-open.js +25 -0
- package/dist/tools/draft-open.js.map +1 -0
- package/dist/tools/draft-seal.d.ts +17 -0
- package/dist/tools/draft-seal.d.ts.map +1 -0
- package/dist/tools/draft-seal.js +27 -0
- package/dist/tools/draft-seal.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +13 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +180 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sean Boots
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# `@shardworks/codexes-apparatus`
|
|
2
|
+
|
|
3
|
+
The Scriptorium — guild codex management apparatus. Manages the guild's codexes (git repositories), draft bindings (isolated worktrees for concurrent work), and the sealing lifecycle that incorporates drafts into the sealed binding. Depends on `@shardworks/stacks-apparatus` for state tracking.
|
|
4
|
+
|
|
5
|
+
The Scriptorium is pure git infrastructure. It does not know what a codex contains or what work applies to it — that's the Surveyor's domain. It does not orchestrate which anima works in which draft — that's the caller's concern.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Add to your guild's dependencies:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@shardworks/codexes-apparatus": "workspace:*"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Register in `guild.json`:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"plugins": ["codexes"]
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
The Scriptorium provides `ScriptoriumApi` — retrieved via `guild().apparatus<ScriptoriumApi>('codexes')`.
|
|
34
|
+
|
|
35
|
+
### Codex Registry
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { guild } from '@shardworks/nexus-core';
|
|
39
|
+
import type { ScriptoriumApi } from '@shardworks/codexes-apparatus';
|
|
40
|
+
|
|
41
|
+
const scriptorium = guild().apparatus<ScriptoriumApi>('codexes');
|
|
42
|
+
|
|
43
|
+
// Register a codex (blocks until bare clone completes)
|
|
44
|
+
const codex = await scriptorium.add('my-app', 'git@github.com:org/my-app.git');
|
|
45
|
+
|
|
46
|
+
// List all codexes
|
|
47
|
+
const codexes = await scriptorium.list();
|
|
48
|
+
|
|
49
|
+
// Show details including active drafts
|
|
50
|
+
const detail = await scriptorium.show('my-app');
|
|
51
|
+
|
|
52
|
+
// Fetch latest refs from remote
|
|
53
|
+
await scriptorium.fetch('my-app');
|
|
54
|
+
|
|
55
|
+
// Push sealed binding to remote
|
|
56
|
+
await scriptorium.push({ codexName: 'my-app' });
|
|
57
|
+
|
|
58
|
+
// Remove a codex (abandons all drafts, removes bare clone)
|
|
59
|
+
await scriptorium.remove('my-app');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Draft Binding Lifecycle
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Open a draft (creates an isolated git worktree)
|
|
66
|
+
const draft = await scriptorium.openDraft({
|
|
67
|
+
codexName: 'my-app',
|
|
68
|
+
branch: 'writ-42', // optional — auto-generates if omitted
|
|
69
|
+
associatedWith: 'writ-42', // optional metadata
|
|
70
|
+
});
|
|
71
|
+
// draft.path → '.nexus/worktrees/my-app/writ-42'
|
|
72
|
+
|
|
73
|
+
// List active drafts
|
|
74
|
+
const drafts = await scriptorium.listDrafts('my-app');
|
|
75
|
+
|
|
76
|
+
// Seal a draft into the codex (ff-only; rebase on contention)
|
|
77
|
+
const result = await scriptorium.seal({
|
|
78
|
+
codexName: 'my-app',
|
|
79
|
+
sourceBranch: 'writ-42',
|
|
80
|
+
});
|
|
81
|
+
// result → { success: true, strategy: 'fast-forward', retries: 0, sealedCommit: 'abc123', inscriptionsSealed: 2 }
|
|
82
|
+
// inscriptionsSealed: 0 means a no-op seal (draft had no commits ahead of target)
|
|
83
|
+
|
|
84
|
+
// Abandon a draft (removes worktree + branch)
|
|
85
|
+
await scriptorium.abandonDraft({
|
|
86
|
+
codexName: 'my-app',
|
|
87
|
+
branch: 'writ-42',
|
|
88
|
+
force: true, // required if draft has unsealed inscriptions
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Session Integration
|
|
93
|
+
|
|
94
|
+
The Scriptorium and the Animator compose through a simple handoff — `DraftRecord.path` is the `cwd` for session launch:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import type { AnimatorApi } from '@shardworks/animator-apparatus';
|
|
98
|
+
import type { ScriptoriumApi } from '@shardworks/codexes-apparatus';
|
|
99
|
+
|
|
100
|
+
const scriptorium = guild().apparatus<ScriptoriumApi>('codexes');
|
|
101
|
+
const animator = guild().apparatus<AnimatorApi>('animator');
|
|
102
|
+
|
|
103
|
+
// 1. Open a draft
|
|
104
|
+
const draft = await scriptorium.openDraft({ codexName: 'nexus' });
|
|
105
|
+
|
|
106
|
+
// 2. Launch a session in the draft's working directory
|
|
107
|
+
const { result } = animator.summon({
|
|
108
|
+
role: 'artificer',
|
|
109
|
+
prompt: 'Build the frobnicator',
|
|
110
|
+
cwd: draft.path,
|
|
111
|
+
});
|
|
112
|
+
await result;
|
|
113
|
+
|
|
114
|
+
// 3. Seal the draft
|
|
115
|
+
await scriptorium.seal({
|
|
116
|
+
codexName: 'nexus',
|
|
117
|
+
sourceBranch: draft.branch,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 4. Push to remote
|
|
121
|
+
await scriptorium.push({ codexName: 'nexus' });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
The `codexes` section in `guild.json`:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"codexes": {
|
|
133
|
+
"settings": {
|
|
134
|
+
"maxMergeRetries": 3,
|
|
135
|
+
"draftRoot": ".nexus/worktrees"
|
|
136
|
+
},
|
|
137
|
+
"registered": {
|
|
138
|
+
"nexus": {
|
|
139
|
+
"remoteUrl": "git@github.com:shardworks/nexus.git"
|
|
140
|
+
},
|
|
141
|
+
"my-app": {
|
|
142
|
+
"remoteUrl": "git@github.com:patron/my-app.git"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Settings
|
|
150
|
+
|
|
151
|
+
| Field | Type | Default | Description |
|
|
152
|
+
|-------|------|---------|-------------|
|
|
153
|
+
| `maxMergeRetries` | `number` | `3` | Max rebase-retry attempts during sealing under contention |
|
|
154
|
+
| `draftRoot` | `string` | `".nexus/worktrees"` | Directory where draft worktrees are created, relative to guild root |
|
|
155
|
+
|
|
156
|
+
### Registered Codexes
|
|
157
|
+
|
|
158
|
+
Each key in `registered` is the codex name. Codexes can be registered via the `codex-add` tool or by hand-editing `guild.json` — the Scriptorium clones any missing bare repos on startup.
|
|
159
|
+
|
|
160
|
+
| Field | Type | Description |
|
|
161
|
+
|-------|------|-------------|
|
|
162
|
+
| `remoteUrl` | `string` | Git remote URL of the codex's repository |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Support Kit
|
|
167
|
+
|
|
168
|
+
The Scriptorium contributes 9 tools via its support kit:
|
|
169
|
+
|
|
170
|
+
### Codex Tools
|
|
171
|
+
|
|
172
|
+
| Tool | Permission | Description |
|
|
173
|
+
|------|-----------|-------------|
|
|
174
|
+
| `codex-add` | `write` | Register a git repository as a guild codex |
|
|
175
|
+
| `codex-list` | `read` | List all registered codexes |
|
|
176
|
+
| `codex-show` | `read` | Show codex details including active drafts |
|
|
177
|
+
| `codex-remove` | `delete` | Remove a codex from the guild |
|
|
178
|
+
| `codex-push` | `write` | Push a branch to the codex's remote |
|
|
179
|
+
|
|
180
|
+
### Draft Tools
|
|
181
|
+
|
|
182
|
+
| Tool | Permission | Description |
|
|
183
|
+
|------|-----------|-------------|
|
|
184
|
+
| `draft-open` | `write` | Open a draft binding (creates an isolated worktree) |
|
|
185
|
+
| `draft-list` | `read` | List active draft bindings |
|
|
186
|
+
| `draft-abandon` | `delete` | Abandon a draft (removes worktree + branch) |
|
|
187
|
+
| `draft-seal` | `write` | Seal a draft into the codex (ff-only or rebase) |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Types
|
|
192
|
+
|
|
193
|
+
### `ScriptoriumApi`
|
|
194
|
+
|
|
195
|
+
The full `provides` interface — see [API](#api) above for usage.
|
|
196
|
+
|
|
197
|
+
### Record Types
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
interface CodexRecord {
|
|
201
|
+
name: string
|
|
202
|
+
remoteUrl: string
|
|
203
|
+
cloneStatus: 'ready' | 'cloning' | 'error'
|
|
204
|
+
activeDrafts: number
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface CodexDetail extends CodexRecord {
|
|
208
|
+
defaultBranch: string
|
|
209
|
+
lastFetched: string | null
|
|
210
|
+
drafts: DraftRecord[]
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
interface DraftRecord {
|
|
214
|
+
id: string
|
|
215
|
+
codexName: string
|
|
216
|
+
branch: string
|
|
217
|
+
path: string
|
|
218
|
+
createdAt: string
|
|
219
|
+
associatedWith?: string
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Request / Result Types
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
interface OpenDraftRequest {
|
|
227
|
+
codexName: string
|
|
228
|
+
branch?: string
|
|
229
|
+
startPoint?: string
|
|
230
|
+
associatedWith?: string
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
interface AbandonDraftRequest {
|
|
234
|
+
codexName: string
|
|
235
|
+
branch: string
|
|
236
|
+
force?: boolean
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
interface SealRequest {
|
|
240
|
+
codexName: string
|
|
241
|
+
sourceBranch: string
|
|
242
|
+
targetBranch?: string
|
|
243
|
+
maxRetries?: number
|
|
244
|
+
keepDraft?: boolean
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
interface SealResult {
|
|
248
|
+
success: boolean
|
|
249
|
+
strategy: 'fast-forward' | 'rebase'
|
|
250
|
+
retries: number
|
|
251
|
+
sealedCommit: string
|
|
252
|
+
/** Number of inscriptions (commits) incorporated from the draft. 0 = no-op seal. */
|
|
253
|
+
inscriptionsSealed: number
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
interface PushRequest {
|
|
257
|
+
codexName: string
|
|
258
|
+
branch?: string
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Configuration Types
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
interface CodexesConfig {
|
|
266
|
+
settings?: CodexesSettings
|
|
267
|
+
registered?: Record<string, CodexConfigEntry>
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface CodexesSettings {
|
|
271
|
+
maxMergeRetries?: number
|
|
272
|
+
draftRoot?: string
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
interface CodexConfigEntry {
|
|
276
|
+
remoteUrl: string
|
|
277
|
+
}
|
|
278
|
+
```
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight git helper — typed wrapper around child_process.execFile.
|
|
3
|
+
*
|
|
4
|
+
* All git operations in the Scriptorium go through this module for
|
|
5
|
+
* safety (no shell injection) and consistent error handling.
|
|
6
|
+
*/
|
|
7
|
+
export interface GitResult {
|
|
8
|
+
stdout: string;
|
|
9
|
+
stderr: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class GitError extends Error {
|
|
12
|
+
readonly command: string[];
|
|
13
|
+
readonly stderr: string;
|
|
14
|
+
readonly exitCode: number | null;
|
|
15
|
+
constructor(message: string, command: string[], stderr: string, exitCode: number | null);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run a git command with typed error handling.
|
|
19
|
+
*
|
|
20
|
+
* @param args - git subcommand and arguments (e.g. ['clone', '--bare', url])
|
|
21
|
+
* @param cwd - working directory for the command
|
|
22
|
+
*/
|
|
23
|
+
export declare function git(args: string[], cwd?: string): Promise<GitResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the default branch of a bare clone by reading HEAD.
|
|
26
|
+
*
|
|
27
|
+
* Returns the branch name (e.g. 'main'), not the full ref.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveDefaultBranch(bareClonePath: string): Promise<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the commit SHA at the tip of a branch in a bare clone.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveRef(bareClonePath: string, ref: string): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a branch has commits ahead of another branch.
|
|
36
|
+
* Returns the number of commits ahead.
|
|
37
|
+
*/
|
|
38
|
+
export declare function commitsAhead(bareClonePath: string, branch: string, base: string): Promise<number>;
|
|
39
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,QAAS,SAAQ,KAAK;IAG/B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;gBAHhC,OAAO,EAAE,MAAM,EACN,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,IAAI;CAKnC;AAED;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgB1E;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIjF;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpF;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight git helper — typed wrapper around child_process.execFile.
|
|
3
|
+
*
|
|
4
|
+
* All git operations in the Scriptorium go through this module for
|
|
5
|
+
* safety (no shell injection) and consistent error handling.
|
|
6
|
+
*/
|
|
7
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
8
|
+
import { promisify } from 'node:util';
|
|
9
|
+
const execFile = promisify(execFileCb);
|
|
10
|
+
export class GitError extends Error {
|
|
11
|
+
command;
|
|
12
|
+
stderr;
|
|
13
|
+
exitCode;
|
|
14
|
+
constructor(message, command, stderr, exitCode) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.command = command;
|
|
17
|
+
this.stderr = stderr;
|
|
18
|
+
this.exitCode = exitCode;
|
|
19
|
+
this.name = 'GitError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Run a git command with typed error handling.
|
|
24
|
+
*
|
|
25
|
+
* @param args - git subcommand and arguments (e.g. ['clone', '--bare', url])
|
|
26
|
+
* @param cwd - working directory for the command
|
|
27
|
+
*/
|
|
28
|
+
export async function git(args, cwd) {
|
|
29
|
+
try {
|
|
30
|
+
const { stdout, stderr } = await execFile('git', args, {
|
|
31
|
+
cwd,
|
|
32
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
33
|
+
});
|
|
34
|
+
return { stdout: stdout.trim(), stderr: stderr.trim() };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const e = err;
|
|
38
|
+
throw new GitError(`git ${args[0]} failed: ${e.stderr || e.message || 'unknown error'}`, ['git', ...args], e.stderr ?? '', e.code ?? null);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the default branch of a bare clone by reading HEAD.
|
|
43
|
+
*
|
|
44
|
+
* Returns the branch name (e.g. 'main'), not the full ref.
|
|
45
|
+
*/
|
|
46
|
+
export async function resolveDefaultBranch(bareClonePath) {
|
|
47
|
+
const { stdout } = await git(['symbolic-ref', 'HEAD'], bareClonePath);
|
|
48
|
+
// stdout is e.g. 'refs/heads/main'
|
|
49
|
+
return stdout.replace('refs/heads/', '');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the commit SHA at the tip of a branch in a bare clone.
|
|
53
|
+
*/
|
|
54
|
+
export async function resolveRef(bareClonePath, ref) {
|
|
55
|
+
const { stdout } = await git(['rev-parse', ref], bareClonePath);
|
|
56
|
+
return stdout;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if a branch has commits ahead of another branch.
|
|
60
|
+
* Returns the number of commits ahead.
|
|
61
|
+
*/
|
|
62
|
+
export async function commitsAhead(bareClonePath, branch, base) {
|
|
63
|
+
const { stdout } = await git(['rev-list', '--count', `${base}..${branch}`], bareClonePath);
|
|
64
|
+
return parseInt(stdout, 10);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;AAOvC,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGtB;IACA;IACA;IAJX,YACE,OAAe,EACN,OAAiB,EACjB,MAAc,EACd,QAAuB;QAEhC,KAAK,CAAC,OAAO,CAAC,CAAC;QAJN,YAAO,GAAP,OAAO,CAAU;QACjB,WAAM,GAAN,MAAM,CAAQ;QACd,aAAQ,GAAR,QAAQ,CAAe;QAGhC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,GAAY;IACpD,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE;YACrD,GAAG;YACH,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;SACrC,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAAkE,CAAC;QAC7E,MAAM,IAAI,QAAQ,CAChB,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,eAAe,EAAE,EACpE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,EAChB,CAAC,CAAC,MAAM,IAAI,EAAE,EACd,CAAC,CAAC,IAAI,IAAI,IAAI,CACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,aAAqB;IAC9D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC;IACtE,mCAAmC;IACnC,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,aAAqB,EAAE,GAAW;IACjE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,aAAqB,EACrB,MAAc,EACd,IAAY;IAEZ,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAC1B,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,KAAK,MAAM,EAAE,CAAC,EAC7C,aAAa,CACd,CAAC;IACF,OAAO,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC9B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @shardworks/codexes-apparatus — The Scriptorium.
|
|
3
|
+
*
|
|
4
|
+
* Guild codex management: bare clone registry, draft binding lifecycle
|
|
5
|
+
* (git worktrees), sealing (ff-only merge or rebase+ff), and push.
|
|
6
|
+
* Default export is the apparatus plugin.
|
|
7
|
+
*
|
|
8
|
+
* See: docs/architecture/apparatus/scriptorium.md
|
|
9
|
+
*/
|
|
10
|
+
export type { ScriptoriumApi, CodexRecord, CodexDetail, DraftRecord, OpenDraftRequest, AbandonDraftRequest, SealRequest, PushRequest, SealResult, CodexesConfig, CodexesSettings, CodexConfigEntry, } from './types.ts';
|
|
11
|
+
export { createScriptorium } from './scriptorium.ts';
|
|
12
|
+
declare const _default: import("@shardworks/nexus-core").Plugin;
|
|
13
|
+
export default _default;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,YAAY,EAEV,cAAc,EAGd,WAAW,EACX,WAAW,EAGX,WAAW,EAGX,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,WAAW,EAGX,UAAU,EAGV,aAAa,EACb,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;;AAIrD,wBAAmC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @shardworks/codexes-apparatus — The Scriptorium.
|
|
3
|
+
*
|
|
4
|
+
* Guild codex management: bare clone registry, draft binding lifecycle
|
|
5
|
+
* (git worktrees), sealing (ff-only merge or rebase+ff), and push.
|
|
6
|
+
* Default export is the apparatus plugin.
|
|
7
|
+
*
|
|
8
|
+
* See: docs/architecture/apparatus/scriptorium.md
|
|
9
|
+
*/
|
|
10
|
+
import { createScriptorium } from "./scriptorium.js";
|
|
11
|
+
// ── Apparatus factory ─────────────────────────────────────────────────
|
|
12
|
+
export { createScriptorium } from "./scriptorium.js";
|
|
13
|
+
// ── Default export: the apparatus plugin ──────────────────────────────
|
|
14
|
+
export default createScriptorium();
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AA8BrD,yEAAyE;AAEzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,yEAAyE;AAEzE,eAAe,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Scriptorium — core logic.
|
|
3
|
+
*
|
|
4
|
+
* Manages the codex registry (bare clones), draft binding lifecycle
|
|
5
|
+
* (worktrees), and sealing (ff-only merge or rebase+ff). All git
|
|
6
|
+
* operations go through the git helper for safety.
|
|
7
|
+
*
|
|
8
|
+
* Draft tracking is in-memory — drafts are reconstructed from
|
|
9
|
+
* filesystem state at startup and maintained in memory during the
|
|
10
|
+
* process lifetime.
|
|
11
|
+
*
|
|
12
|
+
* See: docs/architecture/apparatus/scriptorium.md
|
|
13
|
+
*/
|
|
14
|
+
import type { CodexRecord, CodexDetail, DraftRecord, OpenDraftRequest, AbandonDraftRequest, SealRequest, SealResult, PushRequest, ScriptoriumApi } from './types.ts';
|
|
15
|
+
export declare class ScriptoriumCore {
|
|
16
|
+
private codexes;
|
|
17
|
+
private drafts;
|
|
18
|
+
private maxMergeRetries;
|
|
19
|
+
private draftRoot;
|
|
20
|
+
private get home();
|
|
21
|
+
private codexesDir;
|
|
22
|
+
private bareClonePath;
|
|
23
|
+
private draftWorktreePath;
|
|
24
|
+
start(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Load a codex from config. Checks for existing bare clone;
|
|
27
|
+
* initiates background clone if missing.
|
|
28
|
+
*/
|
|
29
|
+
private loadCodex;
|
|
30
|
+
/**
|
|
31
|
+
* Reconcile in-memory draft tracking with filesystem state.
|
|
32
|
+
* Scans the worktree directories and rebuilds the draft map.
|
|
33
|
+
*/
|
|
34
|
+
private reconcileDrafts;
|
|
35
|
+
/**
|
|
36
|
+
* Ensure a codex's bare clone is ready. Blocks if a background
|
|
37
|
+
* clone is in progress. Throws if the codex is unknown or clone failed.
|
|
38
|
+
*/
|
|
39
|
+
private ensureReady;
|
|
40
|
+
private performClone;
|
|
41
|
+
/**
|
|
42
|
+
* Advance refs/heads/<branch> to the remote's position if the remote is
|
|
43
|
+
* strictly ahead of the local sealed binding.
|
|
44
|
+
*
|
|
45
|
+
* This handles commits pushed to the remote outside the Scriptorium:
|
|
46
|
+
* if the remote has advanced past the local sealed binding, sealing must
|
|
47
|
+
* rebase the draft onto the remote position — not the stale local one.
|
|
48
|
+
*
|
|
49
|
+
* If the local sealed binding is already ahead of (or equal to) the remote
|
|
50
|
+
* (e.g. contains unpushed seals from contention scenarios), it is kept.
|
|
51
|
+
*/
|
|
52
|
+
private advanceToRemote;
|
|
53
|
+
private performFetch;
|
|
54
|
+
createApi(): ScriptoriumApi;
|
|
55
|
+
add(name: string, remoteUrl: string): Promise<CodexRecord>;
|
|
56
|
+
list(): Promise<CodexRecord[]>;
|
|
57
|
+
show(name: string): Promise<CodexDetail>;
|
|
58
|
+
remove(name: string): Promise<void>;
|
|
59
|
+
fetchCodex(name: string): Promise<void>;
|
|
60
|
+
push(request: PushRequest): Promise<void>;
|
|
61
|
+
openDraft(request: OpenDraftRequest): Promise<DraftRecord>;
|
|
62
|
+
listDrafts(codexName?: string): Promise<DraftRecord[]>;
|
|
63
|
+
abandonDraft(request: AbandonDraftRequest): Promise<void>;
|
|
64
|
+
seal(request: SealRequest): Promise<SealResult>;
|
|
65
|
+
private draftsForCodex;
|
|
66
|
+
private toCodexRecord;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=scriptorium-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptorium-core.d.ts","sourceRoot":"","sources":["../src/scriptorium-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,WAAW,EAGX,cAAc,EACf,MAAM,YAAY,CAAC;AAepB,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,MAAM,CAAkC;IAEhD,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,SAAS,CAA8B;IAI/C,OAAO,KAAK,IAAI,GAEf;IAED,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IAMzB,KAAK,IAAI,IAAI;IAoBb;;;OAGG;IACH,OAAO,CAAC,SAAS;IAwBjB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAoCvB;;;OAGG;YACW,WAAW;YAsBX,YAAY;IAM1B;;;;;;;;;;OAUG;YACW,eAAe;YAsBf,YAAY;IAuB1B,SAAS,IAAI,cAAc;IAiBrB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAkC1D,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAQ9B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAiBxC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BnC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzC,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IA+C1D,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAOtD,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+DzD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA8HrD,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,aAAa;CAQtB"}
|