pub(crate) mod install;
pub(crate) struct Skill {
pub(crate) name: &'static str,
pub(crate) content: &'static str,
}
impl Skill {
#[aristo::intent(
"Install paths MUST call resolved_content, never read .content \
directly. The template needs the build-time SDK version; \
writing .content to disk would ship a literal `{{SDK_VERSION}}` \
placeholder to user-installed SKILL.md files. The install \
outcome would look successful but the version pin would be \
garbage — silent staleness on every release.",
verify = "neural",
id = "skill_install_must_use_resolved_content"
)]
pub(crate) fn resolved_content(&self) -> String {
self.content
.replace("{{SDK_VERSION}}", env!("CARGO_PKG_VERSION"))
}
}
#[aristo::intent(
"Skill names in this set are part of the public install surface. \
Renaming or removing one is a breaking change — users on the old \
name have it on disk under that path; agents match by exact name.",
verify = "neural",
id = "bundled_skills_is_stable_set"
)]
pub(crate) fn bundled() -> &'static [Skill] {
BUNDLED
}
const AUTHORING_BODY: &str = concat!(
include_str!("aristo-authoring.md"),
"\n\n---\n\n## Canonical principles (verbatim from PHILOSOPHY.md)\n\n\
The section below is `include_str!`'d at build time from \
`aristo-authoring-philosophy.md` so the bundled skill cannot \
drift from the project's distilled principles. Edit the source \
file, not this section.\n\n",
include_str!("aristo-authoring-philosophy.md"),
);
const AUTHORING: Skill = Skill {
name: "aristo-authoring",
content: AUTHORING_BODY,
};
const NEURAL_VERIFY: Skill = Skill {
name: "aristo-neural-verify",
content: include_str!("aristo-neural-verify.md"),
};
const CRITIQUE: Skill = Skill {
name: "aristo-critique",
content: include_str!("aristo-critique.md"),
};
const BUNDLED: &[Skill] = &[AUTHORING, NEURAL_VERIFY, CRITIQUE];
#[cfg(test)]
mod tests {
use super::*;
fn find(name: &str) -> Option<&'static Skill> {
bundled().iter().find(|s| s.name == name)
}
#[test]
fn authoring_skill_is_bundled() {
assert!(find("aristo-authoring").is_some());
}
#[test]
fn future_skill_names_not_yet_bundled() {
assert!(find("aristo-mine-assertions").is_none()); }
#[test]
fn critique_skill_is_bundled() {
let s = find("aristo-critique").expect("aristo-critique must be bundled");
let body = s.resolved_content();
assert!(
body.contains("aristo critique --submit-findings"),
"skill body must teach the SDK CLI as the single write path"
);
assert!(
body.contains("aristo critique --pop-next"),
"skill body must teach the worker-loop pop pattern"
);
assert!(
body.contains("model=\"sonnet\""),
"skill body must specify the Sonnet model for critique workers \
(Opus is overkill for shallow prose work)"
);
assert!(
body.contains("Bash tools only"),
"skill body must restrict critique workers to Bash only \
(task body is self-contained; no Read needed)"
);
assert!(
body.contains("rephrasing")
&& body.contains("parent-shape")
&& body.contains("vocabulary")
&& body.contains("scope")
&& body.contains("clarity"),
"skill body must enumerate all five v0 finding categories"
);
assert!(
body.contains("strong-suggest") && body.contains("severity"),
"skill body must enumerate the severity scale"
);
assert!(
body.contains("self-contained"),
"skill body must teach that the task body is self-contained \
(no source reads needed)"
);
assert!(
body.contains("aristo session active"),
"skill body's step 0 must check for an active review session \
(slice 27.5 Layer 3 enforcement)"
);
assert!(
body.contains("aristo session start critique-review"),
"skill body's step 5 must open a session before interactive review"
);
assert!(
body.contains("aristo session decide --item"),
"skill body's step 5 must record per-finding decisions via the substrate"
);
assert!(
body.contains("aristo session exit --defer-undecided"),
"skill body must offer defer-undecided as the early-stop path \
so open items go to backlog, not silently dropped"
);
}
#[test]
fn neural_verify_skill_is_bundled() {
let s = find("aristo-neural-verify").expect("aristo-neural-verify must be bundled");
let body = s.resolved_content();
assert!(
body.contains("`.aristo/pending-neural.toml`"),
"skill body must reference the pending-request file the SDK writes"
);
assert!(
body.contains("aristo verify --apply-verdicts"),
"skill body must teach the agent to call the SDK validator after producing proofs"
);
assert!(
body.contains("aristo verify --submit-verdict"),
"skill body must teach the subagent to submit verdicts via the SDK CLI \
(single write path; no direct file writes from agents)"
);
assert!(
body.contains("`Bash` and `Read` tools only"),
"skill body must restrict subagent tools to Bash + Read (no Write)"
);
assert!(
body.contains("ONE-SHOT") || body.contains("one-shot"),
"skill body must teach the one-shot-per-worker pattern \
(context pollution risk if workers loop)"
);
assert!(
body.contains("aristo verify --queue-status"),
"skill body must teach the orchestrator to use --queue-status \
as the non-destructive peek between worker dispatches"
);
assert!(
body.contains("run_in_background"),
"skill body must teach continuous dispatch via Agent(run_in_background=true) \
— waves of N workers waste time waiting on the slowest in each batch"
);
assert!(
body.contains("accepted: sha256:"),
"skill body must teach the subagent how to parse the SDK's accept stdout"
);
assert!(
body.contains("compare with the reported hash"),
"skill body must teach the orchestrator's hash-comparison integrity check"
);
assert!(
body.contains("do NOT inline it as a discovered ground"),
"skill body must encode the strict-on-discovered-assumptions rule"
);
assert!(
body.contains("DO NOT write hash fields"),
"skill body must instruct the agent to omit hash fields (SDK stamps them)"
);
assert!(
body.contains("Cited id discipline"),
"skill body must encode the cited-id-discipline rule (open #2 fix)"
);
assert!(
body.contains("`supports` is NOT a valid variant"),
"skill body must explicitly disallow the `supports` enum variant \
(broke 2/4 of the first submit-flow dogfood run)"
);
assert!(
body.contains("CANNOT cite"),
"skill body must explicitly disallow child-as-prior-step \
(broke verify_bool_true on first dogfood run)"
);
assert!(
body.contains("\"1-200\""),
"skill body must call out the over-broad line-range failure mode \
(broke pending_neural on first dogfood run)"
);
assert!(
body.contains("prior_attempts + 1") || body.contains("prior_attempts}} + 1"),
"skill body must teach the agent to compute attempts as prior_attempts + 1 \
(GAP-9: repair budget accumulates across re-spawns)"
);
assert!(
body.contains("AskUserQuestion") && body.contains("interactive review"),
"skill body must teach the post-apply interactive review flow via AskUserQuestion"
);
assert!(
body.contains("Every suggested annotation gets surfaced as an actionable question"),
"skill body must encode the GSD-style interactive-suggestions rule"
);
assert!(
body.contains("confirmed via a second `AskUserQuestion`"),
"skill body must require two-step confirmation before any source edit \
(no silent source mutation from skill orchestration)"
);
assert!(
body.contains("aristo session active"),
"skill body's step 0 must check for an active review session \
(slice 27.5 Layer 3 enforcement)"
);
assert!(
body.contains("aristo session start proof-review"),
"skill body's step 7 must open a session before interactive review"
);
assert!(
body.contains("aristo session decide --item"),
"skill body's step 7 must record per-proof decisions via the substrate"
);
assert!(
body.contains("aristo session exit --defer-undecided"),
"skill body must offer defer-undecided as the early-stop path \
so un-decided proofs go to backlog, not silently dropped"
);
}
#[test]
fn bundled_skill_names_are_unique() {
let mut names: Vec<_> = bundled().iter().map(|s| s.name).collect();
names.sort_unstable();
let len_before = names.len();
names.dedup();
assert_eq!(
names.len(),
len_before,
"duplicate skill name in BUNDLED — would clobber on install"
);
}
#[test]
fn authoring_skill_references_intent_stmt_not_intent_bang() {
let s = find("aristo-authoring").unwrap();
assert!(
s.content.contains("intent_stmt!"),
"authoring skill must teach intent_stmt! (the actual macro name)"
);
assert!(
!s.content.contains("aristo::intent!("),
"authoring skill must NOT teach intent!() — that name doesn't exist (E0428)"
);
}
#[test]
fn authoring_skill_references_aristos_namespace_warning() {
let s = find("aristo-authoring").unwrap();
assert!(
s.content.contains("aristos:"),
"skill must warn agents not to write the aristos: prefix"
);
assert!(
s.content.contains("aret_"),
"skill must warn agents not to write the aret_ prefix"
);
}
#[test]
fn authoring_skill_embeds_philosophy_principles_verbatim() {
let s = find("aristo-authoring").unwrap();
for principle in [
"P-SPEC-STYLE",
"P-CHECK-TYPE-SYSTEM-FIRST",
"P-NO-DOUBLE-INTENT",
"P-INVARIANT-AT-LOAD-BEARING-SITE",
"P-INVARIANT-NOT-IMPL",
"P-WHY-AS-INVARIANT",
"P-NAME-THE-REFACTOR-TRAP",
"P-AGENT-PROOFING",
"P-VERIFY-MATCHES-SHAPE",
] {
assert!(
s.content.contains(principle),
"bundled skill is missing `{principle}` — did the \
PHILOSOPHY.md include path break?"
);
}
assert!(
s.content.contains("`include_str!`'d at build time from"),
"missing include-marker phrase — skill may not be \
auto-wiring from PHILOSOPHY.md"
);
}
#[test]
fn authoring_skill_has_yaml_frontmatter() {
let s = find("aristo-authoring").unwrap();
let mut lines = s.content.lines();
assert_eq!(
lines.next(),
Some("---"),
"skill must start with frontmatter"
);
assert!(
s.content.contains("name: aristo-authoring"),
"frontmatter must include the skill name"
);
}
}