Install
$ agentstack add skill-chrisgagne-grounded-forge-answer-from-corpus Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Answer from library
Source-grounded answer protocol for any substantive question the library may cover. The library is the assembled body of references and distillations the skill is searching; the matrix is the architectural pattern (reference × task projection) that pre-shapes how the library is organised. Invoke this skill to operationalise the bundled CLAUDE.md's grounding directive: CLAUDE.md sets the principle (search before reasoning from priors; cite or admit guessing), this protocol runs it as executable steps: shape-classification, traceability, citation density, library breadth.
Procedure
Path convention. Every path in this skill is written from the source-repo perspective: corpus.commons/demo/{file}. When /answer-from-corpus runs inside a deployed application (any subdir of corpus.commons/demo/apps/, e.g., apps/decision/, apps/stakeholder/, apps/software-business/), the corpus.commons/demo/ prefix is stripped one-to-one: reference-index.json resolves as ./reference-index.json, distillations/{task}/task-index.json as ./distillations/{task}/task-index.json, references/{slug}.md as ./references/{slug}.md, and so on. The rest of every path is unchanged. The deployed-app CLAUDE.md documents the bare-path layout from the app's own perspective; this skill's corpus.commons/demo/ literals are the source-repo equivalents. Translate at read time; do not paginate or grep for files the literal path-string fails to find.
--corpus {slug} flag. When the operator passes --corpus my-corpus in the invocation (e.g., /answer-from-corpus --corpus demo What is a definition of done?), the skill targets corpus.commons/{slug}/ or corpus.local/{slug}/ instead of the default. Use the flag in two cases: (a) the source repo carries more than one commons or local corpus and the active one is ambiguous; (b) the operator wants to route a query against a specific named corpus regardless of CWD. Default resolution: if the CWD is inside a deployed app, use the bundled corpus (bare paths); if the CWD is inside the source repo and exactly one commons corpus exists, use it; if more than one corpus exists and no flag is passed, refuse with a one-line list of available corpora and ask. The trace footer names the corpus resolved-against: corpus: demo or corpus: my-corpus.
Step 0: Classify the query shape
Before any reads, classify the question:
- Named lookup. The user names a specific framework, author, work, or concept ("walk me through the OpenStax Principles of Management chapter structure", "what does TC 25-20 say about the AAR cycle", "tell me about Dekker's Just Culture as treated in the corpus"). Signal: the answer reduces to what does this one source say. → Protocol N.
- Diagnostic. The user describes a situation that needs reference-mediated guidance ("how do I handle a stakeholder conflict", "I need to make a decision under uncertainty"). Signal: there's a task domain in play, and the corpus has distillations for it. → Protocol D.
- Synthesis. The user asks what the corpus says about a broad topic ("what is Agile", "what does the library say about employee motivation"). Signal: the answer benefits from breadth across multiple authors/traditions and the question is not a named lookup or in-task diagnostic. → Protocol S.
When ambiguous, default to the more expansive protocol (S over N, D over N). Never ask the user to disambiguate unless genuinely unclear.
Step 0.5: Lens-applicability check
After classifying the query and before any reads, check whether a lens materially reweights what's salient for this query.
Skip this step for Protocol N. Named lookups answer what does this one source say; a lens would distort, not clarify.
For Protocols D and S:
- Read [
lens-index.json](../../../lens-index.json) unconditionally. The lens index is a small curated runtime artefact (one entry per lens underlenses.{slug}). Each entry carrieskind,spec_path,purpose,reach_for_when, and a structuredsalienceblock (notices_first,recedes,native_vocabularyas a list of phrases) that primes the lens's vocabulary at a glance. Read it the way the task-axis indexes are read: as a map, not a search target. Always read it for Protocols D and S; do not short-circuit on a query that seems lens-neutral, because the detection in step 2 is what reads the entries against the query, and that detection needs the index loaded. The companion operator-inspection view atlenses/LENS-INDEX.mdcarries the same data in prose form; the JSON is the runtime source of truth. - Detect the lens-shaped signal. The deliverable is lens-shaped when it asks for role-specific guidance, a perspective-bound read, an artefact aimed at a named reader-type (CTO, PM, executive, builder), a query asking for a named living person's voice or for their published framings to be applied to the artefact (real-person lens), an AAR/retro write-up where reader-role is load-bearing, a coaching brief, or process/RACI documentation where role-and-circumstance is the unit of analysis. If the query is lens-neutral (a generic synthesis question with no reader-bound output), no lens applies and the rest of the protocol runs unmodified.
- Name the lens(es) the index surfaces and confirm with the operator before proceeding when more than one lens could apply or when the choice changes the deliverable's shape materially. When exactly one lens fits unambiguously, name it in the trace and proceed without asking.
- For most lens-shaped queries, the index entry is sufficient: the
salienceblock carries enough of the lens's vocabulary (notices-first / recedes / native-vocabulary) to apply at retrieval time. Read the full spec at the path underlenses.{slug}.spec_path(e.g.,lenses/cto.md) only when the query needs the lens's grounding contract, fire-list, or trust-breaking-failure-mode reasoning, i.e. when why this lens reads what it does is material, not just what it reads. Citation-grade synthesis, real-person voice fidelity, and high-stakes artefact shaping are the typical cases. - At retrieval, prefer a pre-projected (source, task, lens) distillation when one exists. If the distillation is lens-neutral in this build, apply the lens at query time via the index entry's
salienceblock (and the full spec's Salience and vocabulary section if Step 4 says read the full spec): the retrieval-time fallback documented in [projection-protocol.md](../creating-distillations/projection-protocol.md) §Retrieval-time fallback.
Lens application shapes salience and voice; the matrix-axis reads (task index → distillations → deeps) run unchanged. The trace footer names the lens used (or "no lens" when the deliverable was lens-neutral).
**Step 0.5 runs before sub-claim decomposition.** The lens shapes what the sub-claims should be: a CTO-lens memo and a builder-lens runbook decompose the same source question into different sub-claim lists. Decompose after the lens is named, not before.
Sub-claim decomposition (Protocols D and S)
For Protocols D and S, before reading reference files, decompose the question into the 3-10 sub-claims the answer will need to make. Write the sub-claim list out explicitly. Examples:
- "What is Agile?" → origin/motivation; key principles; methodology family; common failure modes; critique/limits; evolution post-Agile.
- "How do I handle a stakeholder conflict?" → identify positions vs interests; surface the conflict safely; structure the conversation; close to commitment.
The sub-claim list is the coverage map for retrieval. Stop reading when every sub-claim has at least one strong source AND the next read would only thicken existing coverage.
Skip decomposition for Protocol N: a named lookup has one sub-claim by construction.
Protocol N: Named lookup
- Route directly. Read the corpus catalogue at
reference-index.json: top-level shape is{schema_version, corpus, generated_from, refs}; the per-entry catalogue lives under therefsfield, keyed by 3-character slug-ID (e.g.,refs["00h"]) with each entry carrying{slug, author, year, title, primary_topic, concept_tags, lines_light, lines_deep, scope}. To resolve a named source: scanrefsentries for an author/title/concept_tags match, take the entry'sslugfield, then readreferences/{slug}.mdand{slug}-deep.md. The ID is the join key for concept-index and task-index cross-references; the slug is the file-path key. For task-bound named references also read the relevant task-axis index atdistillations/{task}/task-index.json. - Read the light first.
references/{slug}.mdfor orientation. - Read the deep.
references/{slug}-deep.mdif the question needs citations or substantive treatment. For "what is X" questions and for full-coverage signals ("walk me through", "every section", "full map") read the deep regardless of regime. For "remind me of X" questions, the light alone may suffice. Pick the regime (Citation-grade / Depth-over-breadth / Orientation: table under Protocol S Pass 3) the same way Protocol S does; for a Named lookup with explicit "with citations" or scholarly context, or with a defensibility-critical / under-legal-review framing, fire Citation-grade and surface evidence-classification markers. Long-deep pagination: ifreference-index.json'srefs[id].lines_deepfor the slug exceeds ~400, apply the EOF-successive-reads pattern under Pass 1's cap-aware surfaces and label each read in the trace. - Read the distillation if the question is task-bound:
distillations/{task}/{slug}-{task}.md. - Stop. No triage, no breadth sweep.
Protocol D: Diagnostic
- Decompose the question into 3-6 sub-claims (see above).
- Read the task-axis index at
distillations/{task}/task-index.json. The JSON partitions the task into named phases or situations (each asection) and lists which references apply to each (rowsas[need, slug-id, when]triples). Resolve each slug-ID viareferences/slug-table.json(top-level shape{schema_version, corpus, generated, next_id, slugs}; theid → slugmapping lives underslugs.{id}) or viareference-index.json["refs"][id].slug; either gets you the file-path key forreferences/{slug}.md,{slug}-deep.md, anddistillations/{task}/{slug}-{task}.md. Note: the larger task-axis indexes exceed the Read tool's 25k cap: see Pass 1's cap-aware surfaces and the EOF-successive-reads pattern; for Protocol D prefer the python3 query againstsections[].rowssince you know the phase from step 3.
Unlike Protocol S Pass 1, Protocol D does not require the corpus-level indexes (reference-index.json, concept-index.json) by default: the task-axis index plus the slug-table resolve the candidate sources. Read the corpus-level indexes only if the task-axis index doesn't surface a match or the question crosses the task axis.
- Identify the relevant phase or situation for the question.
- Lean-mode check (when
--leanis passed). If the index surfaces ≤ 2 sources for the identified situation, skip Step 5 (distillations read) and proceed directly to Step 7 (deep refs against the named sources). The index has already done the routing the distillations would do; on canonical material with good filename hygiene, reading the distillations is content-routing overhead. The default (without--lean) is to read the distillations regardless. The flag is the operator's opt-in to the cost-collapse hypothesis: that the curated index is sufficient to route directly to deep refs when it points at one or two sources for a situation. Hypothesis under test: collapsing this step on canonical material brings D's tokens within ~1.5× of Method C without rubric-quality loss; on non-canonical material the distillations layer is doing real work and lean-mode should hurt. Run the eval suite to test. - Read every distillation the index surfaces for that phase/situation (typically 2-5 in this corpus). Distillations at
distillations/{task}/{slug}-{task}.mdare pre-projected for exactly this shape; trust the projection. - Tag each distillation against the sub-claim list. Stop when every sub-claim has at least one strong source AND the next distillation would only restate.
- Read the deep ref for any author whose argument is doing real work in the answer:
references/{slug}-deep.md. The threshold is "would I cite this author?": yes → read the deep. Pick the regime (Citation-grade / Depth-over-breadth / Orientation: table under Protocol S Pass 3) and apply its Pass-3 behaviour; for diagnostic queries the Depth-over-breadth regime is the default, and the distillation-carries-projected-citations calibration applies. The Citation-grade regime fires under D step 7 when the query carries defensibility-critical signals (legal review, audit context, "with citations", manager-pushback): when it fires, apply the Pass-3 read-scope rule under Protocol S Pass 3 (full deep vs targeted re-validation per defensibility unit). Long-deep pagination: ifreference-index.json'srefs[id].lines_deepfor the slug exceeds ~400, apply the EOF-successive-reads pattern under Pass 1's cap-aware surfaces and label each read in the trace.
Protocol S: Synthesis
Three explicit passes:
Pass 1: Routing. Decompose the question into 5-10 sub-claims. Then route:
- Precondition gate: read three corpus-level JSON indexes plus the task-axis index(es) for the domain(s) in play.
Corpus-level (always loaded):
references/slug-table.json: slug ↔ ID mapping; load once per session. Theid → slugmap lives under the top-levelslugskey (full shape:{schema_version, corpus, generated, next_id, slugs}).reference-index.json: file catalogue (one entry per reference: author, year, title, primarytopic, concepttags, scope, line counts). The catalogue's per-ID entries live under the top-levelrefskey (full shape:{schema_version, corpus, generated_from, refs}); query asri["refs"][id].concept-index.json: concept axis with aliases and per-source pointers (entries under top-levelconcepts). Schema: every source entry carries{id}and most carry{context}; the{section, md_line}pair is best-effort, present when the build's mechanical match resolved (~57% of source mentions on the demo corpus, ~65% of concepts have at least one pointer), absent when it didn't. When the pointer is absent, fall through togrep -nagainst the deep ref to find the passage.
Task-axis (load when the question fits a domain):
distillations/{task}/task-index.json: situation router. For grounded-forge's shipped axes (decision-making,stakeholder-engagement,software-business), read the index for each domain that applies; for synthesis questions that span both decision-making and stakeholder-engagement, read both.
Cap-aware surfaces. Several runtime artefacts in the demo corpus either exceed or sit close to the Read tool's 25k single-call cap; each has a specific access pattern:
concept-index.json(~22k tokens): query a specific concept withpython3 -c "import json; ci = json.load(open('concept-index.json')); c = ci.get('concepts', ci); print(json.dumps(c.get('{slug}'), indent=2))". Concept slugs are kebab-case canonical names (e.g.,after-action-review,just-culture,dual-process-theory). Aliases live inside the canonical entry'saliasesarray, not as top-level keys: to resolve an alias (e.g.,aar→after-action-review), reverse-lookup withpython3 -c "import json; ci = json.load(open('concept-index.json'))['concepts']; alias = 'aar'; print(next((k for k, v in ci.items() if alias in v.get('aliases', [])), None))"then probe the canonical key. Try both singular and plural forms; aliases are typically stored singular. Bash querying preserves the index's structure cheaper than pagina
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: chrisgagne
- Source: chrisgagne/grounded-forge
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.