← Public packages
@hypercubed/aksk
AKSK setup planner for coding agents: tailored install plans, live peer-tool versions, managed templates, paste-in validators.
src/validate-paste.ts
68 lines · 2.8 KB · TypeScriptexport type PasteKind = 'agents-md' | 'skill' | 'sessions-gitignore'
export interface ValidateInput {
/** What kind of content is being checked. */
kind: PasteKind
/** The pasted file content to validate. */
content: string
}
export interface Finding {
severity: 'error' | 'warning'
message: string
}
/**
* Validate pasted AKSK file content without repo access.
* Use when a user pastes their AGENTS.md, SKILL.md, or .gitignore into chat and wants to know whether the AKSK wiring is intact. Read-only: analyzes text, changes nothing.
*
* @param input - Kind plus the pasted content
* @returns ok flag plus findings (errors fail, warnings advise)
*
* @example
* import validatePaste from 'kody:@hypercubed/aksk/validate-paste'
*
* const r = await validatePaste({ kind: 'agents-md', content: pastedText })
*/
export default async function validatePaste(input: ValidateInput): Promise<{
kind: PasteKind
ok: boolean
findings: Finding[]
}> {
const { kind, content } = input
const text = content ?? ''
const findings: Finding[] = []
if (kind === 'agents-md') {
if (!text.includes('AKSK:ROUTING')) {
findings.push({ severity: 'error', message: 'Missing AKSK:ROUTING marker block — agents cannot discover .agents/ and openwiki/. Attach with attach_section.mjs.' })
}
if (!text.includes('AKSK:LIFECYCLE')) {
findings.push({ severity: 'warning', message: 'Missing AKSK:LIFECYCLE block — the closeout → distill → prune mandate is not attached.' })
}
if (!text.includes('OPENWIKI:START')) {
findings.push({ severity: 'warning', message: 'Missing OPENWIKI:START/END block — run openwiki init or attach the OpenWiki section.' })
}
if (/20\d\d/.test(text) && text.length > 20000) {
findings.push({ severity: 'warning', message: 'File is large (>20k chars) — durable guidance may be bloated with session history. See docs-lint.' })
}
} else if (kind === 'skill') {
if (!/^---\s*\nname:\s*\S+/m.test(text)) {
findings.push({ severity: 'error', message: 'Missing SKILL.md frontmatter `name:` field.' })
}
if (!/^description:\s*\S+/m.test(text)) {
findings.push({ severity: 'error', message: 'Missing SKILL.md frontmatter `description:` field.' })
}
} else if (kind === 'sessions-gitignore') {
if (!text.split('\n').some((l) => l.trim() === 'sessions/*')) {
findings.push({ severity: 'error', message: 'Missing `sessions/*` rule — task bundles would be committed as durable knowledge.' })
}
if (!text.includes('!sessions/README.md')) {
findings.push({ severity: 'warning', message: 'Missing `!sessions/README.md` exception — the directory readme would be ignored too.' })
}
} else {
throw new Error(`Unknown kind '${String(kind)}'. Known: agents-md, skill, sessions-gitignore.`)
}
return { kind, ok: !findings.some((f) => f.severity === 'error'), findings }
}