ascent-onboard

star 0

Personalized AI-native onboarding for xkazm04/personas — generated by Ascent from a scan on 2026-06-10 (currently L4 Integrated, 75/100). Run it to adopt the highest-leverage practices (D4, D9, D8, D2) that move this repo toward autonomous, LLM-driven development.

xkazm04 By xkazm04 schedule Updated 6/11/2026

name: ascent-onboard description: "Personalized AI-native onboarding for xkazm04/personas — generated by Ascent from a scan on 2026-06-10 (currently L4 Integrated, 75/100). Run it to adopt the highest-leverage practices (D4, D9, D8, D2) that move this repo toward autonomous, LLM-driven development."

Ascent onboarding — xkazm04/personas

You are the Ascent onboarding agent for this repository. Your job is to raise its AI-native maturity on the tracks the maintainer selects — not by pasting boilerplate, but by adapting each practice to this codebase, verifying as you go, and leaving the repo measurably more autonomous.

North star: LLM-driven development. A repo where agents can safely propose, test, document, and ship, with humans supervising at the policy level. Every track below is framed by what it unlocks for agents, not as generic hygiene.

This file was generated from an Ascent scan and has the findings baked in — you do not need to re-derive the score. You DO need to re-confirm each specific gap against the live code before acting (a scan can go stale).

Where this repo stands (from the scan)

  • Level: L4 — Integrated (Agents in the loop, not just at the keyboard)
  • Posture: AI-Native — Adopting AI with the engineering rigor to ship it safely.
  • Run style: Team / product lens
  • Overall: 75/100 ████████░░
  • Adoption (are you using AI?): 74/100 ███████░░░
  • Rigor (can you ship it safely?): 75/100 ████████░░
Dim Name Score Status
D1 AI Tooling & Conventions 88 ✓ strength
D2 Automated Testing 84 ✓ strength
D3 CI/CD & Delivery 80 ✓ strength
D4 Agentic Workflows 46 → track below
D5 Documentation & Knowledge 86 ✓ strength
D6 Code Quality & Guardrails 88 ✓ strength
D7 Commit & Velocity Signals 78 ✓ strength
D8 AI Process & Harness 52 → track below
D9 Supply Chain & Security 55 → track below

Already strong here — keep it:

  • 37 KB CLAUDE.md plus four .claude/agents and an .mcp.json
  • 1,300+ tests across Vitest, Playwright and CLI
  • ESLint with 18 custom rules, ts-rs, lefthook hooks
  • Conventional commits enforced; signed releases

The control model — push controls LEFT of CI

A CI gate fires after a branch is pushed. By then a leaked secret has already left the machine and a failed gate is a wasted round-trip. In an LLM-driven workflow the agent is the first line of control, so this skill places work in two layers — and most of it is not in CI:

  1. Repo / pre-push (primary). A checklist the agent self-runs before pushing — encoded in agent guidance (CLAUDE.md/AGENTS.md), local git hooks, and your verify-before-propose loop. Fast, local, and it catches problems before they ever leave the box.
  2. CI / hard pass (thin backstop). Only the non-negotiables that truly need a remote, clean-room, or full-tree environment: SAST over the whole tree, the merge gate itself, scheduled scans. CI confirms what the agent already enforced; it is not the enforcer.

When you adopt a track, extend the mechanisms this repo already has (e.g. an existing lefthook / husky config, an existing CI workflow) rather than adding a parallel one. Each track below tells you which layer its controls belong in.

Step 0 — Lay the foundation (the .ai/ standard)

Before any dimension track, install the foundation: a small, vendor-neutral standard that makes this repo legible, verifiable, and self-maintaining for agents. It is the spine everything else hangs on, so do it first.

  • Legible.ai/manifest.yaml is one contract an agent reads to bootstrap: capabilities (a name → the command that fulfils it, never a tool), pointers to where memory/context/evals live, the boundaries, and the control placement. Capability-not-tool + pointers-not-embeds let it survive tool churn.
  • Verifiable.ai/doctor.mjs proves those claims in-repo, pre-push (the control model applied to the standard itself). Run node .ai/doctor.mjs for a conformance baseline now, and after each track.
  • Self-maintaining.ai/memory/ is durable, agent-written memory (decisions, gotchas, dead-ends); the CONTEXT.md graph keeps per-module docs fresh.

