@skitterbyte/skitterspec-linear 1.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 +56 -0
- package/assets/claude-md-section.md +39 -0
- package/assets/core/env.config.json.example +28 -0
- package/assets/core/env.config.md +99 -0
- package/assets/core/linear.config.json.example +39 -0
- package/assets/core/linear.config.md +121 -0
- package/assets/rules/spec-planning.md +152 -0
- package/assets/skills/spec/SKILL.md +232 -0
- package/assets/skills/spec-bug/SKILL.md +110 -0
- package/assets/skills/spec-cancel/SKILL.md +61 -0
- package/assets/skills/spec-complete/SKILL.md +87 -0
- package/assets/skills/spec-env/SKILL.md +63 -0
- package/assets/skills/spec-env-down/SKILL.md +64 -0
- package/assets/skills/spec-go/SKILL.md +134 -0
- package/assets/skills/spec-init/SKILL.md +84 -0
- package/assets/skills/spec-pull/SKILL.md +46 -0
- package/assets/skills/spec-push/SKILL.md +53 -0
- package/assets/skills/spec-ready/SKILL.md +50 -0
- package/assets/skills/spec-review/SKILL.md +69 -0
- package/assets/skills/spec-status/SKILL.md +46 -0
- package/bin/skitterspec-linear.js +26 -0
- package/package.json +38 -0
- package/src/cli.js +495 -0
- package/src/deprecate.js +138 -0
- package/src/env/config.js +165 -0
- package/src/env/integrate.js +46 -0
- package/src/env/provision.js +76 -0
- package/src/env/registry.js +95 -0
- package/src/env/render.js +26 -0
- package/src/env/resolve.js +202 -0
- package/src/env/teardown.js +109 -0
- package/src/env/trust.js +87 -0
- package/src/init.js +311 -0
- package/src/prompts.js +56 -0
- package/src/vendor/linear/cli-sync.js +256 -0
- package/src/vendor/linear/config.js +198 -0
- package/src/vendor/linear/mcp.js +112 -0
- package/src/vendor/sync-core/index.js +35 -0
- package/src/vendor/sync-core/src/apply.js +66 -0
- package/src/vendor/sync-core/src/base.js +83 -0
- package/src/vendor/sync-core/src/compare.js +99 -0
- package/src/vendor/sync-core/src/normalize.js +249 -0
- package/src/vendor/sync-core/src/pull.js +84 -0
- package/src/vendor/sync-core/src/push.js +106 -0
- package/src/vendor/sync-core/src/write.js +86 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Local snapshot writes for pull (remote → repo).
|
|
5
|
+
*
|
|
6
|
+
* Phase 2 applies **frontmatter-mapped** pulled fields — the `pull`-owned data
|
|
7
|
+
* remote genuinely owns (`workflowState` → `spec_status`, `priority`, `labels`)
|
|
8
|
+
* plus sync bookkeeping (`last_synced_at`, ids) — by surgically editing the YAML
|
|
9
|
+
* frontmatter of `00-overview.md` and leaving the markdown body byte-for-byte
|
|
10
|
+
* untouched. Existing keys are updated in place (order preserved); new keys are
|
|
11
|
+
* appended; a file with no frontmatter gets one prepended.
|
|
12
|
+
*
|
|
13
|
+
* Body/`both`-owned fields (`description`, `milestones`, …) are NOT written back
|
|
14
|
+
* here — that denormalizer is a tracked follow-up (see the spec). Callers advance
|
|
15
|
+
* the base only for fields they actually applied, so an un-applied remote edit
|
|
16
|
+
* stays pending rather than being silently marked synced.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('node:fs')
|
|
20
|
+
const path = require('node:path')
|
|
21
|
+
|
|
22
|
+
// Serialize a JS value as a YAML-ish frontmatter scalar. null/undefined → the
|
|
23
|
+
// key is dropped (caller shouldn't pass those).
|
|
24
|
+
function serialize(value) {
|
|
25
|
+
if (Array.isArray(value)) return JSON.stringify(value)
|
|
26
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value)
|
|
27
|
+
return JSON.stringify(String(value)) // quoted string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Split `---\n…\n---\n` frontmatter off the top. Returns { fmLines, body, had }.
|
|
31
|
+
function splitFrontmatter(raw) {
|
|
32
|
+
const m = /^---\n([\s\S]*?)\n---\n?/.exec(raw)
|
|
33
|
+
if (!m) return { fmLines: [], body: raw, had: false }
|
|
34
|
+
return { fmLines: m[1].split('\n'), body: raw.slice(m[0].length), had: true }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Apply a key→value patch onto frontmatter lines, preserving order.
|
|
38
|
+
function patchFrontmatterLines(lines, patch) {
|
|
39
|
+
const keys = new Set(Object.keys(patch))
|
|
40
|
+
const out = []
|
|
41
|
+
const seen = new Set()
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line)
|
|
44
|
+
if (kv && keys.has(kv[1])) {
|
|
45
|
+
out.push(`${kv[1]}: ${serialize(patch[kv[1]])}`)
|
|
46
|
+
seen.add(kv[1])
|
|
47
|
+
} else {
|
|
48
|
+
out.push(line)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Append any new keys not already present.
|
|
52
|
+
for (const key of Object.keys(patch)) {
|
|
53
|
+
if (!seen.has(key)) out.push(`${key}: ${serialize(patch[key])}`)
|
|
54
|
+
}
|
|
55
|
+
return out
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Update `00-overview.md` frontmatter under `snapshotDir` with `patch`
|
|
60
|
+
* (key → value; nullish values are skipped). Returns the list of keys written.
|
|
61
|
+
*/
|
|
62
|
+
function writeFrontmatter(snapshotDir, config, patch) {
|
|
63
|
+
const overviewFile = (config && config.snapshot && config.snapshot.overviewFile) || '00-overview.md'
|
|
64
|
+
const file = path.join(snapshotDir, overviewFile)
|
|
65
|
+
const raw = fs.readFileSync(file, 'utf-8')
|
|
66
|
+
|
|
67
|
+
const clean = {}
|
|
68
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
69
|
+
if (v !== null && v !== undefined) clean[k] = v
|
|
70
|
+
}
|
|
71
|
+
if (!Object.keys(clean).length) return []
|
|
72
|
+
|
|
73
|
+
const { fmLines, body, had } = splitFrontmatter(raw)
|
|
74
|
+
const patched = patchFrontmatterLines(fmLines, clean)
|
|
75
|
+
const frontmatter = `---\n${patched.join('\n')}\n---\n`
|
|
76
|
+
const next = had ? frontmatter + body : frontmatter + '\n' + raw
|
|
77
|
+
|
|
78
|
+
fs.writeFileSync(file, next, 'utf-8')
|
|
79
|
+
return Object.keys(clean)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
writeFrontmatter,
|
|
84
|
+
splitFrontmatter,
|
|
85
|
+
serialize,
|
|
86
|
+
}
|