@tiphys/kernel 0.0.0 → 0.2.0
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/AGENTS.md +663 -0
- package/LICENSE +202 -0
- package/assurance-modes.yaml +299 -0
- package/checklists/clean-room.yaml +325 -0
- package/checklists/env-failure-diagnosis.yaml +68 -0
- package/checklists/flake-playbook.yaml +68 -0
- package/checklists/hazard-review.yaml +144 -0
- package/checklists/plan-review.yaml +103 -0
- package/dist/bin/tiphys.d.ts +2 -0
- package/dist/bin/tiphys.js +92 -0
- package/dist/src/adapters/load.d.ts +202 -0
- package/dist/src/adapters/load.js +440 -0
- package/dist/src/brief.d.ts +32 -0
- package/dist/src/brief.js +66 -0
- package/dist/src/checklists.d.ts +169 -0
- package/dist/src/checklists.js +310 -0
- package/dist/src/checks.d.ts +1539 -0
- package/dist/src/checks.js +5025 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +68 -0
- package/dist/src/commands/brief.d.ts +92 -0
- package/dist/src/commands/brief.js +343 -0
- package/dist/src/commands/checklist.d.ts +42 -0
- package/dist/src/commands/checklist.js +168 -0
- package/dist/src/commands/cutover.d.ts +35 -0
- package/dist/src/commands/cutover.js +448 -0
- package/dist/src/commands/doctor.d.ts +264 -0
- package/dist/src/commands/doctor.js +1546 -0
- package/dist/src/commands/gates.d.ts +9 -0
- package/dist/src/commands/gates.js +360 -0
- package/dist/src/commands/init.d.ts +30 -0
- package/dist/src/commands/init.js +177 -0
- package/dist/src/commands/lock.d.ts +34 -0
- package/dist/src/commands/lock.js +340 -0
- package/dist/src/commands/mode.d.ts +40 -0
- package/dist/src/commands/mode.js +134 -0
- package/dist/src/commands/next.d.ts +130 -0
- package/dist/src/commands/next.js +597 -0
- package/dist/src/commands/plan.d.ts +20 -0
- package/dist/src/commands/plan.js +105 -0
- package/dist/src/commands/pool.d.ts +1 -0
- package/dist/src/commands/pool.js +139 -0
- package/dist/src/commands/resume.d.ts +1 -0
- package/dist/src/commands/resume.js +88 -0
- package/dist/src/commands/spawn.d.ts +1 -0
- package/dist/src/commands/spawn.js +195 -0
- package/dist/src/commands/status.d.ts +21 -0
- package/dist/src/commands/status.js +122 -0
- package/dist/src/commands/sync.d.ts +47 -0
- package/dist/src/commands/sync.js +341 -0
- package/dist/src/commands/teardown.d.ts +1 -0
- package/dist/src/commands/teardown.js +87 -0
- package/dist/src/commands/tuition.d.ts +21 -0
- package/dist/src/commands/tuition.js +218 -0
- package/dist/src/commands/validate.d.ts +78 -0
- package/dist/src/commands/validate.js +430 -0
- package/dist/src/commands/watch.d.ts +1 -0
- package/dist/src/commands/watch.js +172 -0
- package/dist/src/cutover.d.ts +584 -0
- package/dist/src/cutover.js +1444 -0
- package/dist/src/exclusion.d.ts +389 -0
- package/dist/src/exclusion.js +843 -0
- package/dist/src/exec/env.d.ts +278 -0
- package/dist/src/exec/env.js +334 -0
- package/dist/src/fleet.d.ts +223 -0
- package/dist/src/fleet.js +298 -0
- package/dist/src/gates/adapters/http-json.d.ts +5 -0
- package/dist/src/gates/adapters/http-json.js +283 -0
- package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
- package/dist/src/gates/adapters/migrations-command.js +373 -0
- package/dist/src/gates/citations.d.ts +408 -0
- package/dist/src/gates/citations.js +1169 -0
- package/dist/src/gates/coverage.d.ts +375 -0
- package/dist/src/gates/coverage.js +836 -0
- package/dist/src/gates/credentials.d.ts +233 -0
- package/dist/src/gates/credentials.js +752 -0
- package/dist/src/gates/deploy.d.ts +1 -0
- package/dist/src/gates/deploy.js +33 -0
- package/dist/src/gates/gate-classes.d.ts +56 -0
- package/dist/src/gates/gate-classes.js +633 -0
- package/dist/src/gates/manifest.d.ts +99 -0
- package/dist/src/gates/manifest.js +208 -0
- package/dist/src/gates/merge-preconditions.d.ts +319 -0
- package/dist/src/gates/merge-preconditions.js +932 -0
- package/dist/src/gates/migrations.d.ts +1 -0
- package/dist/src/gates/migrations.js +36 -0
- package/dist/src/gates/pin.d.ts +114 -0
- package/dist/src/gates/pin.js +154 -0
- package/dist/src/gates/red-witness.d.ts +22 -0
- package/dist/src/gates/red-witness.js +482 -0
- package/dist/src/gates/release.d.ts +283 -0
- package/dist/src/gates/release.js +820 -0
- package/dist/src/gates/result.d.ts +116 -0
- package/dist/src/gates/result.js +91 -0
- package/dist/src/gates/run.d.ts +614 -0
- package/dist/src/gates/run.js +1614 -0
- package/dist/src/gates/schemas/citation-config.schema.json +59 -0
- package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
- package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
- package/dist/src/gates/schemas/gate-result.schema.json +160 -0
- package/dist/src/gates/schemas/phase-declaration.schema.json +87 -0
- package/dist/src/gates/schemas/release-record.schema.json +119 -0
- package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
- package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
- package/dist/src/gates/scope.d.ts +131 -0
- package/dist/src/gates/scope.js +1018 -0
- package/dist/src/gates/suite.d.ts +217 -0
- package/dist/src/gates/suite.js +968 -0
- package/dist/src/gates/validate.d.ts +121 -0
- package/dist/src/gates/validate.js +414 -0
- package/dist/src/hooks.d.ts +84 -0
- package/dist/src/hooks.js +125 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +30 -0
- package/dist/src/liveness.d.ts +321 -0
- package/dist/src/liveness.js +396 -0
- package/dist/src/lock.d.ts +256 -0
- package/dist/src/lock.js +792 -0
- package/dist/src/model-resolution.d.ts +159 -0
- package/dist/src/model-resolution.js +307 -0
- package/dist/src/modes.d.ts +149 -0
- package/dist/src/modes.js +258 -0
- package/dist/src/path-identity.d.ts +34 -0
- package/dist/src/path-identity.js +48 -0
- package/dist/src/plan.d.ts +73 -0
- package/dist/src/plan.js +153 -0
- package/dist/src/pool.d.ts +326 -0
- package/dist/src/pool.js +988 -0
- package/dist/src/roles.d.ts +461 -0
- package/dist/src/roles.js +776 -0
- package/dist/src/spawn.d.ts +482 -0
- package/dist/src/spawn.js +1003 -0
- package/dist/src/status.d.ts +116 -0
- package/dist/src/status.js +148 -0
- package/dist/src/task.d.ts +504 -0
- package/dist/src/task.js +307 -0
- package/dist/src/teardown.d.ts +39 -0
- package/dist/src/teardown.js +422 -0
- package/dist/src/tuition.d.ts +159 -0
- package/dist/src/tuition.js +311 -0
- package/dist/src/validate.d.ts +263 -0
- package/dist/src/validate.js +742 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.js +38 -0
- package/dist/src/watcher.d.ts +275 -0
- package/dist/src/watcher.js +849 -0
- package/dist/src/witness/run.d.ts +299 -0
- package/dist/src/witness/run.js +1373 -0
- package/dist/src/witness/spec.d.ts +270 -0
- package/dist/src/witness/spec.js +475 -0
- package/dist/tsconfig.src.tsbuildinfo +1 -0
- package/gate-registry.yaml +526 -0
- package/gates.manifest.json +257 -0
- package/package.json +72 -3
- package/role-model-config.yaml +88 -0
- package/roles/README.md +128 -0
- package/roles/_shared-dispatch-contract.md +87 -0
- package/roles/adversarial-plan-reviewer.md +80 -0
- package/roles/clean-room-reviewer.md +140 -0
- package/roles/implementer.md +463 -0
- package/roles/investigator.md +138 -0
- package/roles/plan-writer.md +95 -0
- package/schemas/README.md +82 -0
- package/schemas/assurance-modes.schema.json +264 -0
- package/schemas/charter.schema.json +185 -0
- package/schemas/checklist.schema.json +114 -0
- package/schemas/cutover-state.schema.json +64 -0
- package/schemas/decision-record.schema.json +88 -0
- package/schemas/executor-record.schema.json +36 -0
- package/schemas/final-report.schema.json +90 -0
- package/schemas/finding.schema.json +106 -0
- package/schemas/gate-registry.schema.json +260 -0
- package/schemas/mechanism-index.schema.json +94 -0
- package/schemas/model-resolution.schema.json +362 -0
- package/schemas/plan.schema.json +300 -0
- package/schemas/report.schema.json +579 -0
- package/schemas/role-brief.schema.json +105 -0
- package/schemas/role-model-config.schema.json +90 -0
- package/schemas/status-line.schema.json +40 -0
- package/schemas/tuition.schema.json +191 -0
- package/schemas/verdict.schema.json +295 -0
- package/schemas/work-history.schema.json +183 -0
- package/schemas/write-bypass.schema.json +69 -0
- package/templates/charter.example.yaml +54 -0
- package/templates/decision-record.example.yaml +27 -0
- package/templates/final-report.example.yaml +80 -0
- package/templates/plan.example.yaml +87 -0
- package/templates/report.example.yaml +236 -0
- package/templates/warnings.md +74 -0
- package/templates/work-history.example.yaml +185 -0
- package/tuition/README.md +76 -0
- package/tuition/T-001.yaml +48 -0
- package/tuition/T-002.yaml +51 -0
- package/tuition/T-003.yaml +100 -0
- package/tuition/T-004.yaml +52 -0
- package/tuition/T-005.yaml +72 -0
- package/tuition/T-006.yaml +81 -0
- package/tuition/T-007.yaml +56 -0
- package/tuition/T-008.yaml +111 -0
- package/tuition/T-009.yaml +50 -0
- package/tuition/T-015.yaml +36 -0
- package/tuition/T-016.yaml +36 -0
- package/tuition/T-017.yaml +46 -0
- package/tuition/T-018.yaml +84 -0
- package/tuition/T-021.yaml +40 -0
- package/tuition/T-022.yaml +36 -0
- package/tuition/mechanism-index.yaml +256 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import type { Fleet } from "./fleet.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Worktree pool over a project clone (kernel plan v1, M1-P3 step 3).
|
|
4
|
+
* BUILD from the contract (plan decision D-1, FM-026): a clean disposable
|
|
5
|
+
* worktree per task at <fleet>/worktrees/<task-id>, parallel-safe through
|
|
6
|
+
* unique paths, O_EXCL record creation, and git worktree add's own
|
|
7
|
+
* locking. That safety is claimed only at the width M1 actually uses:
|
|
8
|
+
* criterion 15's two concurrent creates, which are witnessed. This
|
|
9
|
+
* phase's own verification measured failures above roughly six-way
|
|
10
|
+
* concurrency on both the fetch and the worktree add, and hardening
|
|
11
|
+
* for that width is deferred to M5 (see the deferral list in
|
|
12
|
+
* delivery/work-history/m1-p3.md). Do not read this as a guarantee at
|
|
13
|
+
* arbitrary concurrency. Substrate-neutral: pure filesystem and git
|
|
14
|
+
* (DR-0007).
|
|
15
|
+
*
|
|
16
|
+
* Base resolution is the five binding steps of EXT-F-03: resolve the
|
|
17
|
+
* project's configured remote and its default branch, fetch that branch,
|
|
18
|
+
* record the fetched base SHA in the pool record (and the CLI emits it on
|
|
19
|
+
* stdout; M1-P4 spawn copies it into tasks/<id>/meta.json as baseSha),
|
|
20
|
+
* create the task branch and worktree directly from that exact SHA, and
|
|
21
|
+
* on fetch failure fail rather than silently use a stale local branch,
|
|
22
|
+
* unless --offline was explicitly passed, in which case the last fetched
|
|
23
|
+
* remote-tracking SHA is used and offline: true is recorded. The clone's
|
|
24
|
+
* local branches are never consulted: a stale local branch is never the
|
|
25
|
+
* base, whether behind or ahead of the remote.
|
|
26
|
+
*
|
|
27
|
+
* The pool record lives BESIDE the worktree (worktrees/<task-id>.pool.json,
|
|
28
|
+
* plain JSON per D-3), never inside it, so the record can never dirty the
|
|
29
|
+
* destroy-time cleanliness check (FM-059: no exemption list, ever).
|
|
30
|
+
*
|
|
31
|
+
* Destroy refuses a dirty worktree (uncommitted changes or untracked
|
|
32
|
+
* files) unless --discard, which is reserved for the teardown scout path
|
|
33
|
+
* (PR-010). A transient git index.lock during destroy is retried; the
|
|
34
|
+
* lock file is removed only under a fail-safe staleness proof (provably
|
|
35
|
+
* no holder via lsof plus mtime age beyond a threshold; any uncertainty
|
|
36
|
+
* means leave it and fail loudly), per FM-036 and FM-051.
|
|
37
|
+
*/
|
|
38
|
+
/** Task branch created by the pool at the fetched base SHA. */
|
|
39
|
+
export declare function taskBranchName(taskId: string): string;
|
|
40
|
+
/** Task ids are single safe path segments. */
|
|
41
|
+
export declare const TASK_ID_PATTERN: RegExp;
|
|
42
|
+
export interface PoolRecord {
|
|
43
|
+
taskId: string;
|
|
44
|
+
project: string;
|
|
45
|
+
remote: string;
|
|
46
|
+
branch: string;
|
|
47
|
+
baseSha: string;
|
|
48
|
+
branchName: string;
|
|
49
|
+
offline: boolean;
|
|
50
|
+
createdAt: string;
|
|
51
|
+
}
|
|
52
|
+
export type PoolResult<T> = {
|
|
53
|
+
ok: true;
|
|
54
|
+
value: T;
|
|
55
|
+
} | {
|
|
56
|
+
ok: false;
|
|
57
|
+
reason: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* THE BOUND ON A NETWORK-REACHING GIT SUBPROCESS (M4-P19 fix round).
|
|
61
|
+
*
|
|
62
|
+
* `spawnSync` with no `timeout` waits for the child forever. For a local
|
|
63
|
+
* git command that is harmless: it either answers or fails. For one that
|
|
64
|
+
* opens a socket it is not, and the failure mode is not a slow command,
|
|
65
|
+
* it is a command that NEVER RETURNS. Measured by the clean-room
|
|
66
|
+
* reviewer against head abde402: a remote pointed at a TCP listener that
|
|
67
|
+
* accepts and never speaks made `tiphys pool list` and `tiphys doctor`
|
|
68
|
+
* run until killed (exit 124 under `timeout 25`), where the same fixture
|
|
69
|
+
* on the phase base exited 0 in about a second.
|
|
70
|
+
*
|
|
71
|
+
* This bound is applied to `ls-remote --symref <remote> HEAD` only, and
|
|
72
|
+
* the reason it is safe THERE and not elsewhere is a property of the
|
|
73
|
+
* command rather than a judgement about it: that invocation transfers a
|
|
74
|
+
* ref advertisement and nothing else, so a legitimate one is bounded by
|
|
75
|
+
* round-trip latency. `git fetch` (src/pool.ts, src/teardown.ts) and
|
|
76
|
+
* `git push` (src/teardown.ts) transfer objects, so their legitimate
|
|
77
|
+
* duration IS unbounded and a wall-clock cap on them would abort real
|
|
78
|
+
* work. They are left unbounded deliberately, and they are reached only
|
|
79
|
+
* from a command the operator invoked to do that work, never from a
|
|
80
|
+
* reporting path; keeping reporting paths off the network entirely is
|
|
81
|
+
* the other half of this fix (see `reconstructPoolRecord`).
|
|
82
|
+
*
|
|
83
|
+
* TIPHYS_GIT_NETWORK_TIMEOUT_MS is a TEST SEAM in the style of
|
|
84
|
+
* TIPHYS_WATCH_TEST_HOLD (src/watcher.ts) and TIPHYS_LOCK_TEST_HOLD
|
|
85
|
+
* (src/commands/lock.ts): a test cannot afford to wait out the shipped
|
|
86
|
+
* bound, and a shipped bound short enough for a test would abort a
|
|
87
|
+
* legitimate ls-remote over a slow link. A value that is not a positive
|
|
88
|
+
* integer is IGNORED rather than honoured, so a malformed environment
|
|
89
|
+
* cannot silently remove the bound.
|
|
90
|
+
*/
|
|
91
|
+
export declare const NETWORK_TIMEOUT_MS = 20000;
|
|
92
|
+
/**
|
|
93
|
+
* Exported as a PURE function so the validation has a witness that does
|
|
94
|
+
* not have to wait out a twenty-second bound to observe it. The
|
|
95
|
+
* end-to-end bound is witnessed separately, against a real remote that
|
|
96
|
+
* never answers; this is the arm that says a malformed environment
|
|
97
|
+
* cannot silently switch the bound off.
|
|
98
|
+
*
|
|
99
|
+
* `Number("")` is 0 and `Number("0x10")` is 16, so neither a blank value
|
|
100
|
+
* nor a hexadecimal one is passed through: the accepted set is exactly
|
|
101
|
+
* the positive integers, and everything else falls back.
|
|
102
|
+
*/
|
|
103
|
+
export declare function resolveNetworkTimeoutMs(raw: string | undefined): number;
|
|
104
|
+
/** Exported for the contention-classification test. */
|
|
105
|
+
export declare function isTransientGitLockError(stderr: string): boolean;
|
|
106
|
+
export declare function recordPath(fleet: Fleet, taskId: string): string;
|
|
107
|
+
export declare function worktreePath(fleet: Fleet, taskId: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* THE RECORD'S ENTRY TYPE IS ESTABLISHED BEFORE IT IS OPENED. A bare read
|
|
110
|
+
* here hung `tiphys pool destroy` forever with zero output against a named
|
|
111
|
+
* pipe at `worktrees/<id>.pool.json`; measured before the fix, `pool list`
|
|
112
|
+
* (which reads only the NAME) returned in the same second while
|
|
113
|
+
* `pool destroy --task t-0001` was killed at ten seconds. The two commands
|
|
114
|
+
* differ by whether this function runs, which is what makes the mechanism
|
|
115
|
+
* the open and not the command.
|
|
116
|
+
*
|
|
117
|
+
* A non-regular record is a REFUSAL rather than `undefined`: `undefined`
|
|
118
|
+
* already means "there is no record", and a caller that cannot tell that
|
|
119
|
+
* apart from "the record could not be opened" would rebuild a worktree over
|
|
120
|
+
* a record it never read.
|
|
121
|
+
*/
|
|
122
|
+
export declare function readPoolRecord(fleet: Fleet, taskId: string): PoolRecord | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* POST-RECLAIM RECONSTRUCTION (M4-D-12, kernel plan M4 section M4-P19).
|
|
125
|
+
*
|
|
126
|
+
* THE RULE, and it is the whole design: RECONSTRUCT FOR REPORTING, NEVER
|
|
127
|
+
* FOR DESTRUCTION. A reconstructed record exists in memory for the life
|
|
128
|
+
* of one command and is NEVER written to worktrees/<id>.pool.json, so a
|
|
129
|
+
* later reader can never mistake a reconstruction for an original.
|
|
130
|
+
*
|
|
131
|
+
* THE DEFECT IT CLOSES, measured rather than assumed. tasks/<id>/meta.json
|
|
132
|
+
* is TRACKED and survives a reclaim; worktrees/<id>.pool.json cannot,
|
|
133
|
+
* because it sits beside the worktree BY DESIGN so it can never dirty the
|
|
134
|
+
* destroy-time cleanliness check (see the module header above, FM-059).
|
|
135
|
+
* Teardown then refuses without a pool record and says so in terms
|
|
136
|
+
* (src/teardown.ts), so the plan's stated fallback of "recovery is manual
|
|
137
|
+
* teardown" does not work post-reclaim: the manual path is itself blocked.
|
|
138
|
+
*
|
|
139
|
+
* WHAT IS DERIVED AND WHAT IS NOT. meta.json carries six of the eight
|
|
140
|
+
* PoolRecord fields directly (taskId, project, baseSha, branchName,
|
|
141
|
+
* offline, createdAt). It carries NEITHER `remote` NOR `branch`, which are
|
|
142
|
+
* the project's configured remote and that remote's default branch. Those
|
|
143
|
+
* two are re-derived from git through the SAME two resolvers poolCreate
|
|
144
|
+
* uses, so a reconstruction is a repeat of the original derivation and
|
|
145
|
+
* never a remembered value.
|
|
146
|
+
*
|
|
147
|
+
* WHEN EITHER OF THOSE TWO CANNOT BE DERIVED THE RESULT IS INCOMPLETE AND
|
|
148
|
+
* NAMES THE FIELD. It is never filled with a plausible default. "origin"
|
|
149
|
+
* and "main" are right often enough to look harmless and wrong often
|
|
150
|
+
* enough to destroy work: a guessed default branch sends the landed-ness
|
|
151
|
+
* judgement at a ref that is not the project's default, and teardown's
|
|
152
|
+
* authorization to delete a task branch comes from exactly that judgement
|
|
153
|
+
* (V-1, the defect src/spawn.ts was rewritten to prevent). An unresolvable
|
|
154
|
+
* field is therefore a refusal, not a gap to fill.
|
|
155
|
+
*/
|
|
156
|
+
export type ReconstructResult =
|
|
157
|
+
/** Every field derived. Safe to report, and safe to pass to a GATED path. */
|
|
158
|
+
{
|
|
159
|
+
kind: "complete";
|
|
160
|
+
record: PoolRecord;
|
|
161
|
+
}
|
|
162
|
+
/** meta.json read, but git could not answer for the named fields. */
|
|
163
|
+
| {
|
|
164
|
+
kind: "incomplete";
|
|
165
|
+
unresolved: string[];
|
|
166
|
+
detail: string;
|
|
167
|
+
}
|
|
168
|
+
/** No readable task meta, so there is nothing to reconstruct from. */
|
|
169
|
+
| {
|
|
170
|
+
kind: "absent";
|
|
171
|
+
reason: string;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* What a caller of `reconstructPoolRecord` is permitted to do to answer.
|
|
175
|
+
*
|
|
176
|
+
* THE FIELD IS REQUIRED AND THE TYPE IS WHY (M4-P19 fix round). The
|
|
177
|
+
* reconstruction rebuilds `branch` through `resolveDefaultBranch`, which
|
|
178
|
+
* falls back to `git ls-remote` when `<remote>/HEAD` is unset locally,
|
|
179
|
+
* and that fallback opens a socket. `<remote>/HEAD` unset is not an
|
|
180
|
+
* exotic state: it is the NORMAL state of a clone made by `git init` +
|
|
181
|
+
* `git remote add` + `git fetch`, which is how this kernel's own tests
|
|
182
|
+
* and fixtures build one. So the fallback is reached on ordinary fleets,
|
|
183
|
+
* and a caller that must return, such as `pool list` or `doctor`, must
|
|
184
|
+
* not reach it.
|
|
185
|
+
*
|
|
186
|
+
* Measured against head abde402, where this option did not exist and
|
|
187
|
+
* every caller got the network: with the remote pointed at a TCP
|
|
188
|
+
* listener that accepts and never speaks, `tiphys pool list` and
|
|
189
|
+
* `tiphys doctor` ran until killed. Making the decision a required field
|
|
190
|
+
* rather than a defaulted one is the part of the fix that survives the
|
|
191
|
+
* next caller: adding one without choosing does not compile.
|
|
192
|
+
*/
|
|
193
|
+
export interface ReconstructOptions {
|
|
194
|
+
/**
|
|
195
|
+
* True only for a caller the operator invoked to CHANGE something and
|
|
196
|
+
* which may therefore wait on a remote. False for every reporting
|
|
197
|
+
* path, which then reports `unreconstructable (unresolved: branch)`
|
|
198
|
+
* rather than blocking.
|
|
199
|
+
*/
|
|
200
|
+
network: boolean;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Rebuild a pool record for taskId from tasks/<id>/meta.json and git.
|
|
204
|
+
* Reads only; writes nothing anywhere, ever.
|
|
205
|
+
*/
|
|
206
|
+
export declare function reconstructPoolRecord(fleet: Fleet, taskId: string, options: ReconstructOptions): ReconstructResult;
|
|
207
|
+
export interface CreateOptions {
|
|
208
|
+
taskId: string;
|
|
209
|
+
project: string;
|
|
210
|
+
offline: boolean;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* pool create (EXT-F-03 five steps; see module doc). Returns the pool
|
|
214
|
+
* record on success.
|
|
215
|
+
*
|
|
216
|
+
* On failure NOTHING IS REMOVED. The pool record, the worktree
|
|
217
|
+
* directory and the task branch may each survive, depending on how far
|
|
218
|
+
* the attempt got, and the reason line names exactly which of them did
|
|
219
|
+
* and the command that clears them. The automatic rollback this
|
|
220
|
+
* docstring used to promise was deleted deliberately: it served a
|
|
221
|
+
* concurrent-create path M1 never enters (parallelism is off until M5)
|
|
222
|
+
* and produced four consecutive rounds of defects, including deleting
|
|
223
|
+
* state it had not validated. Failing loudly and leaving state is the
|
|
224
|
+
* chosen contract, not an oversight.
|
|
225
|
+
*/
|
|
226
|
+
export declare function poolCreate(fleet: Fleet, options: CreateOptions): Promise<PoolResult<PoolRecord>>;
|
|
227
|
+
/**
|
|
228
|
+
* Where an entry's pool record came from. `record` is an original read
|
|
229
|
+
* from worktrees/<id>.pool.json; the other two exist only after a reclaim
|
|
230
|
+
* has taken worktrees/ with it, and are computed fresh on every call.
|
|
231
|
+
*/
|
|
232
|
+
export type PoolEntryOrigin = "record" | "reconstructed" | "unreconstructable";
|
|
233
|
+
export interface PoolListEntry {
|
|
234
|
+
taskId: string;
|
|
235
|
+
headSha: string;
|
|
236
|
+
origin: PoolEntryOrigin;
|
|
237
|
+
/**
|
|
238
|
+
* Set only for `unreconstructable`: what this listing could not establish.
|
|
239
|
+
* Usually the PoolRecord fields git could not answer for; `meta` means the
|
|
240
|
+
* task record itself was present and did not read, which is a different
|
|
241
|
+
* state from a task that is closed and from one that is not there.
|
|
242
|
+
*/
|
|
243
|
+
unresolved?: string[];
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* One entry per pool record, with the worktree's current HEAD SHA, PLUS
|
|
247
|
+
* one per OPEN task that has no pool record beside it (M4-P19).
|
|
248
|
+
*
|
|
249
|
+
* The second group is what a reclaim leaves behind: tasks/ is tracked and
|
|
250
|
+
* survives, worktrees/ is gitignored and does not, so a task can be open
|
|
251
|
+
* with its record gone. Reporting only the first group makes those tasks
|
|
252
|
+
* invisible to `pool list` and to doctor, which is the state the plan
|
|
253
|
+
* calls a defect. Every such entry is marked, never silently blended in
|
|
254
|
+
* with the originals, and NOTHING here is written to disk.
|
|
255
|
+
*
|
|
256
|
+
* Closed tasks are excluded: a closed task is not in the pool, and
|
|
257
|
+
* listing every task this fleet ever finished as a missing worktree would
|
|
258
|
+
* make the report useless within a week.
|
|
259
|
+
*
|
|
260
|
+
* THIS FUNCTION OPENS NO SOCKET (M4-P19 fix round). It reads the
|
|
261
|
+
* filesystem and runs local git commands, and its reconstruction is
|
|
262
|
+
* asked for with `{ network: false }`. An entry whose default branch
|
|
263
|
+
* cannot be established from the clone alone is reported
|
|
264
|
+
* `unreconstructable (unresolved: branch)` rather than waited on. See
|
|
265
|
+
* `ReconstructOptions` for the measured hang that this closes.
|
|
266
|
+
*/
|
|
267
|
+
export declare function poolList(fleet: Fleet): PoolListEntry[];
|
|
268
|
+
export interface LsofProbe {
|
|
269
|
+
available: boolean;
|
|
270
|
+
exitCode: number | null;
|
|
271
|
+
stdout: string;
|
|
272
|
+
}
|
|
273
|
+
/** Age a lock file must reach before a staleness proof is even considered. */
|
|
274
|
+
export declare const STALE_LOCK_AGE_MS = 300000;
|
|
275
|
+
/**
|
|
276
|
+
* Fail-safe staleness proof for a git lock file (FM-036, FM-051): true
|
|
277
|
+
* only when the lock exists, its mtime age exceeds the threshold, and
|
|
278
|
+
* lsof is available and shows provably no holder (exit 1, empty stdout).
|
|
279
|
+
* Any uncertainty (lsof missing, erroring, or listing holders) is false:
|
|
280
|
+
* the lock is left in place and the operation fails loudly.
|
|
281
|
+
*/
|
|
282
|
+
export declare function provablyStaleLock(lockFile: string, opts?: {
|
|
283
|
+
nowMs?: number;
|
|
284
|
+
ageThresholdMs?: number;
|
|
285
|
+
runLsof?: (path: string) => LsofProbe;
|
|
286
|
+
}): boolean;
|
|
287
|
+
export interface DestroyOptions {
|
|
288
|
+
taskId: string;
|
|
289
|
+
/** Override the dirty-worktree refusal (plan step 3, PR-010). */
|
|
290
|
+
discard: boolean;
|
|
291
|
+
/**
|
|
292
|
+
* Authorize deleting a task branch that carries commits beyond its
|
|
293
|
+
* recorded base (V-1). Deliberately distinct from discard, whose
|
|
294
|
+
* plan-defined meaning is the dirty-tree override only: conflating
|
|
295
|
+
* them would make the scout path silently destroy committed work.
|
|
296
|
+
* M1-P4 teardown passes this from its ship path after its landedness
|
|
297
|
+
* judgement, which makes the dependency on teardown explicit rather
|
|
298
|
+
* than assumed.
|
|
299
|
+
*/
|
|
300
|
+
deleteBranchForce: boolean;
|
|
301
|
+
/**
|
|
302
|
+
* An IN-MEMORY reconstructed record (M4-P19), used ONLY when no record
|
|
303
|
+
* exists on disk. It is never written: `haveRecord` still comes from
|
|
304
|
+
* the file, so nothing here creates worktrees/<id>.pool.json and
|
|
305
|
+
* nothing unlinks a file that is not there.
|
|
306
|
+
*
|
|
307
|
+
* WHY THIS EXISTS AT ALL, since the whole design is "never for
|
|
308
|
+
* destruction". Without it, stage 2's base-sha gate has no base to
|
|
309
|
+
* compare against and returns its "pool record missing or unreadable"
|
|
310
|
+
* refusal, so the post-reclaim path would be blocked at the one gate
|
|
311
|
+
* that was ALREADY going to do the right thing. Passing the
|
|
312
|
+
* reconstruction in makes that gate WORK rather than abstain, which is
|
|
313
|
+
* strictly safer than the alternative of relaxing it. The caller is
|
|
314
|
+
* responsible for having derived it (src/teardown.ts's
|
|
315
|
+
* --from-reconstructed path is the only one), and `pool destroy` on
|
|
316
|
+
* the command line never sets it.
|
|
317
|
+
*/
|
|
318
|
+
reconstructed?: PoolRecord;
|
|
319
|
+
}
|
|
320
|
+
/** What a completed destroy removed, for the operator's record. */
|
|
321
|
+
export interface DestroyOutcome {
|
|
322
|
+
deletedBranch?: string;
|
|
323
|
+
/** The branch tip at deletion time: the recovery handle (V-1). */
|
|
324
|
+
deletedSha?: string;
|
|
325
|
+
}
|
|
326
|
+
export declare function poolDestroy(fleet: Fleet, options: DestroyOptions): Promise<PoolResult<DestroyOutcome>>;
|