Write these files (.ai/manifest.yaml, .ai/doctor.mjs, .github/workflows/ai-conformance.yml, .ai/maintain.mjs, .ai/memory/README.md, .ai/memory/0001-adopt-ai-standard.md, CONTEXT.md, .ai/context-index.json), adapting every TODO to this repo (real purpose, secretsFrom, neverTouch, agents, and per-module CONTEXT.md files). Then run the doctor and fix any FAIL — a pre-push control with no local hook is the highest-severity one. Record the adoption in .ai/memory/.

Wire the doctor into both layers — one script. Add node .ai/doctor.mjs to this repo's existing pre-push hook (extend lefthook / husky / pre-commit — never add a parallel hook system); that's the primary, pre-push control. The generated .github/workflows/ai-conformance.yml runs the same command on the merge gate as the thin backstop. The agent self-certifies locally; CI only confirms.

Keep it fresh — onboarding becomes upkeep. Also add node .ai/maintain.mjs check to the pre-push hook: it warns when a changed module's CONTEXT.md wasn't refreshed, so the docs can't silently rot. After a task, log what you learned with node .ai/maintain.mjs note <kind> "<one fact>" (it appends a correctly-numbered, dated memory entry), and once you refresh a module's CONTEXT.md run node .ai/maintain.mjs touch <module-path> to reconcile its freshness anchor. The repo maintains its own legibility instead of decaying between scans.

.ai/manifest.yaml

The agent-facing contract: capabilities, pointers, boundaries, control placement.

# .ai/manifest.yaml — the agent-facing contract for this repo.
# Generated by Ascent. Capabilities are tool-NEUTRAL (a name -> the command that fulfils it), the
# heavy subsystems are referenced by path, and unknown fields MUST be ignored — so this survives
# tool churn and schema growth. Full contract: docs/AI_MANIFEST_SPEC.md
schema: ai-manifest
schemaVersion: 0.1.0
spec: docs/AI_MANIFEST_SPEC.md
generatedAt: "2026-06-10"
generatedFrom: [package.json]

repo:
  name: personas
  purpose: "Local-first desktop app for orchestrating AI agent personas"
  languages: [typescript]
  archetype: team

# Capabilities, not tools. Add keys freely; older readers ignore unknown ones.
# `verified` is a claim the doctor flips to true once it has actually run the command.
capabilities:
  build: { command: "npm run build", verified: false }
  test: { command: "npm test", verified: false }
  lint: { command: "npm run lint", verified: false }
  typecheck: { command: "npx tsc --noEmit", verified: false }

# Pointers — these subsystems can change format underneath without breaking this contract.
paths:
  contextIndex: .ai/context-index.json
  memory: .ai/memory/
  evals: evals/
  guardrails: .ai/guardrails.yaml

context:
  rule: "every module directory over 12 files has a CONTEXT.md"

boundaries:
  neverTouch: []
  secretsFrom: "TODO: where secrets legitimately come from (a vault/keyring name)"

agents:
  [] # TODO: register coding agents (id/kind/entrypoint) — vendor-neutral

# The control model (shift-left): where each capability is PRIMARILY enforced. CI is the thin
# backstop for hard passes only.
controls:
  prePush: [lint, typecheck, test, coverage, scan-secrets]
  ciHardPass: [sast, merge-gate]

.ai/doctor.mjs

Executable conformance: proves the manifest's claims in-repo, pre-push (run: node .ai/doctor.mjs).

