Stack Pack Contract Specification
Formal specification of the
StackPackinterface that project-convention extensions implement to plug intoaidokit.
| Field | Value |
|---|---|
| Spec name | aidokit Stack Pack Contract |
| Spec version | 1.0 (draft) |
| Status | Pre-alpha — locked structure, types may shift |
| Targets | AI Dev Orchestrator Spec v2.0 |
| Compatible CLI | aidokit v0.1+ |
| Sibling spec | adapter-contract.md |
| Last reviewed | Pre-publication |
Table of contents
- Purpose and audience
- Document conventions
- Concepts and terminology
- Stack pack vs adapter — division of responsibility
- Lifecycle
- The
StackPackinterface - Supporting types
- Method specifications
- The
StackPackManifest - Detection model
- Skill contribution rules
- MCP suggestion rules
- Validation command rules
- Architecture pattern hints
- Conformance levels
- Worked example:
node-tsstack pack - Versioning and compatibility
- Migration policy
- Security requirements
- Open questions
- Appendix A: Required outputs by conformance level
- Appendix B: Minimum implementation skeleton
1. Purpose and audience
1.1 Purpose
This specification defines the contract every aidokit stack pack MUST satisfy. A stack pack contributes project-convention knowledge for a specific tech stack (Node.js + TypeScript, Python, React, Go, Django, etc.) — detection logic, stack-aware skills, suggested MCPs, validation commands, and optional architecture pattern hints.
This document is normative. Wording follows RFC 2119 conventions.
1.2 Audience
- Stack pack authors building a new
@aidokit/stack-pack-*or@scope/aidokit-stack-pack-*package - Reviewers auditing a stack pack's quality
- Adapter authors consuming
StackPackoutputs - Core team evolving the contract between spec versions
1.3 Non-purpose
This document does NOT specify:
- File emission (stack packs do not emit files directly — see §4)
- Adapter behavior (see
adapter-contract.md) - The MCP catalog format (see
mcp-catalog.md) - The CLI command surface (see
cli-reference.md)
2. Document conventions
2.1 RFC 2119 keywords
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, and REQUIRED are interpreted as described in RFC 2119.
2.2 Type syntax
All types are presented in TypeScript. Stack packs implemented in other languages MUST satisfy the same semantics.
2.3 Reserved namespaces
@aidokit/stack-pack-*— reserved for first-party stack packs by theaidokitcore team- Third-party stack packs MUST publish under their own scope (e.g.,
@acme/aidokit-stack-pack-django) or unscoped (aidokit-stack-pack-django)
3. Concepts and terminology
| Term | Definition |
|---|---|
| Stack pack | A package implementing this contract for one technology stack |
| Stack | A coherent set of language + framework + tooling conventions |
| Detection | The process of determining whether a project uses a given stack |
| Confidence | A categorical score for how strongly a project matches a stack |
| Skill contribution | A SkillTemplate the stack pack provides for adapter emission |
| MCP suggestion | A reference to an MCP catalog id the stack pack recommends |
| Validation command | A shell command suitable for lint/typecheck/test on this stack |
| Architecture pattern hint | A non-binding recommendation about code organization |
ProjectContext |
The immutable context object passed to most methods (defined in @aidokit/core) |
DetectContext |
A lighter context specific to detection (no user selections yet) |
4. Stack pack vs adapter — division of responsibility
This section is critical. Stack packs and adapters are siblings; both extend the core but in orthogonal directions.
| Concern | Owner |
|---|---|
| Engine directory layout | Adapter |
| Agent rules file format | Adapter |
| Verb / role / hook file emission | Adapter |
| Capability profile enforcement | Adapter |
MCP installation mechanism (claude mcp add, …) |
Adapter |
| Detecting the stack from project files | Stack pack |
| Stack-specific skill templates (e.g., Zod conventions) | Stack pack |
| Which MCPs are useful for this stack | Stack pack |
| Default validation commands (lint, typecheck, test) | Stack pack |
| Optional architecture pattern hints | Stack pack |
Key rule: Stack packs MUST NOT emit files directly. They contribute data (skills, suggestions, commands) that adapters consume and emit in their CLI's native format. This keeps stack packs portable across adapters — a Django stack pack works the same way whether Claude Code or Codex consumes it.
5. Lifecycle
Stack pack methods are called at different points during aidokit init and other commands.
5.1 During aidokit init
1. buildDetectContext()
2. for each installed stack pack:
result = await stackPack.detect(detectCtx)
collect (stackPack, result) pairs sorted by confidence
3. user selects which stack packs to enable
4. buildProjectContext() including selectedStackPacks
5. for each selected stack pack:
skills.push(...stackPack.suggestSkills(ctx))
suggestedMcpIds.push(...stackPack.suggestMCPs(ctx))
validationCmds.push(...stackPack.suggestValidationCommands(ctx))
if conformance >= 'strict' and stackPack.defaultArchitecturePattern:
hints.push(stackPack.defaultArchitecturePattern(ctx))
6. pass skills to adapter.emitSkills(ctx, skills)
7. pass validationCmds into the agent rules file emission
8. resolve suggestedMcpIds against the catalog → user picks which to install
9. resolve hints into the architecture-summary doc (if present)
5.2 During aido mcp suggest
1. for each enabled stack pack:
ids = stackPack.suggestMCPs(ctx)
collect ids
2. filter out already-installed MCPs
3. display remaining suggestions
5.3 During aidokit sync
Stack pack outputs are recomputed during sync; new skills or updated suggestions may be proposed to the user.
5.4 Determinism
Stack packs MUST be deterministic. Given identical DetectContext/ProjectContext and identical filesystem state, every method MUST produce byte-identical output.
6. The StackPack interface
The normative TypeScript interface. Every stack pack MUST implement every method except those marked optional.
import type {
StackPackManifest,
DetectContext,
DetectionResult,
ProjectContext,
SkillTemplate,
ValidationCommand,
ArchitecturePatternHint,
} from '@aidokit/core';
export interface StackPack {
/** Static identity and metadata. */
readonly manifest: StackPackManifest;
/** Determine whether the current project uses this stack. */
detect(ctx: DetectContext): Promise<DetectionResult>;
/** Stack-specific skill templates for adapter emission. */
suggestSkills(ctx: ProjectContext): SkillTemplate[];
/** Catalog MCP ids recommended for this stack. */
suggestMCPs(ctx: ProjectContext): string[];
/** Validation commands (lint, typecheck, test) appropriate for this stack. */
suggestValidationCommands(ctx: ProjectContext): ValidationCommand[];
/** OPTIONAL: architecture pattern hint (Strict conformance only). */
defaultArchitecturePattern?(ctx: ProjectContext): ArchitecturePatternHint;
}
7. Supporting types
All types are exported from @aidokit/core.
7.1 DetectContext
Passed to detect(). Lightweight; no user selections yet.
export interface DetectContext {
/** Absolute path to project root. */
projectRoot: string;
/** Whether a file exists at the given path (relative to projectRoot). */
fileExists(relativePath: string): Promise<boolean>;
/** Read a file's content (UTF-8). Throws if missing. */
readFile(relativePath: string): Promise<string>;
/** Read a parsed package manifest file if recognized; null otherwise. */
readManifest(
name: 'package.json' | 'pyproject.toml' | 'Cargo.toml' | 'go.mod' | 'pom.xml' | 'Gemfile',
): Promise<ParsedManifest | null>;
/** Glob within the project root. */
glob(pattern: string): Promise<string[]>;
/** Whether the manifest declares a dependency (name match, version-agnostic). */
manifestHasDep(name: string): Promise<boolean>;
/** OS info for OS-specific detection. */
os: 'darwin' | 'linux' | 'win32';
}
Rules:
DetectContextmethods MUST NOT execute arbitrary shell commandsDetectContextmethods MUST NOT make network callsDetectContextmethods MUST be safe to call on untrusted project directories
7.2 DetectionResult
export interface DetectionResult {
/** Whether the stack was detected. */
matched: boolean;
/** Categorical confidence level. */
confidence: 'high' | 'medium' | 'low' | 'none';
/** Pack-specific extras (e.g., subframework detection). */
extras?: Record<string, unknown>;
/** Human-readable reason explaining the match. */
reason?: string;
}
Confidence semantics:
| Level | Meaning |
|---|---|
high |
Multiple strong signals (manifest dep + framework-marker file) |
medium |
One strong signal OR multiple weak signals |
low |
Single weak signal (e.g., a config file but no manifest dep) |
none |
No match (and matched MUST be false) |
7.3 SkillTemplate
(Already defined in adapter-contract.md; restated for completeness.)
export interface SkillTemplate {
id: string;
name: string;
source: 'core' | 'stack-pack';
sourcePackId?: string;
content: string;
autoLoadTriggers: string[];
preloadedBy: RoleName[];
required: boolean;
}
For stack-pack-contributed skills:
sourceMUST be'stack-pack'sourcePackIdMUST be set to the stack pack'smanifest.namerequiredMUST befalseunless the stack cannot function without the skill
7.4 ValidationCommand
export interface ValidationCommand {
/** Stable identifier (e.g., 'lint', 'typecheck', 'test'). */
id: string;
/** Human-readable label. */
label: string;
/** Shell command to run. */
command: string;
/** Category. */
kind: 'lint' | 'typecheck' | 'test' | 'format-check' | 'build' | 'other';
/** Whether this command is suitable for CI (non-interactive, deterministic exit code). */
ciSafe: boolean;
/** Approximate runtime budget category. */
speed: 'fast' | 'medium' | 'slow';
}
7.5 ArchitecturePatternHint
export interface ArchitecturePatternHint {
/** Pattern name. */
pattern:
| 'mvc'
| 'controller-service-repository'
| 'hexagonal'
| 'clean'
| 'feature-modules'
| 'monolithic'
| 'other';
/** Short rationale. */
rationale: string;
/** Module / directory layout suggestion. */
suggestedLayout: string[];
/** Whether this is opinionated (the stack pack strongly recommends) or default (just a hint). */
strength: 'opinionated' | 'default';
}
8. Method specifications
8.1 detect
detect(ctx: DetectContext): Promise<DetectionResult>
Purpose: Determine whether the current project uses this stack, with a confidence level.
MUST:
- Return a
DetectionResultfor every invocation (no throws on missing files) - Set
matched: falseandconfidence: 'none'when the stack is not present - Set
confidence: 'high'only when at least two independent signals confirm the match - Use only
DetectContextmethods (no direct filesystem or shell access)
SHOULD:
- Combine multiple signals (manifest dep + framework marker file + config) for higher confidence
- Populate
extraswith sub-framework details (e.g.,{ hasDRF: true }for a Django pack detecting Django REST Framework) - Provide a
reasonexplaining the confidence level
MUST NOT:
- Throw on permission errors; return
matched: false, confidence: 'none'instead - Execute arbitrary code from the project (e.g., do not import or evaluate)
- Make network calls
Conformance: Minimum
8.2 suggestSkills
suggestSkills(ctx: ProjectContext): SkillTemplate[]
Purpose: Provide stack-specific skill templates that the adapter will emit into the project's skills directory.
MUST:
- Return zero or more
SkillTemplateobjects - Set
source: 'stack-pack'andsourcePackIdon every returned skill - Mark stack-specific assumptions in skill content with
<REVIEW REQUIRED>so users know to confirm or edit
SHOULD:
- Return between 3 and 8 skills (more than that suggests the pack should be split)
- Cover at least: conventions for the language/framework, testing patterns, error handling style
- Use the project's detected name in skill content where appropriate (via
ctx.projectName)
MUST NOT:
- Include hard-coded paths or values that should be detected from
ctx - Include credentials, API keys, or any secrets
- Reference adapter-specific syntax (skills must be adapter-portable)
- Return skills with the same
idas a core base skill (would shadow the base skill)
Conformance: Minimum
8.3 suggestMCPs
suggestMCPs(ctx: ProjectContext): string[]
Purpose: Recommend MCP catalog ids that are useful for this stack.
MUST:
- Return zero or more catalog ids as strings
- Only return ids that exist in the current MCP catalog
SHOULD:
- Include MCPs that significantly improve the workflow for this stack (e.g.,
playwrightfor frontend stacks,postgres-mcpfor Postgres-detecting packs) - Exclude MCPs marked
securitySensitive: true(those require explicit user opt-in)
MUST NOT:
- Define new MCPs (MCPs must come from the catalog; propose additions via the catalog spec)
- Return duplicates
- Return MCPs scoped to roles that the stack pack cannot guarantee exist
Conformance: Standard
8.4 suggestValidationCommands
suggestValidationCommands(ctx: ProjectContext): ValidationCommand[]
Purpose: Provide validation commands appropriate for the detected stack.
MUST:
- Return commands that are runnable on the detected stack
- Set
ciSafe: falsefor any command that prompts, requires a TTY, or has non-deterministic exit codes
SHOULD:
- Cover at least: lint, typecheck (if applicable), test
- Use the project's actual package manager (detected from lockfile in
ctx) - Reference scripts defined in the project manifest where available (e.g.,
npm run testiftestexists inpackage.json)
MUST NOT:
- Suggest commands that modify files (e.g.,
eslint --fixinstead ofeslint .) - Suggest network-dependent commands without flagging
ciSafe: false
Conformance: Standard
8.5 defaultArchitecturePattern (optional)
defaultArchitecturePattern?(ctx: ProjectContext): ArchitecturePatternHint
Purpose: Suggest an architecture pattern for greenfield projects in this stack.
MUST:
- Only be implemented when the stack pack has strong opinions
- Mark
strength: 'opinionated'only when the pattern is canonical in the community for this stack
SHOULD:
- Provide a
suggestedLayoutlisting 5–10 directory names with one-line purposes - Include rationale referencing community norms (e.g., "Standard Django app layout per docs.djangoproject.com")
MUST NOT:
- Be invoked at Minimum or Standard conformance (gated to Strict only)
- Conflict with adapter-emitted architecture documents (the hint is appended, not overwritten)
Conformance: Strict
9. The StackPackManifest
The static manifest declares identity, capabilities, and conformance.
9.1 Type
export interface StackPackManifest {
/** Stack pack identifier (kebab-case). */
name: string;
/** Human-readable display name. */
displayName: string;
/** Primary programming languages targeted. */
languages: string[];
/** AI Dev Orchestrator Spec version. */
specVersion: '2.0';
/** Version of @aidokit/core the pack was built against. */
sdkVersion: string;
/** Declared conformance level. */
conformance: 'minimum' | 'standard' | 'strict';
/** This package's own version. */
packVersion: string;
/** Maintainer information. */
maintainer: {
name: string;
url?: string;
email?: string;
};
/** Detection signal summary (informational; not enforced). */
detectionSignals: {
files?: string[]; // e.g., ["manage.py"]
manifestDeps?: string[]; // e.g., ["django"]
configFiles?: string[]; // e.g., ["next.config.js"]
};
/** Whether this pack composes with other packs (e.g., react + node-ts). */
composesWith?: string[]; // other stack pack names that complement this one
}
9.2 Manifest file format
Stack packs MUST ship a stack-pack.md (Markdown with YAML frontmatter) at the package root:
---
name: node-ts
displayName: Node.js + TypeScript
languages: [typescript, javascript]
specVersion: '2.0'
sdkVersion: '^1.0'
conformance: standard
packVersion: '0.1.0'
maintainer:
name: aidokit core team
url: https://github.com/your-org/aidokit
detectionSignals:
files: ['tsconfig.json']
manifestDeps: ['typescript']
composesWith: ['react', 'next-js', 'vue']
---
# Node.js + TypeScript Stack Pack
(Human-readable description.)
9.3 Manifest exposure
Both forms (file at rest, object at runtime) MUST be consistent. CI MUST verify they match.
10. Detection model
10.1 Composability
Multiple stack packs MAY match the same project. The composesWith field in the manifest documents expected combinations. Detection MUST be independent: a stack pack's detect() MUST NOT depend on whether another pack matched.
Example: A Next.js project would match node-ts (high), react (high), and a hypothetical next-js (high) pack.
10.2 Confidence ranking
When the CLI presents detection results, it MUST:
- Show all matches at
mediumconfidence or higher - Default-select all
highmatches - Allow the user to add
lowmatches if they choose - Allow the user to deselect any match
10.3 Conflicts
Two stack packs MAY suggest contradictory things (e.g., different validation commands for the same id). When this happens, the CLI MUST:
- Present both options to the user during init
- Default to the highest-confidence pack's suggestion
- Record the resolved choice in
state.jsonfor future sync runs
10.4 Manual override
aidokit init --stack <id1,id2,…> skips detection for the named packs. Useful for monorepos or unusual structures.
10.5 No detection ≠ unsuitable
A pack returning matched: false MAY still be useful (e.g., a react pack on a project not yet using React but planning to). Users MAY force-enable packs via --stack.
11. Skill contribution rules
11.1 Placeholder discipline
Stack pack skills frequently encode assumptions that may not match the user's project. To prevent hallucination:
- Any skill statement that is an opinion or convention the stack pack imposes MUST be marked with
<REVIEW REQUIRED>inline - The CLI MUST surface a "Review needed" warning during init listing the files with placeholders
Example skill content:
# Zod patterns
## Schema location <REVIEW REQUIRED>
This project places Zod schemas in `src/schemas/`. Each schema file
is named `<resource>.schema.ts`.
## Refinement style <REVIEW REQUIRED>
Refinements use `.refine()` with explicit error messages...
11.2 Required skill metadata
Each contributed skill MUST set:
{
id: 'zod-patterns', // unique across all skills
name: 'Zod patterns', // display name
source: 'stack-pack',
sourcePackId: 'node-ts', // matches manifest.name
content: '...', // Markdown body
autoLoadTriggers: ['src/**/*.ts'], // file globs that auto-load
preloadedBy: ['builder', 'tester-reviewer'], // roles that always load it
required: false, // false unless stack cannot function without
}
11.3 Forbidden content
Skills MUST NOT include:
- Hard-coded absolute paths
- Project-specific values that should come from
ctx - Credentials or secrets
- Adapter-specific markup (e.g., Claude Code frontmatter)
- Code samples larger than 30 lines (skills are guidance, not implementation)
11.4 Skill ID conflicts
A stack pack's skill id MUST NOT match a core base skill id or another active stack pack's skill id. The CLI MUST reject installation if a conflict is detected.
12. MCP suggestion rules
12.1 Catalog only
Stack packs MUST reference MCPs by their catalog id. New MCPs MUST be added to the catalog via the catalog spec; stack packs MUST NOT define MCPs inline.
12.2 Stack-appropriateness
A stack pack SHOULD only suggest MCPs that:
- Have triggers that match the stack's typical use cases
- Don't conflict with the stack's conventions (e.g., don't suggest
postgres-mcpfor a project that uses MongoDB)
12.3 No security-sensitive auto-suggest
Stack packs MUST NOT suggest MCPs marked securitySensitive: true. Those are user-initiated only.
12.4 Role-scoping handled by catalog
Stack packs MUST NOT include role-scoping in their MCP suggestions. The role-scoping comes from the catalog entry's suggestedFor field. Stack packs only say "this MCP is useful for this stack."
13. Validation command rules
13.1 Use project's own scripts
If the project manifest defines a script matching a conventional id (lint, test, typecheck), the stack pack SHOULD use it:
// Good
{ id: 'test', label: 'Test', command: 'npm run test', kind: 'test', ciSafe: true, speed: 'medium' }
// Avoid (reinvents what the project already declares)
{ id: 'test', label: 'Test', command: 'npx vitest run', kind: 'test', ciSafe: true, speed: 'medium' }
13.2 Detect the package manager
Stack packs SHOULD detect lockfiles to choose the right invocation:
| Lockfile | Command prefix |
|---|---|
pnpm-lock.yaml |
pnpm |
yarn.lock |
yarn |
package-lock.json |
npm |
bun.lockb |
bun |
13.3 Mark non-CI commands
Commands requiring a TTY, network access, or non-deterministic state MUST set ciSafe: false. The adapter uses this to gate which commands run in headless contexts.
13.4 Speed categorization
Stack packs SHOULD categorize commands by speed:
fast: under 5 seconds (lint, typecheck)medium: under 60 seconds (unit tests)slow: over 60 seconds (e2e, full builds)
This lets the adapter sequence validation appropriately.
14. Architecture pattern hints
14.1 When to provide
A stack pack SHOULD implement defaultArchitecturePattern only when:
- The community strongly favors one pattern (e.g., Django apps, Rails MVC, Phoenix contexts)
- The pattern is not the language's default that any project would adopt anyway
14.2 What the hint becomes
The hint is appended to the project's architecture summary doc (docs/architecture/summary.md or similar) during init, marked <REVIEW REQUIRED>. Users adjust as needed.
14.3 Strength
opinionated— Stack pack strongly recommends; CLI surfaces this prominently during initdefault— A reasonable starting point; CLI mentions it lightly
A stack pack MUST NOT mark a hint as opinionated unless the pattern is canonically associated with the stack.
15. Conformance levels
15.1 Per-method conformance
| Method | Minimum | Standard | Strict |
|---|---|---|---|
detect |
MUST | MUST | MUST |
suggestSkills |
MUST | MUST | MUST |
suggestMCPs |
MAY | MUST | MUST |
suggestValidationCommands |
MAY | MUST | MUST |
defaultArchitecturePattern |
MAY | MAY | SHOULD |
15.2 Minimum conformance
A Minimum stack pack provides detection and at least one skill. Useful for niche stacks where MCP suggestions don't apply.
15.3 Standard conformance (recommended default)
Standard adds MCP and validation suggestions. This is the recommended target for first-party packs and most third-party packs.
15.4 Strict conformance
Strict adds architecture hints. Reserved for stacks with strong community conventions.
15.5 Verification
@aidokit/core exports a stack-pack conformance harness:
import { runStackPackConformanceTests } from '@aidokit/core';
import { stackPack } from './src/index.js';
const results = await runStackPackConformanceTests(stackPack, 'standard');
The harness runs detect() against synthetic fixtures, validates returned SkillTemplate shapes, checks that suggested MCPs exist in the catalog, and verifies validation commands are well-formed. Stack packs MUST run the harness in CI.
16. Worked example: node-ts stack pack
A complete Minimum-to-Standard implementation for Node.js + TypeScript.
// packages/aidokit-stack-pack-node-ts/src/index.ts
import type {
StackPack,
StackPackManifest,
DetectContext,
DetectionResult,
ProjectContext,
SkillTemplate,
ValidationCommand,
} from '@aidokit/core';
const manifest: StackPackManifest = {
name: 'node-ts',
displayName: 'Node.js + TypeScript',
languages: ['typescript', 'javascript'],
specVersion: '2.0',
sdkVersion: '^1.0',
conformance: 'standard',
packVersion: '0.1.0',
maintainer: { name: 'aidokit core team' },
detectionSignals: {
files: ['tsconfig.json'],
manifestDeps: ['typescript'],
},
composesWith: ['react', 'next-js', 'vue', 'express'],
};
export const stackPack: StackPack = {
manifest,
async detect(ctx) {
const hasTsConfig = await ctx.fileExists('tsconfig.json');
const hasPkg = await ctx.fileExists('package.json');
const hasTsDep = hasPkg && (await ctx.manifestHasDep('typescript'));
if (hasTsConfig && hasTsDep) {
return {
matched: true,
confidence: 'high',
reason: 'tsconfig.json present and typescript declared in package.json',
};
}
if (hasTsDep || hasTsConfig) {
return {
matched: true,
confidence: 'medium',
reason: hasTsDep
? 'typescript in deps but no tsconfig.json'
: 'tsconfig.json but no typescript in deps',
};
}
return { matched: false, confidence: 'none' };
},
suggestSkills(_ctx) {
return [
{
id: 'typescript-conventions',
name: 'TypeScript conventions',
source: 'stack-pack',
sourcePackId: 'node-ts',
content: `# TypeScript conventions
## Strictness <REVIEW REQUIRED>
This project uses TypeScript strict mode...
`,
autoLoadTriggers: ['src/**/*.ts'],
preloadedBy: ['builder', 'tester-reviewer'],
required: false,
},
{
id: 'vitest-patterns',
name: 'Vitest patterns',
source: 'stack-pack',
sourcePackId: 'node-ts',
content: `# Vitest patterns
## Test file naming <REVIEW REQUIRED>
Tests are colocated as \`*.test.ts\` next to the source...
`,
autoLoadTriggers: ['**/*.test.ts'],
preloadedBy: ['tester-reviewer'],
required: false,
},
// ... more skills
];
},
suggestMCPs(_ctx) {
return ['context7']; // docs lookup is universally useful
},
suggestValidationCommands(ctx) {
// Detect package manager from lockfile
const pm = ctx.packageManagerLockfile?.includes('pnpm')
? 'pnpm'
: ctx.packageManagerLockfile?.includes('yarn')
? 'yarn'
: 'npm';
return [
{
id: 'lint',
label: 'Lint',
command: `${pm} run lint`,
kind: 'lint',
ciSafe: true,
speed: 'fast',
},
{
id: 'typecheck',
label: 'Typecheck',
command: `${pm} run typecheck`,
kind: 'typecheck',
ciSafe: true,
speed: 'fast',
},
{
id: 'test',
label: 'Test',
command: `${pm} test`,
kind: 'test',
ciSafe: true,
speed: 'medium',
},
];
},
// defaultArchitecturePattern is omitted — Node-TS has no canonical pattern
};
The pack ships via npm:
npm install --save-dev @aidokit/stack-pack-node-ts
The CLI discovers it during init when it scans node_modules for aidokit-stack-pack-* packages.
17. Versioning and compatibility
17.1 Three independent semvers
Same model as the adapter contract:
- Spec version — this contract's version (
1.0) @aidokit/coreSDK version — types semver- Stack pack version — package semver
17.2 Compatibility rules
- Stack packs MUST declare
specVersionandsdkVersion aidokitCLI MUST refuse to load packs declaring an incompatible spec version- Major SDK version mismatches MUST be refused; minor mismatches warned
17.3 Deprecation policy
- Removing a method or required field → major spec bump
- Renaming a field → major spec bump
- Adding an optional method → minor spec bump
- Tightening MAY → SHOULD → non-breaking
- Tightening SHOULD → MUST → breaking
17.4 Sunset window
Major spec bumps support the previous major for at least two minor aidokit CLI releases.
18. Migration policy
18.1 Migration scripts
Every breaking spec change MUST ship with a migration script in @aidokit/core/migrations. Same model as adapter migrations.
18.2 What migrations cover
- Field renames in
StackPackManifest - Method signature changes
- Newly required methods (skeleton implementations)
- Changes to
SkillTemplateshape that affect contributed skills
18.3 What migrations do NOT cover
- Stack-pack-author code logic
- User customizations to emitted skill files (preserved through
aidokit syncdiff-then-merge)
19. Security requirements
19.1 No file emission
Stack packs MUST NOT write files directly. They contribute data to adapters. This eliminates an entire class of security concerns (capability declarations, write-path globs) at the spec level.
19.2 No network calls
detect() MUST NOT make network calls. suggestSkills(), suggestMCPs(), and suggestValidationCommands() MUST NOT make network calls. Stack packs are pure functions of ProjectContext (plus filesystem reads for detect).
19.3 No code execution
Stack packs MUST NOT execute project code (no require(), import(), or shell invocations against project files). DetectContext provides only safe read operations.
19.4 No secrets
Skills, validation commands, and MCP suggestions MUST NOT contain credentials, tokens, or any value sourced from environment variables.
19.5 Reporting issues
Security issues in any stack pack SHOULD be reported per the pack's SECURITY.md. For first-party packs, see ../../../SECURITY.md.
20. Open questions
| Question | Resolution target |
|---|---|
Whether detect() should be cached across stack packs (currently re-runs filesystem reads) |
Spec 1.0 freeze |
Whether to support sub-packs (e.g., node-ts/express as a composition) |
Spec 1.1 |
| How conflicting validation commands from composed packs are merged (currently user-resolved) | Spec 1.1 |
| Whether stack packs should be able to override core base skills | Spec 1.0 freeze |
Whether ArchitecturePatternHint should be machine-readable or include a Markdown blob |
Spec 1.0 freeze |
Whether to add a suggestADRs(ctx) method for stacks with canonical decisions to capture |
Spec 1.1 |
Appendix A: Required outputs by conformance level
Minimum
manifestdetect()returning a validDetectionResultsuggestSkills()returning at least oneSkillTemplatewith placeholder markers
Standard
All of Minimum, plus:
suggestMCPs()returning at least one valid catalog id (or empty array with documented reason)suggestValidationCommands()returning at least one command matching akind
Strict
All of Standard, plus:
defaultArchitecturePattern()returning a populatedArchitecturePatternHint- All skills marked
<REVIEW REQUIRED>where applicable - Pack declares
composesWithif it commonly pairs with others
Appendix B: Minimum implementation skeleton
Proposed scaffolding script (ships in @aidokit/sdk-stack-pack post-1.0):
npx @aidokit/sdk-stack-pack create elixir-phoenix
✔ Created packages/aidokit-stack-pack-elixir-phoenix/
├── stack-pack.md
├── src/
│ ├── index.ts ← exports stackPack
│ ├── detect.ts
│ ├── skills/
│ │ ├── phoenix-conventions/SKILL.md
│ │ └── ecto-patterns/SKILL.md
│ ├── mcps.ts
│ └── validation.ts
├── test/
│ ├── conformance.test.ts
│ └── detection.test.ts
└── package.json
Pre-1.0 (before SDK ships): copy packages/stack-pack-node-ts/ and adapt.
See also
adapter-contract.md— sibling contract for adapters../../ARCHITECTURE.md— system design contextcli-reference.md—aidokitcommands that invoke stack packsmcp-catalog.md— MCP catalog (referenced bysuggestMCPs)conformance-levels.md— per-level checklists- Upstream
orchestrator-spec.md— tool-agnostic workflow spec