Initial publish v0.1.0: standalone workflow core (corpus + examples + guards)

This commit is contained in:
octopus
2026-09-15 08:41:51 +08:00
commit bb35e661b2
114 changed files with 20240 additions and 0 deletions
+205
View File
@@ -0,0 +1,205 @@
#!/usr/bin/env bun
import fs from "node:fs"
import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..")
const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json")
const CORE_ROOT = path.join(ROOT, "core")
export const HARD_PATTERNS: RegExp[] = [
/\bins24\b/,
/dev\.eightarms\.net/,
/10\.\d+\.\d+\.\d+/,
/192\.168\.\d+\.\d+/,
/172\.(1[6-9]|2\d|3[01])\.\d+\.\d+/,
/~\/\.config\/octopus/,
]
export const SOFT_PATTERNS: RegExp[] = [
/\.octopus\//,
/examples\//,
/\/data\/git/,
/\bins24\b/,
/dev\.eightarms\.net/,
/gitea_wiki__/,
/gitea_issue_comment__/,
/gitea_column__/,
/gitea_project__/,
/packages\/octopus/,
/~\/\.config\/octopus/,
]
export const INSTANCE_PATTERNS: RegExp[] = SOFT_PATTERNS
export function stripCodeSpans(line: string): string {
return line.replace(/`[^`]*`/g, "")
}
export function stripFencedBlocks(lines: string[]): string[] {
let inFence = false
return lines.filter((line) => {
if (line.trimStart().startsWith("```")) {
inFence = !inFence
return false
}
return !inFence
})
}
function scanFile(relFile: string, patterns: RegExp[]): string[] {
const file = path.join(ROOT, relFile)
const lines = stripFencedBlocks(fs.readFileSync(file, "utf8").split("\n"))
const violations: string[] = []
lines.forEach((line) => {
const effective = stripCodeSpans(line)
for (const pattern of patterns) {
if (pattern.test(effective)) {
violations.push(`${relFile}: ${pattern.source}`)
}
}
})
return violations
}
export function findInstanceViolations(relFile: string): string[] {
return scanFile(relFile, INSTANCE_PATTERNS)
}
export function findHardViolations(relFile: string): string[] {
return scanFile(relFile, HARD_PATTERNS)
}
export function scanContent(relFile: string, content: string, patterns: RegExp[]): string[] {
const lines = stripFencedBlocks(content.split("\n"))
const violations: string[] = []
lines.forEach((line) => {
const effective = stripCodeSpans(line)
for (const pattern of patterns) {
if (pattern.test(effective)) {
violations.push(`${relFile}: ${pattern.source}`)
}
}
})
return violations
}
function findPatternsFor(relFile: string): RegExp[] {
if (relFile.startsWith("core/adapters/")) return HARD_PATTERNS
if (relFile === "core/README.md" || relFile === "core/MIGRATION.md")
return [...HARD_PATTERNS, ...SOFT_PATTERNS.filter((p) => p.source !== "examples\\/")]
return [...HARD_PATTERNS, ...SOFT_PATTERNS]
}
interface Mapping {
core: string
dogfood: string | null
sync?: string
deferHard?: boolean
}
function fail(message: string): never {
console.error(`check-core-cohesion: ${message}`)
process.exit(1)
}
function listMarkdownFiles(dir: string, base = ""): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const rel = base ? `${base}/${entry.name}` : entry.name
if (entry.isDirectory()) out.push(...listMarkdownFiles(path.join(dir, entry.name), rel))
else if (entry.name.endsWith(".md") || entry.name.endsWith(".yaml")) out.push(rel)
}
return out
}
if (import.meta.main) {
const STRICT = process.argv.includes("--strict")
if (!fs.existsSync(MANIFEST_PATH)) fail(`manifest not found: ${MANIFEST_PATH}`)
let mappings: Mapping[]
try {
mappings = (JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf8")) as { mappings: Mapping[] }).mappings
} catch (e) {
fail(`manifest is not valid JSON: ${(e as Error).message}`)
}
if (!Array.isArray(mappings) || mappings.length === 0) fail("manifest has no mappings")
const missing: string[] = []
for (const m of mappings) {
if (!fs.existsSync(path.join(ROOT, m.core))) missing.push(m.core)
}
if (missing.length > 0) {
console.error("check-core-cohesion: manifest core path(s) missing:")
for (const p of missing) console.error(` ${p}`)
process.exit(1)
}
const violations: string[] = []
const exempt = new Set<string>()
for (const m of mappings) {
if (m.sync !== "verbatim" && m.sync !== "verbatimDir") continue
if (m.sync === "verbatimDir") {
const dir = m.core.endsWith("/") ? m.core : `${m.core}/`
for (const f of listDir(dir)) exempt.add(`${dir}${f}`)
} else {
exempt.add(m.core)
}
}
const mdFiles = listMarkdownFiles(CORE_ROOT).map((f) => `core/${f}`)
const scanned = mdFiles.filter((rel) => !exempt.has(rel) && !exempt.has(rel.replace(/^core\//, "")))
for (const rel of scanned) {
violations.push(...scanFile(rel, findPatternsFor(rel)))
}
if (STRICT) {
let deferred = 0
let strictScanned = 0
for (const m of mappings) {
if (m.sync !== "verbatim") continue
if (m.deferHard) {
deferred++
continue
}
strictScanned++
violations.push(...scanFile(m.core, INSTANCE_PATTERNS))
}
console.log(`check-core-cohesion: strict verbatim scan: ${strictScanned} scanned, ${deferred} deferred (deferHard)`)
}
if (violations.length > 0) {
console.error("check-core-cohesion: C-1 violation(s):")
for (const v of violations) console.error(` ${v}`)
process.exit(1)
}
console.log(
`check-core-cohesion: ${mappings.length} mappings present, ${scanned.length}/${mdFiles.length} core markdown files scanned, 0 violations`,
)
}
export function listCorpus(relDir: string, base = ""): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(path.join(ROOT, relDir), { withFileTypes: true })) {
const rel = base ? `${base}/${entry.name}` : entry.name
if (entry.isDirectory()) out.push(...listCorpus(path.join(relDir, entry.name), rel))
else if (entry.name.endsWith(".md") || entry.name.endsWith(".yaml")) out.push(rel)
}
return out.sort()
}
export function listDir(relDir: string, base = ""): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(path.join(ROOT, relDir), { withFileTypes: true })) {
const rel = base ? `${base}/${entry.name}` : entry.name
if (entry.isDirectory()) out.push(...listDir(path.join(relDir, entry.name), rel))
else if (entry.name !== ".gitkeep") out.push(rel)
}
return out.sort()
}
export function collectVerbatimDirFiles(m: Mapping): { side: string; files: string[] } | null {
if (m.sync !== "verbatimDir") return null
const rel = m.core.endsWith("/") ? m.core : `${m.core}/`
return { side: rel, files: listDir(rel) }
}
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env bun
import fs from "node:fs"
import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..")
const CORE_ROOT = path.join(ROOT, "core")
const EXEMPT = new Set(["core/schemas/id-aliases.json"])
const P1_PATTERNS: { name: string; re: RegExp }[] = [
{ name: "ins24", re: /\bins24\b/ },
{ name: "private-ip-10", re: /\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/ },
{ name: "private-ip-192", re: /\b192\.168\.\d{1,3}\.\d{1,3}\b/ },
{ name: "private-ip-172", re: /\b172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b/ },
{ name: "config-home", re: /~\/\.config\/octopus/ },
{ name: "dev-instance-host", re: /dev\.eightarms\.net/ },
{ name: "git-data-dirs", re: /\/data\/git-wikis|\/data\/git-worktrees/ },
{ name: "personal-identity", re: /\bzhusi\w*\b/ },
{ name: "org-owner-legacy", re: /\bfourbroad\b/ },
]
function listTextFiles(absDir: string, base = ""): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(absDir, { withFileTypes: true })) {
const rel = base ? `${base}/${entry.name}` : entry.name
if (entry.isDirectory()) out.push(...listTextFiles(path.join(absDir, entry.name), rel))
else if (/\.(md|yaml|json|ts)$/.test(entry.name)) out.push(rel)
}
return out
}
const files = listTextFiles(CORE_ROOT).map((f) => `core/${f}`)
const HISTORICAL_NS_RE = /https:\/\/eightarms\.net\/fourbroad\//
interface Mapping {
core: string
sync: string
}
const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json")
const byteLocked = new Set<string>()
if (fs.existsSync(MANIFEST_PATH)) {
const mappings = (JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf8")) as { mappings: Mapping[] }).mappings
for (const m of mappings) {
if (m.sync !== "verbatim" && m.sync !== "verbatimDir") continue
const dir = m.core.endsWith("/") ? m.core : `${m.core}/`
if (m.sync === "verbatimDir") {
for (const f of listTextFiles(path.join(ROOT, dir))) byteLocked.add(`${dir}${f}`)
} else {
byteLocked.add(m.core)
}
}
}
const hits: string[] = []
const deferred: string[] = []
for (const rel of files) {
if (EXEMPT.has(rel)) continue
const lines = fs.readFileSync(path.join(ROOT, rel), "utf8").split("\n")
lines.forEach((line, i) => {
for (const p of P1_PATTERNS) {
if (!p.re.test(line)) continue
if (p.name === "org-owner-legacy" && HISTORICAL_NS_RE.test(line)) continue
const entry = `${rel}:${i + 1} [${p.name}]`
if (byteLocked.has(rel))
deferred.push(`${entry} (byte-locked verbatim mirror — delink with dogfood side, Inc 6b)`)
else hits.push(entry)
}
})
}
if (hits.length > 0) {
console.error(`check-core-p1: ${hits.length} P1 residual hit(s) in core/:`)
for (const h of hits) console.error(` ${h}`)
process.exit(1)
}
console.log(
`check-core-p1: OK — ${files.length} text files scanned, 0 P1 hits` +
(deferred.length > 0 ? `; ${deferred.length} hit(s) in byte-locked verbatim mirrors deferred to Inc 6b` : "") +
` (id-aliases.json exempt)`,
)
if (deferred.length > 0) for (const d of deferred) console.log(` deferred: ${d}`)
+107
View File
@@ -0,0 +1,107 @@
#!/usr/bin/env bun
import fs from "node:fs"
import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..")
const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json")
const CHECK = process.argv.includes("--check")
const REF_RE = /\B#(\d{3,5})\b/g
const PLACEHOLDER = "org-internal"
interface Mapping {
core: string
dogfood: string | null
sync: string
}
function fail(message: string): never {
console.error(`delink-core: ${message}`)
process.exit(1)
}
if (!fs.existsSync(MANIFEST_PATH)) fail(`manifest not found: ${MANIFEST_PATH}`)
let mappings: Mapping[]
try {
mappings = (JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf8")) as { mappings: Mapping[] }).mappings
} catch (e) {
fail(`manifest is not valid JSON: ${(e as Error).message}`)
}
function listTextFiles(absDir: string, base = ""): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(absDir, { withFileTypes: true })) {
const rel = base ? `${base}/${entry.name}` : entry.name
if (entry.isDirectory()) out.push(...listTextFiles(path.join(absDir, entry.name), rel))
else if (/\.(md|yaml|json)$/.test(entry.name)) out.push(rel)
}
return out
}
const byteLocked = new Set<string>()
for (const m of mappings) {
if (m.sync !== "verbatim" && m.sync !== "verbatimDir") continue
if (m.sync === "verbatimDir") {
const dir = m.core.endsWith("/") ? m.core : `${m.core}/`
for (const f of listTextFiles(path.join(ROOT, dir))) byteLocked.add(`${dir}${f}`)
} else if (/\.(md|yaml|json)$/.test(m.core)) {
byteLocked.add(m.core)
}
}
function transformContent(content: string): { next: string; count: number } {
let count = 0
const next = content.replace(REF_RE, (match, _digits: string, offset: number, whole: string) => {
const before = whole.slice(Math.max(0, offset - 14), offset)
if (before.endsWith(`[${PLACEHOLDER} `)) return match
count++
return `[${PLACEHOLDER} #${_digits}]`
})
return { next, count }
}
export function transformContentForTest(content: string): { next: string; count: number } {
return transformContent(content)
}
const files = listTextFiles(path.join(ROOT, "core"))
const perFile: { file: string; count: number }[] = []
const deferredLocked: { file: string; count: number }[] = []
let total = 0
let replacedTotal = 0
for (const rel of files) {
const fullRel = `core/${rel}`
const content = fs.readFileSync(path.join(ROOT, "core", rel), "utf8")
const { next, count } = transformContent(content)
if (count === 0) continue
if (byteLocked.has(fullRel)) {
deferredLocked.push({ file: fullRel, count })
total += count
continue
}
perFile.push({ file: fullRel, count })
total += count
if (!CHECK) {
fs.writeFileSync(path.join(ROOT, "core", rel), next)
replacedTotal += count
}
}
if (CHECK) {
if (perFile.length > 0) {
console.error(`delink-core: ${perFile.length} file(s) still carry replaceable refs:`)
for (const p of perFile) console.error(` ${p.file}: ${p.count}`)
process.exit(1)
}
const lockedRefs = deferredLocked.reduce((a, b) => a + b.count, 0)
console.log(
`delink-core: check ok — 0 replaceable refs; ${deferredLocked.length} byte-locked verbatim mirror(s) carrying ${lockedRefs} refs deferred to dogfood-side delink (Inc 6b)`,
)
process.exit(0)
}
console.log(`delink-core: replaced ${replacedTotal} refs across ${perFile.length} file(s)`)
const top = [...perFile, ...deferredLocked].sort((a, b) => b.count - a.count).slice(0, 10)
for (const p of top) console.log(` ${p.file}: ${p.count}`)
process.exit(0)