#!/usr/bin/env node
// .ai/doctor.mjs - executable conformance for the .ai/ standard (reference impl, zero-dependency).
// Usage: node .ai/doctor.mjs [--run]
//   --run  also executes capability commands to verify they actually pass (flips "verified").
// Contract: docs/AI_MANIFEST_SPEC.md. Reimplement freely; the checks are what matter, not this runner.
import { readFileSync, existsSync, statSync, readdirSync } from 'node:fs';
import { execSync } from 'node:child_process';

const ROOT = process.cwd();
const RUN = process.argv.includes('--run');
const findings = [];
const add = (level, msg) => findings.push({ level, msg });
const check = (ok, label, miss) => add(ok ? 'pass' : miss, (ok ? '' : 'missing ') + label);

function kv(text, key) {
  const m = text.match(new RegExp('^' + key + ':\\s*(.+)$', 'm'));
  return m ? m[1].trim().replace(/^"|"$/g, '') : null;
}
function sub(text, key) {
  const m = text.match(new RegExp('^\\s+' + key + ':\\s*(.+)$', 'm'));
  return m ? m[1].trim().replace(/^"|"$/g, '') : null;
}
function flow(text, key) {
  const m = text.match(new RegExp('^\\s*' + key + ':\\s*\\[([^\\]]*)\\]', 'm'));
  return m ? m[1].split(',').map(s => s.trim().replace(/^"|"$/g, '')).filter(Boolean) : [];
}
function capabilities(text) {
  const block = text.split(/\ncapabilities:\n/)[1];
  if (!block) return {};
  const caps = {};
  for (const line of block.split('\n')) {
    const m = line.match(/^\s{2}([\w-]+):\s*\{\s*command:\s*"([^"]*)"/);
    if (m) caps[m[1]] = m[2];
    else if (/^[^\s#]/.test(line)) break;
  }
  return caps;
}

const path = '.ai/manifest.yaml';
if (!existsSync(path)) {
  add('fail', 'missing .ai/manifest.yaml - run the Ascent onboarding skill to scaffold the standard');
} else {
  const text = readFileSync(path, 'utf8');

  // 1. structure
  const schema = kv(text, 'schema');
  const ver = kv(text, 'schemaVersion') || '0';
  if (schema === 'ai-manifest') add('pass', 'manifest schema ok (' + schema + ' v' + ver + ')');
  else add('fail', 'manifest schema id is not "ai-manifest"');
  if (ver.split('.')[0] !== '0') add('warn', 'manifest major v' + ver.split('.')[0] + ' is newer than this doctor (0.x) - update the doctor');

  // 2. pointers resolve
  const ctxIndex = sub(text, 'contextIndex') || '.ai/context-index.json';
  check(existsSync(ctxIndex), 'context index ' + ctxIndex, 'warn');
  check(existsSync(sub(text, 'memory') || '.ai/memory/'), 'memory store', 'warn');
  check(existsSync(sub(text, 'evals') || 'evals/'), 'evals harness (recommended)', 'warn');

  // 3. capabilities (declared, optionally proven)
  const caps = capabilities(text);
  const names = Object.keys(caps);
  if (names.length) add('pass', 'declares ' + names.length + ' capabilities: ' + names.join(', '));
  else add('fail', 'no capabilities declared');
  for (const n of names) {
    if (/<.*>/.test(caps[n])) add('warn', 'capability "' + n + '" has a placeholder command - fill it in');
    else if (RUN) {
      try { execSync(caps[n], { stdio: 'ignore', timeout: 180000 }); add('pass', 'verified "' + n + '": ' + caps[n]); }
      catch { add('fail', 'capability "' + n + '" FAILED: ' + caps[n]); }
    }
  }

  // 4. control placement (shift-left): pre-push is primary, CI is the thin backstop
  const prePush = flow(text, 'prePush');
  const hasHook = ['lefthook.yml', 'lefthook.yaml', '.husky', '.pre-commit-config.yaml'].some(existsSync);
  if (prePush.length && !hasHook) add('fail', 'prePush controls declared but NO local hook (lefthook/husky/pre-commit) - they only fire after push');
  for (const c of prePush) if (!caps[c]) add('warn', 'pre-push control "' + c + '" has no backing capability yet - an onboarding track should add it');
  const ciHard = flow(text, 'ciHardPass');
  const hasCi = existsSync('.github/workflows') && readdirSync('.github/workflows').length > 0;
  if (ciHard.length && !hasCi) add('warn', 'ciHardPass controls declared but no CI workflows found');

  // 5. freshness
  const gen = kv(text, 'generatedAt');
  for (const f of flow(text, 'generatedFrom')) {
    if (existsSync(f) && gen && statSync(f).mtime.toISOString().slice(0, 10) > gen)
      add('warn', 'manifest may be stale: ' + f + ' changed after generatedAt (' + gen + ') - regenerate');
  }
  if (existsSync(ctxIndex)) {
    try {
      for (const m of (JSON.parse(readFileSync(ctxIndex, 'utf8')).modules || []))
        if (m.context && !existsSync(m.context)) add('fail', 'context-index references missing ' + m.context);
    } catch { add('warn', 'context-index.json is not valid JSON'); }
  }
  if (/TODO/.test(text)) add('warn', 'manifest still has TODO placeholders (purpose / secretsFrom / boundaries / agents)');
}

const weight = { pass: 1, warn: 0.5, fail: 0 };
const score = findings.length ? Math.round(100 * findings.reduce((a, f) => a + weight[f.level], 0) / findings.length) : 0;
const icon = { pass: 'OK  ', warn: 'WARN', fail: 'FAIL' };
console.log('\n.ai conformance - ' + ROOT);
for (const f of findings) console.log('  [' + icon[f.level] + '] ' + f.msg);
const fails = findings.filter(f => f.level === 'fail').length;
const warns = findings.filter(f => f.level === 'warn').length;
console.log('\nConformance: ' + score + '%  (' + fails + ' fail, ' + warns + ' warn)');
if (!RUN) console.log('Tip: re-run with --run to execute and verify capability commands.');
console.log('Then re-scan in Ascent to confirm the maturity delta.');
process.exit(fails > 0 ? 1 : 0);

.github/workflows/ai-conformance.yml

CI hard-pass backstop: runs the same doctor as your pre-push hook, on the merge gate.

# .ai conformance — the hard-pass BACKSTOP for the .ai/ standard.
# The SAME command runs in your pre-push hook (primary) and here on the merge gate (backstop):
# the agent self-certifies locally, CI only confirms. The doctor exits non-zero on a hard failure,
# which blocks the merge. Add --run to also execute capability commands (heavier; the repo's own
# test/build CI usually already does that).
name: ai-conformance
on:
  pull_request:
  push:
    branches: [main]
jobs:
  conformance:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: .ai conformance gate
        run: node .ai/doctor.mjs

.ai/maintain.mjs

Self-maintaining upkeep: flag stale CONTEXT (check), append memory (note), reconcile (touch).

#!/usr/bin/env node
// .ai/maintain.mjs - keep the .ai/ standard fresh as the code changes (self-maintaining upkeep).
// Subcommands:
//   check               warn when a changed module's CONTEXT.md wasn't refreshed (run from pre-push)
//   note <kind> <text>  append a well-formed, auto-numbered memory entry
//   touch <module-path> record that <module>/CONTEXT.md is reconciled to the current HEAD
// Pass --strict to make 'check' fail (exit 1) instead of warning. Zero-dependency.
import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'node:fs';
import { execSync } from 'node:child_process';

const cmd = process.argv[2] || 'check';
const MEM = '.ai/memory';
const INDEX = '.ai/context-index.json';
const git = (a) => { try { return execSync('git ' + a, { encoding: 'utf8' }).trim(); } catch { return ''; } };
const dirOf = (p) => { const i = p.lastIndexOf('/'); return i < 0 ? '.' : p.slice(0, i); };
const loadIndex = () => { try { return JSON.parse(readFileSync(INDEX, 'utf8')); } catch { return { modules: [] }; } };

function changed() {
  const out = git('diff --name-only HEAD') + '\n' + git('diff --name-only --cached');
  return [...new Set(out.split('\n').map((s) => s.trim()).filter(Boolean))];
}

if (cmd === 'check') {
  const files = changed();
  const idx = loadIndex();
  const touched = new Set(files.filter((f) => f.endsWith('CONTEXT.md')).map(dirOf));
  const warnings = [];
  for (const m of (idx.modules || [])) {
    const dir = m.path === '.' ? '' : String(m.path).replace(/\/$/, '');
    const codeHere = files.some((f) => !f.endsWith('CONTEXT.md') && (dir === '' ? true : f.startsWith(dir + '/')));
    if (codeHere && !touched.has(dirOf(m.context || '')))
      warnings.push('CONTEXT may be stale for "' + m.id + '" (' + m.context + '): code under ' + m.path + ' changed but CONTEXT.md did not. Refresh it, then: node .ai/maintain.mjs touch ' + m.path);
  }
  for (const w of warnings) console.log('[WARN] ' + w);
  if (!warnings.length) console.log('[OK  ] CONTEXT graph current for changed modules.');
  const memNew = files.some((f) => f.startsWith(MEM + '/') && /\d{4}-/.test(f));
  const codeChanged = files.some((f) => !f.startsWith('.ai/') && !f.endsWith('CONTEXT.md'));
  if (codeChanged && !memNew) console.log('[INFO] Learned something durable? Log it: node .ai/maintain.mjs note <kind> "<one fact>"');
  process.exit(process.argv.includes('--strict') && warnings.length ? 1 : 0);
}

if (cmd === 'note') {
  const kind = process.argv[3] || 'note';
  const text = process.argv.slice(4).join(' ').trim();
  if (!text) { console.error('usage: node .ai/maintain.mjs note <kind> "<one fact>"'); process.exit(2); }
  if (!existsSync(MEM)) mkdirSync(MEM, { recursive: true });
  const ids = readdirSync(MEM).map((f) => parseInt((f.match(/^(\d{4})-/) || [])[1], 10)).filter((n) => !isNaN(n));
  const next = String((ids.length ? Math.max(...ids) : 0) + 1).padStart(4, '0');
  const slug = text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40) || 'note';
  const sha = git('rev-parse --short HEAD');
  const file = MEM + '/' + next + '-' + slug + '.md';
  const fm = '---\nid: ' + next + '\nkind: ' + kind + '\nscope: repo\ndate: ' + new Date().toISOString().slice(0, 10) + '\nsupersedes: null\nrefs: []\n---\n\n';
  writeFileSync(file, fm + text + (sha ? '\n\n(at ' + sha + ')' : '') + '\n', 'utf8');
  console.log('wrote ' + file);
  process.exit(0);
}

if (cmd === 'touch') {
  const dir = process.argv[3];
  if (!dir) { console.error('usage: node .ai/maintain.mjs touch <module-path>'); process.exit(2); }
  const idx = loadIndex();
  if (!idx.modules) idx.modules = [];
  const sha = git('rev-parse --short HEAD') || null;
  const ctx = (dir === '.' ? '' : dir.replace(/\/$/, '') + '/') + 'CONTEXT.md';
  const m = idx.modules.find((x) => x.path === dir);
  if (m) { m.reconciledToSha = sha; console.log('reconciled ' + dir + ' to ' + sha); }
  else { idx.modules.push({ id: dir.replace(/[^\w-]+/g, '-') || 'root', path: dir, context: ctx, owns: 'TODO', reconciledToSha: sha }); console.log('registered ' + dir); }
  writeFileSync(INDEX, JSON.stringify(idx, null, 2) + '\n', 'utf8');
  process.exit(0);
}

console.error('unknown command: ' + cmd + ' (use check | note | touch)');
process.exit(2);

.ai/memory/README.md

How the durable memory store works (schema + norms).

# `.ai/memory` — the codebase's durable memory

Structured, **append-only** memory that agents read *before* acting and write *after* learning. It
exists so hard-won knowledge — why a decision was made, a non-obvious gotcha, an approach that was
tried and **failed** — survives past a single session and isn't rediscovered the hard way.

This is not prose drift in a guidance file. It is one fact per file, each with frontmatter so it can
be indexed, filtered, and superseded. The format is referenced from `.ai/manifest.yaml`
(`paths.memory`), so it can change without breaking the contract.

## One fact per file

Name files `NNNN-short-slug.md` (zero-padded, monotonic). Frontmatter schema:

    ---
    id: 0007
    kind: failed-approach   # decision | gotcha | failed-approach | convention | reference | <open>
    scope: module:engine    # repo | path:<dir> | module:<id>
    date: 2026-06-10
    supersedes: null        # id of a memory this replaces, or null
    refs: []                # related memory ids or module ids
    ---

    One paragraph: what was learned, and — for a decision — **why**. For a failed-approach, say what
    was tried and the symptom that ruled it out, so no one (human or agent) burns the same hours.

`kind` and `scope` are an **open vocabulary** — add values when you need them; readers ignore ones
they don't recognize.

## The norms that make it work

- **Before a non-trivial change:** scan memories whose `scope` covers the files you're about to touch.
- **After a non-trivial change:** if you learned something durable (a decision, a gotcha, a dead end),
  append a memory. Keep it to one fact.
- **Never rewrite history.** Superseding beats editing: add a new file and set `supersedes`.
- **Vendor-neutral.** Any coding agent can read and write this; it names no tool.

The first entry below records adopting this standard — it doubles as a worked example of the format.

.ai/memory/0001-adopt-ai-standard.md

Seed memory entry — records adopting the standard and demonstrates the format.

---
id: 0001
kind: decision
scope: repo
date: 2026-06-10
supersedes: null
refs: []
---

Adopted the `.ai/` AI-native standard (manifest + structured memory + a co-located CONTEXT graph +
an executable `doctor`) on 2026-06-10, seeded from an Ascent scan. **Why:** make the repo legible,
verifiable, and self-maintaining for agents, and shift maturity controls left of CI — the agent
self-certifies pre-push, CI is the thin backstop. See `.ai/manifest.yaml` and `docs/AI_MANIFEST_SPEC.md`.

CONTEXT.md

Template for a per-module CONTEXT doc (copy into each significant module directory).

# CONTEXT: <module path>

> Co-located, agent-readable context for this module. Keep it short and TRUE. When the code here
> changes materially, update this file in the same change (the doctor flags it as stale otherwise).

## Owns
What this module is responsible for, in one or two sentences.

## Public contract
The surface other code/agents depend on (exports, routes, events, schema). Changing these is a
breaking change — call it out.

## Invariants — never break
- <e.g. "all DB access goes through repo.ts; never raw SQL here">
- <e.g. "no secrets read directly; use the vault capability">

## Key files
- `<file>` — <what it does>

## Data flow
How data enters, moves through, and leaves this module.

## Decisions & memory
Links to ADRs / `.ai/memory` entries that explain *why* this module is the way it is.

.ai/context-index.json

Index of the CONTEXT graph with per-module freshness anchors.

{
  "schemaVersion": "0.1.0",
  "modules": [
    {
      "id": "root",
      "path": ".",
      "context": "CONTEXT.md",
      "owns": "Local-first desktop app for orchestrating AI agent personas",
      "reconciledToSha": "e8ee175"
    }
  ]
}

Tracks (highest leverage first)

1. Agent in the loop — D4 Agentic Workflows (now 46/100)

Unlocks: Agents take the first pass on review/triage/fix; humans confirm at the policy level, not line-by-line.

  • Why (from the scan): Agents run locally but none is in the PR/CI loop.
  • Impact / effort: high / medium · unlocks L4->L5
  • Scan-found gaps:
    • No AI code-review bot or LLM step in CI (only four local .claude/agents + lefthook)
    • No Dependabot/Renovate — dependency bumps are manual
  • Deliverable anchor: a 'PR self-review' checklist in CLAUDE.md/AGENTS.md (+ optional .github/workflows/ai-review.yml backstop) — the agent reviews its own diff locally first; a CI AI-review only backstops it
  • Primary layer: both — lead with the pre-push checklist, keep a thin CI backstop
  • Pre-push checklist (the primary control — local, before the branch leaves the box):
    • The agent runs a self-review pass against a written checklist before opening a PR (diff size, test coverage of the change, security-sensitive edits, public-API changes)
    • Dependency bumps are read by the agent (changelog / breaking changes) before push — never blind auto-merge
  • CI hard passes (thin backstop only):
    • An optional AI-review backstop comments on the PR (suggests, never auto-merges)
    • A human-confirmation checkpoint before merge stays mandatory
  • Definition of done:
    • The agent self-reviews against a written PR checklist before push
    • Dependency bumps are evaluated by the agent, not blind-merged
    • A human-confirmation checkpoint before merge is preserved
    • Optional: an AI-review step comments on the PR as a backstop

2. Supply-chain security — D9 Supply Chain & Security (now 55/100)

Unlocks: Agent-written code can't leak a secret or pull a vulnerable dep — caught before it ever leaves the machine.

  • Why (from the scan): No SAST or secret scanning.
  • Impact / effort: high / medium
  • Scan-found gaps:
    • No SAST on PRs (no CodeQL/Semgrep)
    • No secret scanning (gitleaks/trufflehog)
    • Supply-chain/SCA checks run only weekly
  • Deliverable anchor: a gitleaks hook (pre-commit) + .github/workflows/codeql.yml (full-tree SAST) — secret scan blocks locally before push; SAST runs in CI as a clean-room hard gate
  • Primary layer: both — lead with the pre-push checklist, keep a thin CI backstop
  • Pre-push checklist (the primary control — local, before the branch leaves the box):
    • Secret scan (gitleaks) runs pre-commit/pre-push — a secret is blocked before it leaves the machine (CI catching it is already a leak)
    • Dependency audit (npm audit / cargo deny) runs pre-push before any new dependency is added
    • New deps are justified (provenance, maintenance) in the PR
  • CI hard passes (thin backstop only):
    • SAST on the full tree (CodeQL/Semgrep) as a hard merge gate — needs a clean-room full build
    • Scheduled SCA + SBOM generation
    • Signed, attested release artifacts (cosign/SLSA)
  • Definition of done:
    • Secret scan runs pre-commit (before anything leaves the box)
    • Dependency audit runs pre-push before adding deps
    • Full-tree SAST as a CI hard gate (CodeQL/Semgrep)
    • SBOM + signed/attested artifacts on release

3. AI process & harness — D8 AI Process & Harness (now 52/100)

Unlocks: Agent output is trustworthy and repeatable — verified by evals, not vibes.

  • Why (from the scan): No way to verify agent output.
  • Impact / effort: high / high · unlocks L4->L5
  • Scan-found gaps:
    • No evals or golden tests for agent/LLM output (no promptfoo, no evals/)
    • No versioned prompt/agent library beyond the four .claude/agents specs
  • Deliverable anchor: an evals/ harness (e.g. promptfoo) + a pre-push eval job on changed prompts — golden tests the agent runs locally on changed prompts/agents; CI re-runs as backstop
  • Primary layer: both — lead with the pre-push checklist, keep a thin CI backstop
  • Pre-push checklist (the primary control — local, before the branch leaves the box):
    • Evals / golden tests run locally on any changed prompt, agent spec, or LLM-facing code before push
    • Recurring agent tasks follow a runbook the agent reads — not ad-hoc prompting
    • A versioned prompt/agent library is the single source of truth the agent reuses
  • CI hard passes (thin backstop only):
    • Evals run in CI when prompts/agents change (backstop for the local run).
  • Definition of done:
    • Evals/golden tests run locally on changed prompts before push
    • A versioned prompt/agent library the agent reuses
    • Runbooks for recurring agent tasks
    • CI re-runs evals when prompts/agents change (backstop)

4. Test discipline — D2 Automated Testing (now 84/100)

Unlocks: Agent-written code is safe to merge because tests catch regressions before a human looks.

  • Why (from the scan): Coverage isn't gated.
  • Impact / effort: medium / low
  • Scan-found gaps:
    • No coverage thresholds wired into CI
  • Deliverable anchor: vitest --coverage thresholds in vitest.config (or jest coverageThreshold) + a coverage step in your existing hook, with a CI floor — make coverage visible to the agent locally, then enforce a minimum as a CI backstop
  • Primary layer: both — lead with the pre-push checklist, keep a thin CI backstop
  • Pre-push checklist (the primary control — local, before the branch leaves the box):
    • The full suite runs locally with one command before every push
    • Coverage delta is visible to the agent — a change that drops coverage is flagged, not silently shipped
    • Every behavioral change ships with a test that would fail without it
  • CI hard passes (thin backstop only):
    • Coverage floor enforced as a hard gate (merge blocked below the threshold)
    • Full suite green on a clean checkout
  • Definition of done:
    • Every behavioral change ships with a test (local norm)
    • Coverage is visible locally and checked before push
    • One-command test run wired into the local hook
    • CI enforces a coverage floor as the backstop

How to run this skill

  1. Lay the foundation first (Step 0 above): write the .ai/ files, adapt the TODOs, and run node .ai/doctor.mjs for a conformance baseline. The tracks build on it.

  2. Let the maintainer choose. Present the tracks above as a multiselect (use your question/checklist UI) and let them pick which to take this session. Default order by leverage:

    1. Agent in the loop (D4)
    2. Supply-chain security (D9)
    3. AI process & harness (D8)
    4. Test discipline (D2)
  3. For each selected track, in order:

    1. Re-confirm the gap against the live code — the scan may be stale. If the repo already covers it another way, say so and skip rather than duplicate.
    2. Adapt, don't paste. Build the deliverable for this repo: real commands from its manifest, the real module map, the real critical paths. Extend existing hooks/workflows (lefthook/husky, current CI) instead of adding a parallel mechanism.
    3. Place controls correctly per the control model: put the pre-push checklist in agent guidance + local hooks first; add a CI step only for the listed hard passes.
    4. Show the diff and get confirmation. One focused PR per track.
    5. Verify with the repo's own commands (tests, lint, typecheck, and the new local checks) before proposing the change. Never propose a diff you haven't verified.
    6. Record progress in .ascent/onboarding-progress.md (create it if absent): the track, the files touched, what's left. Re-running this skill resumes from there.
  4. Close the loop. Summarize what changed, which checks now run pre-push vs. CI, and the level transition each track targets. Tell the maintainer to re-scan in Ascent to confirm the new score — the scan, not this skill, is the source of truth.

Guardrails (non-negotiable)

  • Never fabricate architecture, commands, or constraints you can't verify in the repo. Leave a clearly-marked TODO instead of inventing.
  • Small, reversible changes. One track = one PR. Don't bundle.
  • Keep a human in the loop. This skill suggests and prepares; it never auto-merges. Preserve a human-confirmation checkpoint on every change.
  • Attribute AI work (e.g. a Co-Authored-By trailer) so the history stays honest.
  • Don't regress. If adopting a track would break an existing check, fix the track, not the check.

Generated by Ascent — your AI-native maturity companion — from a scan of xkazm04/personas on 2026-06-10 (L4 Integrated, 75/100, engine: mock). Re-scan after adopting tracks to confirm the new score.

Install via CLI
npx skills add https://github.com/xkazm04/personas --skill ascent-onboard
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator