specline 1.4.0 → 2.0.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/README.md +132 -125
- package/adapters/claude/deploy.json +12 -0
- package/adapters/claude/hooks/hooks.json +12 -0
- package/adapters/claude/hooks.json +12 -0
- package/adapters/claude/orchestration.md +17 -0
- package/adapters/codex/agent.toml.hbs +7 -0
- package/adapters/codex/deploy.json +12 -0
- package/adapters/codex/hooks.json +12 -0
- package/adapters/codex/orchestration.md +18 -0
- package/adapters/cursor/deploy.json +12 -0
- package/adapters/cursor/hooks.json +9 -0
- package/adapters/cursor/orchestration.md +17 -0
- package/adapters/opencode/deploy.json +12 -0
- package/adapters/opencode/orchestration.md +18 -0
- package/adapters/opencode/plugin.js +10 -0
- package/cli.mjs +161 -558
- package/core/agents/specline-backend-dev.yaml +45 -0
- package/core/agents/specline-code-reviewer.yaml +67 -0
- package/core/agents/specline-config-dev.yaml +50 -0
- package/core/agents/specline-config-reviewer.yaml +70 -0
- package/core/agents/specline-explore-assistant.yaml +79 -0
- package/core/agents/specline-frontend-dev.yaml +45 -0
- package/core/agents/specline-spec-creator.yaml +58 -0
- package/core/agents/specline-spec-reviewer.yaml +58 -0
- package/core/agents/specline-test-runner.yaml +62 -0
- package/core/agents/specline-test-writer.yaml +67 -0
- package/core/bootstrap/using-specline.md +14 -0
- package/core/gates/pipeline-gate-checks/a1-covers-ref.sh +125 -0
- package/core/gates/pipeline-gate-checks/a2-a3-reverse.sh +171 -0
- package/core/gates/pipeline-gate-checks/c1-exception.sh +71 -0
- package/core/gates/pipeline-gate-checks/c2-vague.sh +60 -0
- package/core/gates/pipeline-gate-checks/common.sh +68 -0
- package/core/gates/pipeline-gate-checks/d1-cycle.sh +149 -0
- package/core/gates/pipeline-gate-checks/d3-type-file.sh +260 -0
- package/core/gates/pipeline-gate.sh +1456 -0
- package/core/hooks/session-start.sh +259 -0
- package/core/skills/specline-apply-change/SKILL.md +197 -0
- package/core/skills/specline-archive-change/SKILL.md +173 -0
- package/core/skills/specline-explore/SKILL.md +504 -0
- package/core/skills/specline-knowledge/SKILL.md +539 -0
- package/core/skills/specline-pipeline/SKILL.md +604 -0
- package/core/skills/specline-pipeline/references/error-recovery-details.md +49 -0
- package/core/skills/specline-pipeline/references/event-log-spec.md +59 -0
- package/core/skills/specline-pipeline/references/pipeline-state-schema.md +87 -0
- package/core/skills/specline-pipeline/templates/subagent-prompts.md +397 -0
- package/core/skills/specline-propose/SKILL.md +186 -0
- package/core/skills/specline-quickfix/SKILL.md +289 -0
- package/core/templates/AGENTS.md.hbs +5 -0
- package/core/templates/specline/config.yaml +15 -0
- package/lib/deploy-claude.mjs +80 -0
- package/lib/deploy-codex.mjs +77 -0
- package/lib/deploy-opencode.mjs +93 -0
- package/lib/deploy.mjs +668 -0
- package/lib/gate.mjs +103 -0
- package/lib/hash.mjs +13 -0
- package/lib/hook.mjs +105 -0
- package/lib/init.mjs +122 -0
- package/lib/lock.mjs +99 -0
- package/lib/merge.mjs +184 -0
- package/lib/paths.mjs +40 -0
- package/lib/platforms.mjs +74 -0
- package/lib/render-agents.mjs +88 -0
- package/lib/render.mjs +126 -0
- package/lib/sync.mjs +253 -0
- package/lib/tty-select.mjs +89 -0
- package/package.json +4 -1
- package/templates/.cursor/README.md +18 -0
- package/templates/.cursor/agents/specline-code-reviewer.md +18 -2
- package/templates/.cursor/agents/specline-spec-creator.md +51 -2
- package/templates/.cursor/agents/specline-test-runner.md +10 -1
- package/templates/.cursor/agents/specline-test-writer.md +58 -7
- package/templates/.cursor/hooks/specline-pipeline-gate-checks/a2-a3-reverse.sh +1 -1
- package/templates/.cursor/hooks/specline-pipeline-gate.sh +118 -0
- package/templates/.cursor/skills/specline-pipeline/SKILL.md +10 -4
- package/templates/.cursor/skills/specline-propose/SKILL.md +3 -3
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { PACKAGE_ROOT } from './paths.mjs';
|
|
4
|
+
import { getOpencodeUpstreamManifest, writeManifestToProject } from './deploy.mjs';
|
|
5
|
+
import { mergeOpencodeJson } from './merge.mjs';
|
|
6
|
+
|
|
7
|
+
const PLUGIN_REL = 'specline/opencode-plugin/plugin.js';
|
|
8
|
+
const OPENCODE_JSON_REL = 'opencode.json';
|
|
9
|
+
const PLUGIN_ENTRY = './specline/opencode-plugin';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Deploy Specline assets to an OpenCode project.
|
|
13
|
+
*
|
|
14
|
+
* Skills -> .opencode/skills/ | Plugin -> specline/opencode-plugin/plugin.js
|
|
15
|
+
* Merge opencode.json plugin entry. No agent files generated.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} projectDir Target project root
|
|
18
|
+
* @param {{ packageRoot?: string, dryRun?: boolean }} [options]
|
|
19
|
+
* @returns {{ filesWritten: string[], opencodeJsonAction: 'created'|'merged'|'unchanged' }}
|
|
20
|
+
*/
|
|
21
|
+
export function deployOpencode(projectDir, options = {}) {
|
|
22
|
+
const { packageRoot = PACKAGE_ROOT, dryRun = false } = options;
|
|
23
|
+
|
|
24
|
+
const manifest = getOpencodeUpstreamManifest(packageRoot);
|
|
25
|
+
|
|
26
|
+
manifest.delete(PLUGIN_REL);
|
|
27
|
+
manifest.delete(OPENCODE_JSON_REL);
|
|
28
|
+
|
|
29
|
+
const filesWritten = [];
|
|
30
|
+
|
|
31
|
+
if (!dryRun) {
|
|
32
|
+
for (const dir of ['.opencode/skills', 'specline/opencode-plugin']) {
|
|
33
|
+
const full = join(projectDir, dir);
|
|
34
|
+
if (!existsSync(full)) mkdirSync(full, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
writeManifestToProject(projectDir, manifest);
|
|
37
|
+
}
|
|
38
|
+
for (const rel of manifest.keys()) filesWritten.push(rel);
|
|
39
|
+
|
|
40
|
+
deployPluginJs(projectDir, packageRoot, dryRun);
|
|
41
|
+
filesWritten.push(PLUGIN_REL);
|
|
42
|
+
|
|
43
|
+
const opencodeJsonAction = mergeOpencodeJsonFile(projectDir, dryRun);
|
|
44
|
+
filesWritten.push(OPENCODE_JSON_REL);
|
|
45
|
+
|
|
46
|
+
return { filesWritten, opencodeJsonAction };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Copy plugin.js from adapters/opencode/ to specline/opencode-plugin/.
|
|
51
|
+
*/
|
|
52
|
+
function deployPluginJs(projectDir, packageRoot, dryRun) {
|
|
53
|
+
const src = join(packageRoot, 'adapters', 'opencode', 'plugin.js');
|
|
54
|
+
const dest = join(projectDir, PLUGIN_REL);
|
|
55
|
+
if (!existsSync(src)) return;
|
|
56
|
+
|
|
57
|
+
if (!dryRun) {
|
|
58
|
+
const dir = dirname(dest);
|
|
59
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
60
|
+
copyFileSync(src, dest);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Merge opencode.json in project root.
|
|
66
|
+
*
|
|
67
|
+
* - Existing file: ensure "plugin" array includes specline entry, preserve rest
|
|
68
|
+
* - No file: create minimal { "plugin": ["./specline/opencode-plugin"] }
|
|
69
|
+
*
|
|
70
|
+
* @param {string} projectDir
|
|
71
|
+
* @param {boolean} dryRun
|
|
72
|
+
* @returns {'created'|'merged'|'unchanged'}
|
|
73
|
+
*/
|
|
74
|
+
function mergeOpencodeJsonFile(projectDir, dryRun) {
|
|
75
|
+
const jsonPath = join(projectDir, OPENCODE_JSON_REL);
|
|
76
|
+
|
|
77
|
+
if (existsSync(jsonPath)) {
|
|
78
|
+
const existingContent = readFileSync(jsonPath, 'utf-8');
|
|
79
|
+
const merged = mergeOpencodeJson(existingContent, PLUGIN_ENTRY);
|
|
80
|
+
if (merged === existingContent) return 'unchanged';
|
|
81
|
+
|
|
82
|
+
if (!dryRun) {
|
|
83
|
+
writeFileSync(jsonPath, merged, 'utf-8');
|
|
84
|
+
}
|
|
85
|
+
return 'merged';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!dryRun) {
|
|
89
|
+
const fresh = mergeOpencodeJson('', PLUGIN_ENTRY);
|
|
90
|
+
writeFileSync(jsonPath, fresh, 'utf-8');
|
|
91
|
+
}
|
|
92
|
+
return 'created';
|
|
93
|
+
}
|