aimship 0.0.0-stage → 0.1.0-preview.4
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/CONTRIBUTING.md +11 -0
- package/LICENSE +21 -0
- package/README.md +44 -2
- package/README.zh-CN.md +45 -0
- package/bin/aimship.mjs +17 -0
- package/docs/cli.md +62 -0
- package/docs/guide.md +59 -0
- package/docs/installation.md +117 -0
- package/lib/cli.mjs +159 -0
- package/lib/install.mjs +363 -0
- package/lib/io.mjs +55 -0
- package/lib/state.mjs +210 -0
- package/package.json +42 -4
- package/skills/aimship/SKILL.md +19 -0
- package/skills/aimship/agents/openai.yaml +6 -0
- package/skills/aimship/references/core.md +84 -0
- package/skills/aimship/references/document-patterns.md +19 -0
- package/skills/aimship/references/hosts.md +15 -0
- package/skills/aimship/references/recovery.md +13 -0
- package/skills/aimship/references/sources-and-changes.md +28 -0
- package/skills/aimship/references/stages/contract.md +19 -0
- package/skills/aimship/references/stages/diagnose.md +19 -0
- package/skills/aimship/references/stages/frame.md +19 -0
- package/skills/aimship/references/stages/handoff.md +19 -0
- package/skills/aimship/references/stages/implement.md +19 -0
- package/skills/aimship/references/stages/plan.md +19 -0
- package/skills/aimship/references/stages/prototype.md +19 -0
- package/skills/aimship/references/stages/requirements.md +19 -0
- package/skills/aimship/references/stages/review.md +19 -0
- package/skills/aimship/references/stages/scope.md +19 -0
- package/skills/aimship/references/stages/tech-design.md +19 -0
- package/skills/aimship/references/stages/test-design.md +19 -0
- package/skills/aimship/references/stages/verify.md +19 -0
package/lib/state.mjs
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { atomicWrite, exists, fail, inside, json, noSymlinks, readJSON, withLock } from './io.mjs';
|
|
5
|
+
|
|
6
|
+
export const SCHEMA_VERSION = 1;
|
|
7
|
+
export const STAGES = ['frame', 'requirements', 'prototype', 'scope', 'diagnose', 'tech-design', 'contract', 'plan', 'test-design', 'implement', 'review', 'verify', 'handoff'];
|
|
8
|
+
const PROGRESS = ['planned', 'active', 'blocked', 'done'];
|
|
9
|
+
const RESULTS = ['passed', 'failed', 'not-run', 'unknown', 'mixed'];
|
|
10
|
+
const OUTCOME_REFS = ['goalConclusionRef', 'acceptanceRef', 'mergeRef', 'deploymentRef', 'handoffRef'];
|
|
11
|
+
const object = x => x !== null && typeof x === 'object' && !Array.isArray(x);
|
|
12
|
+
const string = x => typeof x === 'string' && x.trim().length > 0;
|
|
13
|
+
function requireThat(condition, message) { if (!condition) fail('INVALID_STATE', message, 'Correct the input without overwriting the current state; read help for the state protocol.'); }
|
|
14
|
+
function ref(value, field) {
|
|
15
|
+
requireThat(string(value), `${field} must be a nonempty reference string.`);
|
|
16
|
+
requireThat(!value.includes('\0'), `${field} contains a null byte.`);
|
|
17
|
+
if (/^https?:\/\//.test(value)) { try { new URL(value); } catch { requireThat(false, `${field} is not a URL.`); } return; }
|
|
18
|
+
requireThat(!value.includes('\\') && (!value.startsWith('repo:') || /^repo:[^/#]+\/.+/.test(value)), `${field} must use slash-separated relative paths and a valid repository ID.`);
|
|
19
|
+
const local = value.replace(/^repo:[^/]+\//, '').split('#')[0];
|
|
20
|
+
requireThat(string(local) && !path.isAbsolute(local) && !/^[a-zA-Z]:/.test(local) && !local.split(/[\\/]/).includes('..'), `${field} must be delivery-relative, repo:<id>/<path>, or an HTTP(S) URL.`);
|
|
21
|
+
}
|
|
22
|
+
function refs(value, field) { requireThat(Array.isArray(value), `${field} must be an array.`); value.forEach(x => ref(x, field)); }
|
|
23
|
+
function unique(items, label) { requireThat(items.every(object), `${label} entries must be objects.`); const ids = items.map(x => x.id); requireThat(ids.every(string) && new Set(ids).size === ids.length, `${label} IDs must be nonempty and unique.`); }
|
|
24
|
+
|
|
25
|
+
export function validateState(state) {
|
|
26
|
+
requireThat(object(state), 'State must be an object.');
|
|
27
|
+
if (state.schemaVersion !== SCHEMA_VERSION) fail('UNKNOWN_SCHEMA', `Schema ${state.schemaVersion} is read-only for this tool.`, 'Preserve the file and use a compatible tool or an explicit, reviewed migration.');
|
|
28
|
+
requireThat(Number.isSafeInteger(state.revision) && state.revision >= 0, 'revision must be a nonnegative integer.');
|
|
29
|
+
requireThat(string(state.deliveryId) && string(state.rulesVersion), 'deliveryId and rulesVersion are required.');
|
|
30
|
+
requireThat(object(state.goal) && string(state.goal.summary) && string(state.goal.endpoint), 'goal.summary and goal.endpoint are required.');
|
|
31
|
+
ref(state.goalRef, 'goalRef');
|
|
32
|
+
if (state.goal.decisionRef !== undefined) ref(state.goal.decisionRef, 'goal.decisionRef');
|
|
33
|
+
requireThat(Number.isSafeInteger(state.cycle) && state.cycle >= 1, 'cycle must be a positive integer.');
|
|
34
|
+
refs(state.closureRefs, 'closureRefs');
|
|
35
|
+
requireThat(Array.isArray(state.stageRuns), 'stageRuns must be an array.'); unique(state.stageRuns, 'Stage instance');
|
|
36
|
+
for (const run of state.stageRuns) {
|
|
37
|
+
requireThat(STAGES.includes(run.stage), `Unknown stage: ${run.stage}`);
|
|
38
|
+
requireThat(string(run.scope) && PROGRESS.includes(run.progress), `Invalid scope or progress in ${run.id}.`);
|
|
39
|
+
refs(run.inputRefs, `${run.id}.inputRefs`); refs(run.outputRefs, `${run.id}.outputRefs`);
|
|
40
|
+
for (const key of ['resultRef', 'priorResultRef']) if (run[key] !== undefined) ref(run[key], `${run.id}.${key}`);
|
|
41
|
+
if (run.historyResultRefs !== undefined) refs(run.historyResultRefs, `${run.id}.historyResultRefs`);
|
|
42
|
+
if (run.result !== undefined) requireThat(RESULTS.includes(run.result), `Invalid result in ${run.id}.`);
|
|
43
|
+
if (run.applicability !== undefined) requireThat(['current', 'needs-review', 'unknown'].includes(run.applicability), `Invalid applicability in ${run.id}.`);
|
|
44
|
+
if (run.progress === 'done') requireThat(string(run.resultRef), `Completed instance ${run.id} requires resultRef; file existence does not establish semantic completion.`);
|
|
45
|
+
}
|
|
46
|
+
requireThat(state.currentRun === null || state.stageRuns.some(x => x.id === state.currentRun), 'currentRun must refer to a stage instance or be null.');
|
|
47
|
+
requireThat(Array.isArray(state.openChanges), 'openChanges must be an array.'); unique(state.openChanges, 'Change');
|
|
48
|
+
for (const change of state.openChanges) { ref(change.ref, 'change.ref'); requireThat(['open', 'closed'].includes(change.status), 'Invalid change status.'); }
|
|
49
|
+
requireThat(Array.isArray(state.repositories), 'repositories must be an array.'); unique(state.repositories, 'Repository');
|
|
50
|
+
for (const repo of state.repositories) requireThat(path.isAbsolute(repo.path ?? '') && string(repo.role), 'Repository path must be absolute and role nonempty.');
|
|
51
|
+
requireThat(object(state.outcome) && ['in-progress', 'met', 'not-met', 'unknown'].includes(state.outcome.goal), 'Invalid outcome.goal.');
|
|
52
|
+
requireThat(['not-recorded', 'accepted', 'declined', 'unknown'].includes(state.outcome.acceptance), 'Invalid outcome.acceptance.');
|
|
53
|
+
for (const key of OUTCOME_REFS) if (state.outcome[key] !== undefined) ref(state.outcome[key], `outcome.${key}`);
|
|
54
|
+
if (state.outcome.goal === 'met') requireThat(string(state.outcome.goalConclusionRef), 'A met goal requires an explicit goalConclusionRef.');
|
|
55
|
+
if (['accepted', 'declined'].includes(state.outcome.acceptance)) requireThat(string(state.outcome.acceptanceRef), 'Acceptance requires a separate decision reference.');
|
|
56
|
+
requireThat(object(state.next) && string(state.next.action), 'next.action is required.');
|
|
57
|
+
if (state.next.inputRefs !== undefined) refs(state.next.inputRefs, 'next.inputRefs');
|
|
58
|
+
if (state.goalHistory !== undefined) requireThat(Array.isArray(state.goalHistory), 'goalHistory must be an array.');
|
|
59
|
+
if (state.rulesHistory !== undefined) requireThat(Array.isArray(state.rulesHistory), 'rulesHistory must be an array.');
|
|
60
|
+
return state;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function statePaths(directory) {
|
|
64
|
+
const dir = path.resolve(directory);
|
|
65
|
+
return { dir, statePath: path.join(dir, 'state.json'), backup: path.join(dir, 'state.previous.json'), lock: path.join(dir, '.state.lock') };
|
|
66
|
+
}
|
|
67
|
+
export async function readState(directory) {
|
|
68
|
+
const paths = statePaths(directory); const state = await readJSON(paths.statePath);
|
|
69
|
+
requireThat(object(state), 'State must be an object.');
|
|
70
|
+
const readOnly = state.schemaVersion !== SCHEMA_VERSION;
|
|
71
|
+
if (!readOnly) validateState(state);
|
|
72
|
+
return { ...paths, state, readOnly };
|
|
73
|
+
}
|
|
74
|
+
function checkRevision(state, revision) {
|
|
75
|
+
if (!Number.isSafeInteger(revision) || revision !== state.revision) fail('REVISION_CONFLICT', `Expected revision ${revision}; current revision is ${state.revision}.`, 'Read state again and merge your intended changes; never retry with a guessed revision.', { expected: revision, actual: state.revision });
|
|
76
|
+
}
|
|
77
|
+
export function assertRules(state, rulesVersion, runtime) {
|
|
78
|
+
assertInstallationComplete(runtime);
|
|
79
|
+
if (!rulesVersion || rulesVersion !== state.rulesVersion || rulesVersion !== runtime.version || runtime.activeVersion !== runtime.version) fail('VERSION_MISMATCH', 'The session, state, tool, and active installation must use the same rules version.', 'Save only unfinished facts with checkpoint if available; bind the active version, reload its core and current stage, then adopt at a stable point.', { session: rulesVersion, state: state.rulesVersion, tool: runtime.version, active: runtime.activeVersion, launcher: runtime.launcher });
|
|
80
|
+
}
|
|
81
|
+
export function assertInstallationComplete(runtime) {
|
|
82
|
+
if (runtime.installPending) fail('INSTALL_PENDING', 'The installation is incomplete; new workflow writes and bindings are suspended.', 'Read state without progressing, then rerun install from the same exact pending package. After recovery, bind and reload its fixed core before continuing.', { pendingVersion: runtime.installPending.version, activeVersion: runtime.activeVersion, launcher: runtime.launcher });
|
|
83
|
+
}
|
|
84
|
+
export async function initState(directory, input, rulesVersion, runtime) {
|
|
85
|
+
assertInstallationComplete(runtime);
|
|
86
|
+
if (rulesVersion !== runtime.version || runtime.activeVersion !== runtime.version) fail('VERSION_MISMATCH', 'New delivery requires the active tool and rules version.', 'Bind the current installation and use its returned version.');
|
|
87
|
+
const p = statePaths(directory); await noSymlinks(p.dir); await fs.mkdir(p.dir, { recursive: true });
|
|
88
|
+
return withLock(p.lock, async () => {
|
|
89
|
+
if (await exists(p.statePath)) fail('ALREADY_EXISTS', 'A delivery already exists here.', 'Read/resume this delivery or choose a different folder.');
|
|
90
|
+
const forbidden = ['schemaVersion', 'revision', 'deliveryId', 'rulesVersion', 'createdAt', 'updatedAt', 'goalHistory', 'rulesHistory'];
|
|
91
|
+
requireThat(object(input) && !forbidden.some(x => Object.hasOwn(input, x)), 'init input must not set tool-managed identity/version fields.');
|
|
92
|
+
const now = new Date().toISOString();
|
|
93
|
+
const state = { cycle: 1, closureRefs: [], stageRuns: [], currentRun: null, openChanges: [], repositories: [], outcome: { goal: 'in-progress', acceptance: 'not-recorded' }, next: { action: 'Continue the confirmed arrangement.' }, ...input, schemaVersion: SCHEMA_VERSION, revision: 0, deliveryId: randomUUID(), rulesVersion, createdAt: now, updatedAt: now };
|
|
94
|
+
validateState(state); await atomicWrite(p.statePath, json(state)); return state;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function merge(base, patch) {
|
|
98
|
+
const result = structuredClone(base);
|
|
99
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
100
|
+
requireThat(!['__proto__', 'constructor', 'prototype'].includes(key), `Unsafe property: ${key}`);
|
|
101
|
+
result[key] = object(value) && object(result[key]) ? merge(result[key], value) : structuredClone(value);
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
function retainHistory(previous, next) {
|
|
106
|
+
for (const old of previous.stageRuns) {
|
|
107
|
+
const current = next.stageRuns.find(x => x.id === old.id);
|
|
108
|
+
if (!current) requireThat(old.progress === 'planned' && !old.resultRef, `Cannot remove started instance ${old.id}; preserve historical execution.`);
|
|
109
|
+
else {
|
|
110
|
+
requireThat(current.stage === old.stage, `Cannot change stage type for ${old.id}.`);
|
|
111
|
+
const oldRefs = [old.resultRef, old.priorResultRef, ...(old.historyResultRefs ?? [])].filter(Boolean);
|
|
112
|
+
const currentRefs = [current.resultRef, current.priorResultRef, ...(current.historyResultRefs ?? [])];
|
|
113
|
+
requireThat(oldRefs.every(x => currentRefs.includes(x)), `Preserve historical result references for ${old.id}.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
requireThat(previous.closureRefs.every(x => next.closureRefs.includes(x)), 'Preserve historical closure references.');
|
|
117
|
+
requireThat(previous.openChanges.every(old => next.openChanges.some(x => x.id === old.id && x.ref === old.ref)), 'Preserve change records, using closed status when resolved.');
|
|
118
|
+
requireThat(next.cycle >= previous.cycle && next.cycle <= previous.cycle + 1, 'cycle may stay unchanged or increase by one.');
|
|
119
|
+
if (next.cycle > previous.cycle) requireThat(next.closureRefs.length > previous.closureRefs.length && next.outcome.acceptance === 'not-recorded', 'Reopening requires a previous closure reference and reset current acceptance.');
|
|
120
|
+
}
|
|
121
|
+
export async function updateState(directory, patch, revision, rulesVersion, runtime, mode = 'update') {
|
|
122
|
+
assertInstallationComplete(runtime);
|
|
123
|
+
const p = statePaths(directory);
|
|
124
|
+
return withLock(p.lock, async () => {
|
|
125
|
+
const { state: previous } = await readState(directory); validateState(previous); checkRevision(previous, revision);
|
|
126
|
+
requireThat(object(patch), 'Update input must be an object.');
|
|
127
|
+
if (mode === 'checkpoint') {
|
|
128
|
+
if (rulesVersion !== previous.rulesVersion || runtime.version !== previous.rulesVersion) fail('VERSION_MISMATCH', 'Checkpoint must use the rules already bound to this state.', 'Use the compatible old tool or preserve facts outside state and resume with the active tool.');
|
|
129
|
+
requireThat(Object.keys(patch).every(x => ['next', 'checkpoint'].includes(x)) && object(patch.checkpoint) && string(patch.checkpoint.summary), 'Checkpoint may save only next and checkpoint.summary/ref facts; it cannot complete stages or outcomes.');
|
|
130
|
+
if (runtime.activeVersion === runtime.version) fail('CHECKPOINT_NOT_NEEDED', 'Rules match; use a normal update for unfinished facts.', 'Save current work with update.');
|
|
131
|
+
if (previous.checkpoint?.activeVersion === runtime.activeVersion) fail('CHECKPOINT_ALREADY_SAVED', 'A checkpoint for this active version already exists.', 'Reload active rules and adopt at the recorded stable point.');
|
|
132
|
+
if (patch.checkpoint.ref !== undefined) ref(patch.checkpoint.ref, 'checkpoint.ref');
|
|
133
|
+
} else if (mode === 'adopt') {
|
|
134
|
+
requireThat(runtime.version === runtime.activeVersion && rulesVersion === runtime.version, 'Adoption requires the active rules and tool.');
|
|
135
|
+
requireThat(previous.rulesVersion !== rulesVersion, 'Rules are already adopted; no version change is needed.');
|
|
136
|
+
requireThat(Object.keys(patch).length === 1 && string(patch.compatibilityRef), 'Adoption input must contain only compatibilityRef documenting the stable point and compatibility assessment.');
|
|
137
|
+
ref(patch.compatibilityRef, 'compatibilityRef');
|
|
138
|
+
} else {
|
|
139
|
+
assertRules(previous, rulesVersion, runtime);
|
|
140
|
+
}
|
|
141
|
+
const immutable = ['schemaVersion', 'revision', 'deliveryId', 'rulesVersion', 'createdAt', 'updatedAt', 'goalHistory', 'rulesHistory'];
|
|
142
|
+
requireThat(!immutable.some(x => Object.hasOwn(patch, x)), 'Identity, revision, and historical metadata are tool-managed.');
|
|
143
|
+
let next;
|
|
144
|
+
if (mode === 'adopt') {
|
|
145
|
+
next = { ...previous, rulesVersion, rulesHistory: [...(previous.rulesHistory ?? []), { from: previous.rulesVersion, to: rulesVersion, ref: patch.compatibilityRef, at: new Date().toISOString() }] };
|
|
146
|
+
} else next = merge(previous, patch);
|
|
147
|
+
if (mode === 'checkpoint') next.checkpoint.activeVersion = runtime.activeVersion;
|
|
148
|
+
validateState(next);
|
|
149
|
+
if (JSON.stringify(previous.goal) !== JSON.stringify(next.goal) || previous.goalRef !== next.goalRef) {
|
|
150
|
+
requireThat(string(next.goal.decisionRef) && next.goal.decisionRef !== previous.goal.decisionRef, 'Goal revision requires a new explicit decisionRef; viewing results does not revise a goal.');
|
|
151
|
+
next.goalHistory = [...(previous.goalHistory ?? []), { goal: previous.goal, goalRef: previous.goalRef, outcome: previous.outcome, revision: previous.revision }];
|
|
152
|
+
}
|
|
153
|
+
retainHistory(previous, next); next.revision = previous.revision + 1; next.updatedAt = new Date().toISOString();
|
|
154
|
+
validateState(next); await atomicWrite(p.backup, json(previous)); await atomicWrite(p.statePath, json(next)); return next;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
export async function recoverState(directory, revision, rulesVersion, runtime) {
|
|
158
|
+
const p = statePaths(directory);
|
|
159
|
+
return withLock(p.lock, async () => {
|
|
160
|
+
const backup = await readJSON(p.backup); validateState(backup); checkRevision(backup, revision); assertRules(backup, rulesVersion, runtime);
|
|
161
|
+
let corruptRevision = backup.revision + 1;
|
|
162
|
+
if (await exists(p.statePath)) {
|
|
163
|
+
const raw = await fs.readFile(p.statePath, 'utf8');
|
|
164
|
+
let parsed; try { parsed = JSON.parse(raw); } catch { /* Corruption is preserved below. */ }
|
|
165
|
+
if (parsed) {
|
|
166
|
+
if (parsed.schemaVersion !== SCHEMA_VERSION) fail('UNKNOWN_SCHEMA', 'Cannot recover over an unknown schema.', 'Use a compatible tool; preserve the newer state.');
|
|
167
|
+
try { validateState(parsed); fail('STATE_VALID', 'Current state is valid; refusing rollback.', 'Use a normal revision-checked update to reconcile facts.'); }
|
|
168
|
+
catch (e) { if (e.code !== 'INVALID_STATE') throw e; }
|
|
169
|
+
if (Number.isSafeInteger(parsed.revision)) corruptRevision = Math.max(corruptRevision, parsed.revision);
|
|
170
|
+
}
|
|
171
|
+
await atomicWrite(path.join(p.dir, `state.corrupt.${randomUUID()}.json`), raw);
|
|
172
|
+
}
|
|
173
|
+
const next = { ...backup, revision: corruptRevision + 1, updatedAt: new Date().toISOString(), recovery: { fromRevision: backup.revision, action: 'Inspect actual artifacts and unfinished effects before proceeding; nothing has been re-executed.' } };
|
|
174
|
+
await atomicWrite(p.statePath, json(next)); return next;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
export async function checkReferences(directory, state, all = false) {
|
|
178
|
+
const current = state.stageRuns.find(x => x.id === state.currentRun);
|
|
179
|
+
const values = new Set([state.goalRef, ...(state.next.inputRefs ?? []), ...(current?.inputRefs ?? [])]);
|
|
180
|
+
if (all) {
|
|
181
|
+
for (const run of state.stageRuns) { for (const value of [...run.inputRefs, ...run.outputRefs, run.resultRef, run.priorResultRef, ...(run.historyResultRefs ?? [])].filter(Boolean)) values.add(value); }
|
|
182
|
+
state.openChanges.forEach(x => values.add(x.ref)); state.closureRefs.forEach(x => values.add(x));
|
|
183
|
+
const add = value => { if (value !== undefined) { ref(value, 'registered reference'); values.add(value); } };
|
|
184
|
+
const addOutcome = outcome => { for (const key of OUTCOME_REFS) add(outcome?.[key]); };
|
|
185
|
+
add(state.goal.decisionRef); addOutcome(state.outcome);
|
|
186
|
+
for (const history of state.goalHistory ?? []) {
|
|
187
|
+
add(history?.goalRef); add(history?.goal?.decisionRef); addOutcome(history?.outcome);
|
|
188
|
+
}
|
|
189
|
+
for (const history of state.rulesHistory ?? []) add(history?.ref);
|
|
190
|
+
add(state.checkpoint?.ref);
|
|
191
|
+
}
|
|
192
|
+
const results = [];
|
|
193
|
+
for (const value of values) {
|
|
194
|
+
if (/^https?:\/\//.test(value)) { results.push({ ref: value, status: 'not-checked', reason: 'Remote access and adopted version require the host.' }); continue; }
|
|
195
|
+
let base = path.resolve(directory); let relative = value.split('#')[0];
|
|
196
|
+
if (value.startsWith('repo:')) {
|
|
197
|
+
const match = /^repo:([^/]+)\/(.*)$/.exec(relative); const repo = state.repositories.find(x => x.id === match?.[1]);
|
|
198
|
+
if (!repo) { results.push({ ref: value, status: 'missing', reason: 'Repository ID is not registered.' }); continue; }
|
|
199
|
+
base = repo.path; relative = match[2];
|
|
200
|
+
}
|
|
201
|
+
const target = path.resolve(base, relative);
|
|
202
|
+
if (!inside(base, target)) fail('INVALID_REFERENCE', `Reference escapes its root: ${value}`, 'Use a path within its registered root.');
|
|
203
|
+
try {
|
|
204
|
+
const real = await fs.realpath(target); const realBase = await fs.realpath(base);
|
|
205
|
+
if (!inside(realBase, real)) results.push({ ref: value, status: 'outside-root', path: target });
|
|
206
|
+
else { await fs.access(real, fs.constants.R_OK); results.push({ ref: value, status: 'exists', path: target, fragmentChecked: false }); }
|
|
207
|
+
} catch (e) { results.push({ ref: value, status: e.code === 'ENOENT' ? 'missing' : 'inaccessible', path: target, reason: e.code }); }
|
|
208
|
+
}
|
|
209
|
+
return results;
|
|
210
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aimship",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0-preview.4",
|
|
4
|
+
"description": "Explicit, goal-driven delivery workflow for coding agents",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.0.0"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"aimship": "bin/aimship.mjs"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin/",
|
|
15
|
+
"lib/",
|
|
16
|
+
"skills/",
|
|
17
|
+
"docs/",
|
|
18
|
+
"README.md",
|
|
19
|
+
"README.zh-CN.md",
|
|
20
|
+
"CONTRIBUTING.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "node --test --test-concurrency=1",
|
|
25
|
+
"check:package": "node scripts/check-package.mjs",
|
|
26
|
+
"prepack": "node scripts/check-package.mjs"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"registry": "https://registry.npmjs.org",
|
|
30
|
+
"tag": "preview",
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"author": {
|
|
34
|
+
"name": "clsx"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/clsx/aimship.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/clsx/aimship/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/clsx/aimship#readme"
|
|
44
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aimship
|
|
3
|
+
description: Guide an explicitly requested Aimship software delivery, or resume an existing Aimship delivery, from its recorded goal through the agreed stages and handoff.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Aimship
|
|
8
|
+
|
|
9
|
+
Activate only when the user explicitly asks to start or resume Aimship. Ordinary conversation does not create a delivery. Once activated, continue the same delivery across turns without asking the user to invoke every stage.
|
|
10
|
+
|
|
11
|
+
1. Run `"{{AIMSHIP_NODE}}" "{{AIMSHIP_LAUNCHER}}" bind` to resolve the installed version. Read the returned fixed-version core and CLI help. Use that fixed version's tools, carrying its rules version and the current state revision. If this is a source checkout rather than an installed entry, use `node bin/aimship.mjs bind` from the package root.
|
|
12
|
+
2. Read the core at the path returned by `bind`. Resolve all supporting links below against that same fixed release, even if a cached entry mentions an older path. [The shared core](references/core.md) is the source-checkout reference. For an existing delivery, read its state and the current goal/Scope plus only the next step's required references. Do not create a replacement delivery, reset its plan, or infer a new goal from “continue”.
|
|
13
|
+
3. For new work, use the binding’s configured `dataRoot` unless the user supplied a delivery location; do not infer it from the code root. Preserve the original request, identify the authorized endpoint and code locations, and propose the necessary ordered stages. After associating code scope, follow the core’s recorded-overlap check for independent deliveries. Existing explicit authorization and agreed arrangements remain valid. No answer is not acceptance. Create records only for an actual request.
|
|
14
|
+
4. Read the selected [stage reference](references/core.md#stage-references) when reaching it. Explain design choices and unresolved decisions, then continue authorized work. Only material missing facts or choices block their dependent work.
|
|
15
|
+
5. At stable results and before a manual session switch, save the state and give a short continuation prompt. Keep a compact binding: delivery ID, absolute delivery directory, state path, current run, rules version, and fixed core/tool paths. After compaction, reload these references if absent; do not assume the full skill survived.
|
|
16
|
+
|
|
17
|
+
Read [recovery and updates](references/recovery.md) on interruption, version mismatch or missing references; [sources and change flow](references/sources-and-changes.md) when adopting external material or revising reviewed work; [host access](references/hosts.md) only when access or host setup needs attention. Read [document patterns](references/document-patterns.md) only for an artifact being produced.
|
|
18
|
+
|
|
19
|
+
The agent handles meaning, engineering and evidence. The local tools protect structure and writes; a successful command or a file's existence cannot establish goal completion. This skill does not schedule agents, open conversations, merge, deploy, or execute database changes by default.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Shared delivery core
|
|
2
|
+
|
|
3
|
+
## Start from the commission
|
|
4
|
+
|
|
5
|
+
A delivery has one centralized material directory, a preserved original request, current requirements or adopted sources plus Scope, an endpoint, and a state record. Code stays in its existing locations. A single repository and several repositories use the same model; there is no project registration step, repository count limit, or route classification.
|
|
6
|
+
|
|
7
|
+
Understand the intended result, supplied evidence, authorized changes and endpoint. Record known answers instead of asking again. Clarify only gaps that affect this work, with a recommendation and its consequence. Do not promote assumptions into user decisions. A design-only commission may have no repository. A short bug fix still needs its original report, context, expected behavior, scope and acceptance criteria, but not a full PRD.
|
|
8
|
+
|
|
9
|
+
Use the configured material root (default `~/Aimship`), with one identifiable directory per delivery. Do not create it during installation. Before creating a new directory, use the user's explicit target or check a possible existing match; ambiguous candidates need selection, not a global “latest” pointer. If access fails, retain the request and intended location in the conversation and say what has not been saved. Continue the same delivery after access is restored.
|
|
10
|
+
|
|
11
|
+
Read repository instructions and existing tools for the relevant work. Record relevant pre-existing modifications and distinguish them from the delivery's changes. Do not clean a working tree, initialize Git, modify an unrelated repository, or expand write access merely to simplify the workflow.
|
|
12
|
+
|
|
13
|
+
## Independent deliveries and recorded overlap
|
|
14
|
+
|
|
15
|
+
Several independent deliveries may progress at the same time, each with its own material directory, goal, stages and state. One writing session **per delivery** is not a product-wide single-task limit. This check is workspace preparation based on records, not a cross-session lock or scheduler.
|
|
16
|
+
|
|
17
|
+
Check when code scope is associated or changed, before entering implementation, or when an actual code working directory changes. Do not repeat it every turn or stage. Once the code scope is known:
|
|
18
|
+
|
|
19
|
+
1. Enumerate all delivery directories in the accessible configured material root and any other explicitly known/authorized material roots or delivery locations. Read their `state.json` summaries; do not limit the search to recent folders. Do not scan the whole disk, code trees, processes, PRDs or full histories. Do not discover unknown custom roots by searching the home directory. Report roots checked and inaccessible, invalid or unknown-format records; unseen custom roots and non-Aimship work remain outside the check.
|
|
20
|
+
2. Exclude this delivery by `deliveryId`. Compare `repositories[].path` (the actual checkout/worktree root), role, `currentRun`, relevant `stageRuns` scope/progress, `outcome`, `next` and recorded update time. Repository IDs are local to each delivery and are not global repository identity. Use already recorded repository identity; when needed and accessible, read only local Git root/common-directory metadata for the associated paths to distinguish linked worktrees. Normalize existing paths to their actual location; nested paths in one checkout are not independent isolation. Distinct independent checkouts may share a recorded repository identity even with different Git directories. If identity/location cannot be established, report it as unknown rather than assuming separation.
|
|
21
|
+
3. Include older active, blocked or uncertain deliveries. A `done` stage, completed handoff, old timestamp or declined acceptance alone does not close a delivery. A recorded met goal with no recorded remaining code work is ended; otherwise use the existing explicit closing conclusion if needed. `not-met` or `unknown` is not automatically ended. Read only the relevant Scope/plan/conclusion section when state summaries cannot establish writing intent or closure. Do not rewrite another delivery's state. Ended deliveries are not active writers, although their unmerged results or known dependencies can still matter.
|
|
22
|
+
4. Compare actual writing intent and locations using the table below. A stage label alone is not permission to write code. Keep one brief result in the existing Scope/plan or results section, linked from the current delivery's existing references when needed: check occasion, roots/limits, relevant delivery IDs and recorded stages, actual directories, known dependencies and chosen arrangement. State stays authoritative; do not add a registry, index, second progress ledger or service.
|
|
23
|
+
|
|
24
|
+
| Recorded situation | Action |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| No known overlap | Continue without a new confirmation. Say “no overlap found among the recorded deliveries checked,” never guarantee there is no conflict. |
|
|
27
|
+
| Same repository, current work is requirements/design or explicitly read-only | Briefly identify related delivery and scope; continue that non-writing work and record any known business/interface dependency. Recheck before implementation. |
|
|
28
|
+
| Multiple deliveries preparing to modify the same actual checkout | Do not silently write concurrently. Identify the deliveries and recorded stages; use the user's existing choice of sequential implementation or a separate worktree/checkout. If unresolved, propose those choices and hold only the affected code writes. A recorded blocked writer does not prove its workspace has been released. |
|
|
29
|
+
| Same repository, distinct existing worktrees/checkouts | Reuse the existing isolation, do not create it again. File isolation does not guarantee conflict-free merging or compatible business changes. Record integration dependencies where known. |
|
|
30
|
+
| Different repositories with known shared API/database/test data/service | Record dependency and necessary sequencing or use arrangement in the existing plan. Do not operate real shared environments without authorization or build automatic dependency analysis. |
|
|
31
|
+
|
|
32
|
+
Records can be stale and cannot detect all other work. Do not switch another session's branch, stash, overwrite or clean unknown changes. The state tool's short write lock/revision check protects an individual state update; it does not reserve a checkout or enforce this workflow across sessions.
|
|
33
|
+
|
|
34
|
+
## Agree an ordered arrangement
|
|
35
|
+
|
|
36
|
+
Choose stages from the responsibilities below based on the goal and existing inputs. Requirements and scope alignment are always needed; they may be one short conversation and one document. Adopt adequate existing artifacts as inputs without claiming their stages were newly executed. Do not create empty stage runs or templates.
|
|
37
|
+
|
|
38
|
+
Show the selected order and endpoint. If the user already specified or accepted this arrangement, record the decision and proceed. An unanswered proposal remains a proposal. Once agreed, follow the order; adding, dropping or reordering work needs a reason and an updated record. Important changes follow [change flow](sources-and-changes.md). A stage may recur as distinct instances with stable IDs and explicit scopes.
|
|
39
|
+
|
|
40
|
+
Explain each design's key decisions, why they fit the requirements, tradeoffs, artifact location and remaining questions. Ordinary internal implementation choices stay with the agent. Ask for material changes to goals, scope, external behavior, compatibility, significant cost, data handling or an explicit technical commitment. Honor an agreed human review point, without adding approvals to every document.
|
|
41
|
+
|
|
42
|
+
## Stage references
|
|
43
|
+
|
|
44
|
+
Read the reference for the current responsibility, not all thirteen on every turn.
|
|
45
|
+
|
|
46
|
+
| Responsibility | Read when | Reference |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| frame | Clarifying a problem or exploring a goal | [frame](stages/frame.md) |
|
|
49
|
+
| requirements | Defining or refining requirements | [requirements](stages/requirements.md) |
|
|
50
|
+
| prototype | Designing interaction and its states | [prototype](stages/prototype.md) |
|
|
51
|
+
| scope | Adopting inputs and aligning this commission | [scope](stages/scope.md) |
|
|
52
|
+
| diagnose | Investigating cause or feasibility | [diagnose](stages/diagnose.md) |
|
|
53
|
+
| tech-design | Choosing an engineering approach | [tech-design](stages/tech-design.md) |
|
|
54
|
+
| contract | Defining interfaces and exchanged data | [contract](stages/contract.md) |
|
|
55
|
+
| plan | Splitting implementation into dependent batches | [plan](stages/plan.md) |
|
|
56
|
+
| test-design | Mapping acceptance and risks to checks | [test-design](stages/test-design.md) |
|
|
57
|
+
| implement | Carrying out an authorized implementation batch | [implement](stages/implement.md) |
|
|
58
|
+
| review | Reviewing a batch, all batches, or affected rework | [review](stages/review.md) |
|
|
59
|
+
| verify | Executing the agreed checks and recording evidence | [verify](stages/verify.md) |
|
|
60
|
+
| handoff | Delivering against the current goal or handing over incomplete work | [handoff](stages/handoff.md) |
|
|
61
|
+
|
|
62
|
+
Each run records its scope, required inputs, results and progress. A result may be a section in a shared document. Proceed when this run's requirements are met, the next inputs exist, authorization covers it and no relevant unresolved issue blocks it. An issue blocks only dependent work; changing the order to continue other work is still an explicit plan change.
|
|
63
|
+
|
|
64
|
+
## Implementation and evidence
|
|
65
|
+
|
|
66
|
+
For multiple batches: implement batch → review batch, repeat; after every batch is complete and reviewed, review the whole change, then independently verify. For one batch, one review record may explicitly cover both batch and whole-change scopes. Do not create a complete testing gate after every batch. Planned tests can be written with implementation; writing them does not mean they passed.
|
|
67
|
+
|
|
68
|
+
Record review and verification against actual objects: repository ID, commit if any, relevant uncommitted/untracked paths and content digests or necessary patch, scope and baseline. Distinguish pre-existing changes. A branch name alone is insufficient. For documents record file/section and the content basis; preserve necessary old excerpts when a digest would not explain the reviewed meaning.
|
|
69
|
+
|
|
70
|
+
Each conclusion identifies who/what produced it, date, object/version, scope, basis, result and evidence. Distinguish user review, agent review, actual execution and user-reported results. Actual verification also records commands or operations, environment/data, case version and unexecuted checks. If the object changes during testing, determine which results remain applicable and retest affected checks.
|
|
71
|
+
|
|
72
|
+
Execution progress (`planned`, `active`, `blocked`, `done`) is separate from pass/fail/not-run/unknown, current applicability, goal achievement and user acceptance. A finished failed verification is still failed. Review is not runtime testing. Neither the presence of a report nor successful tool exit proves the goal.
|
|
73
|
+
|
|
74
|
+
## State and stopping
|
|
75
|
+
|
|
76
|
+
Use the installed tool's documented state protocol. Read the current revision before a write and provide the expected revision; never bypass a conflict by blindly increasing it. State stores summaries and references, not copies of requirements or test reports. Persist the unfinished intent before changing multiple documents, then verify the artifacts before recording completion. No cross-file transaction is promised.
|
|
77
|
+
|
|
78
|
+
Important semantic changes retain historical review and test facts, mark affected conclusions for review and update the current editable authority. Do not overwrite external adopted sources. See [sources and change flow](sources-and-changes.md).
|
|
79
|
+
|
|
80
|
+
At stable results save the state, remaining issues and next action. On a session switch give: “Use Aimship to continue <absolute delivery directory>; read state.json, the current goal/Scope and next-step inputs; <specific blocker if any>.” A new session reloads the same delivery, not the whole transcript. Use [recovery](recovery.md) for mismatch or uncertainty. Keep one active writing session per delivery.
|
|
81
|
+
|
|
82
|
+
End when the current confirmed goal is met. For design work this means the agreed design, not code execution. For development it includes agreed review and verification. “Show me the result” does not shorten the goal. If the user explicitly changes the endpoint, preserve the old goal, decision and unfinished work, update the arrangement, and assess the revised goal. An incomplete handoff is allowed but is not goal completion.
|
|
83
|
+
|
|
84
|
+
Small corrections within the original goal can reopen the same delivery: preserve its previous closure and result basis, increment the cycle, and review/verify affected work. A separate goal or substantial redesign starts a related delivery; retain the defect or source relationship without introducing parent/child scheduling. Prepared, accepted, merged and deployed are independent facts.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Optional document patterns
|
|
2
|
+
|
|
3
|
+
Use only the needed sections and artifacts. These are prompts for useful content, not empty files to generate automatically. Small work may combine diagnosis, test design, review, verification and handoff in `results.md`, with distinct referenced sections.
|
|
4
|
+
|
|
5
|
+
**Requirements / Scope:** original request or adopted source; background; current goal and endpoint; included/excluded scope; authorized objects and constraints; requirements and acceptance criteria; source mapping; conflicts/decisions and open questions. Keep original input separate from revised current content.
|
|
6
|
+
|
|
7
|
+
**Technical design:** current requirement basis; engineering constraints; chosen structure and alternatives/tradeoffs; interface links; data and compatibility; failure/recovery; risks and open decisions. For database changes link the independent SQL and its dialect/version, existing schema basis and execution conditions.
|
|
8
|
+
|
|
9
|
+
**Plan:** batch ID and goal; requirement coverage; files/repositories and boundary; dependencies and interface; each batch review scope; overall review and independent verification. State tracks progress, so do not create a competing progress table.
|
|
10
|
+
|
|
11
|
+
**Verification plan:** requirement/risk → scenario and observable expected result; environment/data/tools; normal, error, boundary and relevant regression cases; known execution gaps. Keep missing-condition cases visible.
|
|
12
|
+
|
|
13
|
+
**Review record:** actor/source and date; exact objects/versions/differences; batch/overall/affected scope; requirements/design basis; findings, disposition and conclusion. A single-batch review explicitly covers both batch and overall responsibilities.
|
|
14
|
+
|
|
15
|
+
**Verification record:** actor/source and date; case version; tested code/build and environment; executed commands/operations; assertions and actual results; pass/fail/not-run/unknown; evidence locations; missing conditions and recovery action. Append a retest rather than rewriting the earlier failure.
|
|
16
|
+
|
|
17
|
+
**Change:** stable ID; reason and decision source; old/new meaning; affected artifacts/runs; remaining uncertainty; work completed and review/verification result. One important decision affecting several artifacts remains one record.
|
|
18
|
+
|
|
19
|
+
**Handoff:** current goal (and explicit revision if any); completed deliverables and links; how to use/check; actual review and verification scope; limitations/remaining work; goal achievement, acceptance, merge and deployment as separate facts; continuation if incomplete.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Host access
|
|
2
|
+
|
|
3
|
+
Reuse the current session's access when normal file operations succeed. Do not create probe files, rescan all permissions every stage or treat a second project as permission for the current conversation. Keep the materials directory separate from repository roots and set the correct working directory for engineering commands.
|
|
4
|
+
|
|
5
|
+
When access is missing, name the exact delivery/repository path and the needed operation. Retain the original request and continuation context. Do not disable host permission controls, grant the entire home directory or silently move materials into the repository.
|
|
6
|
+
|
|
7
|
+
- Codex: explicitly select Aimship (CLI `$aimship`). If CLI startup is needed, verify the executable/version/help and use its supported `--cd` and repeated `--add-dir` syntax for the needed writable directories. For desktop, rely on the actual current interface or official guidance; never invent a directory button or claim a prepared path has been granted access.
|
|
8
|
+
- Cursor: explicitly use `/aimship`. When useful, prepare `host/cursor.code-workspace` inside the delivery with `folders` entries only, referencing materials and repositories; preserve an existing workspace's settings. The user opens/adds folders when necessary. For CLI verify the exact executable (do not assume bare `agent` is Cursor) and current `--workspace` / `--add-dir` support.
|
|
9
|
+
- Claude Code: explicitly use `/aimship`; verify current `/add-dir` or `--add-dir` behavior when additional access is needed. Do not fork the skill or start a subagent.
|
|
10
|
+
|
|
11
|
+
Installation discovery, actual selection, model behavior, directory access and continuation are separate evidence levels. Codex/Cursor share the managed `.agents/skills/aimship` entry; Claude Code uses `.claude/skills/aimship`. A host may discover both, including when it is not registered with Aimship. Registration controls installer-managed connections, not another host’s compatibility scanning. Managed entries must point to the same stable installation; do not assume duplicate precedence or delete unrelated entries. Record duplicates as observed, and consult the published support matrix for tested surfaces.
|
|
12
|
+
|
|
13
|
+
After compaction or manual switching, reload the fixed-version core, state and current-stage inputs if missing. Do not rely on a host retaining all skill text. If even the binding location is absent, request the delivery path. Re-invoking an entry to restore context continues the existing delivery; it does not create another one.
|
|
14
|
+
|
|
15
|
+
When changing hosts, use the same delivery directory and state; do not duplicate requirements, Scope or design to establish a new session. Permissions must be granted separately in each host. Keep one writing host/session for the delivery. User-facing entry/reload and lifecycle instructions are in [the installation guide](../../../docs/installation.md).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Resume, recover and update
|
|
2
|
+
|
|
3
|
+
Start by locating the same delivery. Read state, current goal/Scope and next-step references. Verify actual artifacts or related changes only when needed to act or reuse a conclusion. Restoring context is not a new test result. If the directory is ambiguous, ask for the missing location, not already recorded goals and decisions.
|
|
4
|
+
|
|
5
|
+
A revision conflict means another writer or manual change intervened. Read and reconcile; do not force overwrite. One writing session per delivery remains the supported workflow. On malformed state, preserve the damaged file, inspect the last recovery copy and actual subsequent artifacts, then explicitly recover only the trustworthy facts. If no reliable copy exists, reconstruct from readable requirements/change/results, marking uncertain authorization and results unknown. Never rerun a side effect just because state is incomplete.
|
|
6
|
+
|
|
7
|
+
A path move requires the provided new location and identity evidence, not a disk-wide name search. Keep IDs stable. Repair references after checking the relevant repository/delivery; do not move or copy code. Preserve manual document edits and assess their intent and downstream impact before updating state.
|
|
8
|
+
|
|
9
|
+
A tool/version mismatch stops new stage advancement. Save only in-progress facts through the documented limited checkpoint if safe; it cannot finish a stage or declare a goal met. At a stable boundary read the current complete installation's core, current stage and state, handle any compatibility needs, then explicitly adopt the current rules version. Keep the same goal, decisions and history. If the old context cannot reliably refresh, give the manual continuation prompt; do not open a new conversation automatically.
|
|
10
|
+
|
|
11
|
+
Unknown newer formats remain readable as files but must not be overwritten or silently downgraded. Structural migrations require a supported conversion, necessary backup, clear description and validation. If no migration exists, preserve the materials and state the gap; do not invent historical stages. Compatible rules updates do not require new goal approval. Never sweep ended deliveries during install; only assess an ended delivery when it is reopened.
|
|
12
|
+
|
|
13
|
+
Installation and data are separate. Explicit install manages product-owned files and host entries. Preserve user customizations and unrelated same-name skills; report the exact conflict. Uninstall retains delivery materials, customization and necessary configuration. Recovery retains a bounded previous installation, not every runtime forever. Consult the CLI help for implemented operations; do not bypass checks with raw state edits to obtain a success result.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Sources, artifacts and change flow
|
|
2
|
+
|
|
3
|
+
## Adopt without rewriting the source
|
|
4
|
+
|
|
5
|
+
Preserve the original request once. For external PRDs, prototypes and images keep the original and necessary adopted version read-only. Keep referenced HTML/Markdown assets when needed to understand that version. A mutable URL alone cannot establish what was adopted. Record origin, location, version/digest, adopted sections and reading gaps. Do not claim visual understanding from text extraction or file storage.
|
|
6
|
+
|
|
7
|
+
Use existing requirement IDs. If none exist, assign local IDs mapped to source sections, pages, prototype screens or short excerpts. Scope records the current goal, inclusion/exclusion, source mappings, acceptance, constraints, conflicts and adopted decisions. Do not transcribe an entire adequate PRD or create a second one merely to fit a template. Self-owned requirements may also carry Scope.
|
|
8
|
+
|
|
9
|
+
A prototype and PRD can disagree; neither file type nor modification date automatically wins. Record the conflict and decision authority. Pause dependent work when a material answer is missing, while continuing independent authorized work. Do not contact the external author automatically. If a new version arrives, adopt it separately, assess relevant differences and retain the old basis. Indicate any external document still awaiting its author's correction.
|
|
10
|
+
|
|
11
|
+
## Artifact boundaries
|
|
12
|
+
|
|
13
|
+
Use relative references within the delivery. Identify engineering files by repository ID and repository-relative path; keep local repository locations in the user's delivery state, not public product content. Record role, authorization and relevant working version. Do not store credential-bearing remote URLs.
|
|
14
|
+
|
|
15
|
+
For HTTP interfaces, reuse the engineering repository's authoritative OpenAPI; only create a delivery-local contract when none exists. Other protocols use the appropriate engineering format. Explain decisions in technical design and link details rather than duplicating the contract. No interface change means no mandatory contract.
|
|
16
|
+
|
|
17
|
+
When the design changes a table, column, index or data, produce a separate SQL file in the delivery directory, with technical design describing dialect/version, existing schema basis, preconditions, sequence and relevant data impact. SQL is an ordinary formal artifact, with the same review/change rules as designs and tests. A code block or reference to an engineering migration does not replace it. Default scope does not edit migration files or execute SQL. Explicitly authorized integration/execution is handled within its environment and recorded file version; prepared, reviewed, tested and production-applied remain distinct. Missing dialect/schema details prevent an implementation-ready claim.
|
|
18
|
+
|
|
19
|
+
Markdown/HTML are principal carriers, not a format whitelist. Images, screenshots, wireframes and diagrams can be sources or outputs. Record separately text reading, visual inspection, interaction checks, generation and native-format editing. PDF/DOCX/online inputs depend on available tools and access. Missing tools require an honest gap and a feasible alternative; changing agreed output requires a decision. A still image does not establish interactions, error states, permissions or responsiveness. Never add a universal conversion service to the task.
|
|
20
|
+
|
|
21
|
+
## One record for an important change
|
|
22
|
+
|
|
23
|
+
1. Persist the reason, old/new intent, decision/source or open question, affected artifacts/runs and uncertainties in one change record.
|
|
24
|
+
2. Update editable requirements/Scope, design, contracts, independent SQL, plan and test cases where affected. Preserve external sources and necessary old excerpts.
|
|
25
|
+
3. Mark affected conclusions as needing review; historical records keep their original object and outcome. Leave unrelated results intact.
|
|
26
|
+
4. Review affected work and execute affected verification as required by the goal, then close the same change with its result and remaining issues.
|
|
27
|
+
|
|
28
|
+
Formatting/typo corrections do not require semantic re-review. Implementation bugs are fixed against the requirements; do not weaken the requirements to match the bug. Tools detect structural problems, not every semantic dependency. State uncertainty in the impact analysis rather than claiming complete automatic coverage.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Define interfaces
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read the current requirements, technical design and existing engineering contracts.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Update/reuse the authoritative HTTP OpenAPI when applicable; create a delivery-local OpenAPI only if the engineering authority is absent. Specify operations, schemas, errors, compatibility and consumer expectations. Use appropriate formats for messages/non-HTTP interfaces. Link design and test requirements.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
The cooperating parties have an unambiguous applicable contract consistent with the current requirements/design. No relevant interface change means this responsibility need not be selected.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
A breaking interface/compatibility decision needs its proper authority. Missing consumers or schemas remain stated gaps, not fabricated agreements.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Investigate cause or feasibility
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read reported symptoms, expected behavior, relevant code/material and reproducible evidence.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Investigate within authorized objects. Record observations, reproduction or supporting evidence, probable/established causes and remaining uncertainty. Keep incidental behavior changes out of a refactor.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
The investigation goal is met, or the inability to determine a cause and a concrete next step are accurately stated. A hypothesis is not a confirmed root cause.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
If the apparent small fix expands into behavior or scope changes, explain the impact before dependent implementation.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Clarify the problem
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read the original request, background, constraints and available evidence.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Establish the problem, intended outcome, non-goals and assumptions worth checking. Separate known facts from hypotheses; a short section in requirements is enough.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
The commissioned exploration has a clear objective and its uncertainty is visible. Do not force this stage when the goal is already clear.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
A missing business objective or incompatible expected outcomes needs a user decision; independent evidence gathering may continue.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Deliver against the goal
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read the current goal/Scope, explicit goal revisions, deliverables, applicable review/verification and unresolved work.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Provide deliverable links, use/check instructions, actual validation scope and limits, goal changes and unfinished items. Identify each actual code checkout/worktree, branch and commit when available, relevant uncommitted changes, and whether integration/merge is still pending (including target/dependencies if known). A completed branch is not a merged change. Independently record goal achievement, user acceptance, merge and deployment. Save next-step context when incomplete.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
The report honestly matches the current commissioned endpoint. Complete the delivery only when its actual completion criteria are satisfied. A user-authorized partial endpoint preserves the old goal and remaining work.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
Showing results does not revise the endpoint. Required blocked verification means incomplete acceptance, even when code is ready. Small later corrections reopen with preserved closure; independent goals create related deliveries.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Implement one batch
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read this run’s scope, current requirements/design/contracts, relevant repository instructions and pre-existing changes.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Before entering implementation, or when a code working directory changes, apply the [recorded-overlap check](../core.md#independent-deliveries-and-recorded-overlap). Reuse an existing user-selected sequence or isolated checkout; unresolved same-checkout writing overlap holds the affected code writes, not independent design work. Complete this batch using the existing engineering stack. Write planned test code where appropriate. Preserve user work and external sources. Record deviations and route semantic changes through the current authority, including SQL when affected. Engineering commands use the repository working directory.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
The planned batch is implemented and known deviations are resolved or explicitly routed. Move to this batch’s review; running a complete test suite is not a new batch gate.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
Expanded external behavior, data handling or authorization needs return to the relevant decision. A rejected permission remains blocked and is not retried through another host.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Plan implementation batches
|
|
2
|
+
|
|
3
|
+
## Basis
|
|
4
|
+
|
|
5
|
+
Read current Scope, applicable design/contracts and relevant repository boundaries.
|
|
6
|
+
|
|
7
|
+
## Work and result
|
|
8
|
+
|
|
9
|
+
Define executable batches, each goal and requirement coverage, dependencies, authorized file/repository scope and interfaces. Arrange batch implementation/review, overall review, then independent verification. Include known cross-delivery interface, database, test-data/service and integration dependencies in this same plan, with necessary sequencing or use arrangements. Keep test-code development in appropriate batches; do not add per-batch full testing gates.
|
|
10
|
+
|
|
11
|
+
## Continue when
|
|
12
|
+
|
|
13
|
+
Batches can be executed in order and together cover the delivery goal. Small work may keep a concise ordered arrangement in state rather than a separate plan.
|
|
14
|
+
|
|
15
|
+
## Decisions and blockers
|
|
16
|
+
|
|
17
|
+
A material change in scope/endpoint needs a decision; routine task splitting does not. Record the reason if changing the existing order.
|
|
18
|
+
|
|
19
|
+
Use [the shared core](../core.md) for state, evidence and continuation rules. Record meaningful results in an artifact or referenced section; a file alone is not completion.
|