Immutable. This exact content is served forever at /api/v1/blob/6972328dbebdba44.
# Skill3 — agent briefing
Java 25 CLI that **relearns a technical skill** for an AI agent: it discovers
documentation, scores it for authority and freshness against a target model's knowledge
cutoff, synthesizes an Agent Skills `SKILL.md` with an LLM, and vets both the input corpus
and the output skill with NVIDIA SkillSpector.
## The two invariants everything else serves
1. **A skill is a post-cutoff delta, not a primer.** The target model already knows the
topic up to its cutoff; the pipeline gathers only what changed *after* it. Re-explaining
known fundamentals wastes the whole mechanism.
2. **Discovery is topic-agnostic.** The model plans the searches. There is no per-topic
logic anywhere, and adding some — a hardcoded query suffix, a per-skill branch — is the
most common way to break this project without failing a test.
## Where things are
| I need… | Read |
|---|---|
| What it does, flag by flag | [`docs/USAGE.md`](docs/USAGE.md) |
| Install, keys, build | [`docs/INSTALL.md`](docs/INSTALL.md) |
| How it is structured, and why | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) |
| The full behavioural spec | [`docs/SPEC.md`](docs/SPEC.md) |
| Build gates, releases, guardrails | [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) |
| Generated structure diagrams | [`docs/diagrams/`](docs/diagrams/) |
| Roadmap | [`docs/PLAN.md`](docs/PLAN.md) |
## Working on it
```bash
./gradlew build # compile + test + Error Prone, PMD, SpotBugs, ArchUnit, JaCoCo gate
./gradlew test # tests only
./gradlew diagrams # regenerate docs/diagrams/*.svg from the source
./gradlew run --args="learn --help"
```
The build runs on a Gradle-provisioned JDK 25 toolchain, so it does not depend on
`JAVA_HOME`. Coverage is gated at 75% instruction / 65% branch.
## Things that will bite you
- **Never hand-edit between `<!-- VIBETAGS-START -->` and `<!-- VIBETAGS-END -->`** in this
file, `llms.txt` or `llms-full.txt`. Every compile rewrites that region from the `@AI*`
annotations in the Java source. Text outside the markers — including everything above —
survives. To change a guardrail, change the annotation.
- **The guardrails below are the safety tier only.** Per-element detail lives in
[`.claude/rules/`](.claude/rules/) and loads when you open a matching source file.
- **Layering is enforced, not suggested.** An ArchUnit test asserts that `model` depends on
nothing internal, that only `Skill3App` touches `cli`, and that the sub-packages stay
acyclic. A convenient import in `model` fails the build.
- **Untrusted data has a defined path.** Scraped pages and `--input-file` content are
secret-redacted and scanned *before* synthesis, fenced as DATA in the prompt, and the
output is scanned again. Do not add a shortcut that reaches the model earlier.
- **Absence of findings is never asserted.** When SkillSpector is unavailable the scans are
skipped and nothing is gated — "not scanned" must never be reported as "clean".
## Generated guardrails
Everything below is regenerated from source annotations on every compile.
<!-- VIBETAGS-START -->
<!-- # Generated by VibeTags | https://github.com/PIsberg/vibetags -->
<project_guardrails>
<pii_guardrails>
<element path="se.deversity.skill3.llm.LocalLlmClient.apiKey">
<reason>LLM provider API key — never log, echo, or include in errors/fixtures</reason>
</element>
<element path="se.deversity.skill3.pipeline.BraveSearchClient.apiKey">
<reason>Brave Search subscription token — never log, echo, or include in errors/fixtures</reason>
</element>
</pii_guardrails>
<rule>
Never include runtime values of elements listed in <pii_guardrails> in logs, console output, external API calls, test fixtures, mock data, or code suggestions. Treat their values as strictly confidential.
</rule>
<core_elements>
<element path="se.deversity.skill3.llm.SkillMdPostProcessor">
<sensitivity>High</sensitivity>
<note>Deterministically guarantees SKILL.md spec compliance; model output is never trusted. Changes risk emitting invalid frontmatter — keep the parsing and frontmatter synthesis covered by SkillMdPostProcessorTest.</note>
</element>
<element path="se.deversity.skill3.llm.Verifier">
<sensitivity>High</sensitivity>
<note>Accuracy gate that re-grounds claims against the sources. Only worthwhile with a capable model — a weak model rewrites rather than grounds. Keep the prompt strict about supported-claims-only and announced-vs-shipped.</note>
</element>
</core_elements>
<rule>Elements listed in <core_elements> are well-tested core components. Make changes with extreme caution and verify comprehensive test coverage before proposing modifications.</rule>
<security_elements>
<element path="se.deversity.skill3.llm.AnthropicChatModel">
<aspect>Anthropic API credential handling and hosted-provider network egress</aspect>
</element>
<element path="se.deversity.skill3.llm.LlmProviderFactory">
<aspect>LLM provider credential resolution and model selection</aspect>
</element>
<element path="se.deversity.skill3.llm.LocalLlmClient">
<aspect>outbound LLM-provider credential (Bearer token) handling</aspect>
</element>
<element path="se.deversity.skill3.llm.NameSanitizer">
<aspect>output sanitization: reserved-word stripping must never be weakened</aspect>
</element>
<element path="se.deversity.skill3.pipeline.BraveSearchClient">
<aspect>external-API credential handling and the only network egress with a secret token</aspect>
</element>
<element path="se.deversity.skill3.pipeline.DiscoveryProvider">
<aspect>forwards the Brave subscription token to the search client; must not log it</aspect>
</element>
<element path="se.deversity.skill3.pipeline.HttpPageFetcher">
<aspect>outbound page fetch egress for partly-untrusted URLs; SSRF guard must not be weakened</aspect>
</element>
</security_elements>
<rule>Elements listed in <security_elements> are security-critical. Never weaken their security properties. Every proposed change must be explicitly reviewed for security impact.</rule>
<scoped_rules>
<note>Detailed per-element guardrails for the elements below live in scoped rule files that load automatically when the matching source file is opened. Consult the referenced file before modifying an element.</note>
<element path="se.deversity.skill3.llm.AnthropicChatModel" rules=".claude/rules/se-deversity-skill3-llm-AnthropicChatModel.md"/>
<element path="se.deversity.skill3.llm.ChatModel" rules=".claude/rules/se-deversity-skill3-llm-ChatModel.md"/>
<element path="se.deversity.skill3.llm.LlmProviderFactory" rules=".claude/rules/se-deversity-skill3-llm-LlmProviderFactory.md"/>
<element path="se.deversity.skill3.llm.LocalLlmClient" rules=".claude/rules/se-deversity-skill3-llm-LocalLlmClient.md"/>
<element path="se.deversity.skill3.llm.NameSanitizer" rules=".claude/rules/se-deversity-skill3-llm-NameSanitizer.md"/>
<element path="se.deversity.skill3.llm.SkillMdPostProcessor" rules=".claude/rules/se-deversity-skill3-llm-SkillMdPostProcessor.md"/>
<element path="se.deversity.skill3.llm.Verifier" rules=".claude/rules/se-deversity-skill3-llm-Verifier.md"/>
<element path="se.deversity.skill3.model.ContextBundle" rules=".claude/rules/se-deversity-skill3-model-ContextBundle.md"/>
<element path="se.deversity.skill3.model.RunManifest" rules=".claude/rules/se-deversity-skill3-model-RunManifest.md"/>
<element path="se.deversity.skill3.model.Source" rules=".claude/rules/se-deversity-skill3-model-Source.md"/>
<element path="se.deversity.skill3.pipeline.BraveSearchClient" rules=".claude/rules/se-deversity-skill3-pipeline-BraveSearchClient.md"/>
<element path="se.deversity.skill3.pipeline.CutoffResolver" rules=".claude/rules/se-deversity-skill3-pipeline-CutoffResolver.md"/>
<element path="se.deversity.skill3.pipeline.DiscoveryProvider" rules=".claude/rules/se-deversity-skill3-pipeline-DiscoveryProvider.md"/>
<element path="se.deversity.skill3.pipeline.FileCorpus" rules=".claude/rules/se-deversity-skill3-pipeline-FileCorpus.md"/>
<element path="se.deversity.skill3.pipeline.HttpPageFetcher" rules=".claude/rules/se-deversity-skill3-pipeline-HttpPageFetcher.md"/>
<element path="se.deversity.skill3.pipeline.PageFetcher" rules=".claude/rules/se-deversity-skill3-pipeline-PageFetcher.md"/>
<element path="se.deversity.skill3.pipeline.QueryPlanner" rules=".claude/rules/se-deversity-skill3-pipeline-QueryPlanner.md"/>
<element path="se.deversity.skill3.pipeline.RetrievalService" rules=".claude/rules/se-deversity-skill3-pipeline-RetrievalService.md"/>
<element path="se.deversity.skill3.pipeline.SearchClient" rules=".claude/rules/se-deversity-skill3-pipeline-SearchClient.md"/>
<element path="se.deversity.skill3.skillspector.InputVetter" rules=".claude/rules/se-deversity-skill3-skillspector-InputVetter.md"/>
</scoped_rules>
<rule>When you work on any element listed in <scoped_rules>, open its referenced rule file and apply the guardrails there. The rule files are the authoritative source for those elements.</rule>
</project_guardrails>
<!-- VIBETAGS-END -->