SpecMemClient¶
The main entry point for all SpecMem operations.
Import¶
Constructor¶
SpecMemClient(
config_path: str | Path | None = None,
embedding_provider: str | None = None,
vectordb_backend: str | None = None,
)
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
config_path |
str \| Path \| None |
Path to config file | Auto-detect |
embedding_provider |
str \| None |
Override embedding provider | From config |
vectordb_backend |
str \| None |
Override vector backend | From config |
Example¶
# Default configuration
sm = SpecMemClient()
# Custom config file
sm = SpecMemClient(config_path="./custom.toml")
# Override settings
sm = SpecMemClient(
embedding_provider="openai",
vectordb_backend="chroma"
)
Methods¶
query¶
Search specifications using semantic search.
def query(
query: str,
top_k: int = 5,
spec_type: SpecType | None = None,
lifecycle: Lifecycle | None = None,
threshold: float = 0.5,
) -> list[QueryResult]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
query |
str |
Search query | required |
top_k |
int |
Number of results | 5 |
spec_type |
SpecType \| None |
Filter by type | None |
lifecycle |
Lifecycle \| None |
Filter by lifecycle | None |
threshold |
float |
Minimum similarity | 0.5 |
Example¶
results = sm.query("authentication requirements", top_k=10)
for result in results:
print(f"{result.spec.path}: {result.score:.2f}")
get_context_for_change¶
Get context bundle for code changes.
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
files |
list[str] |
Changed file paths | required |
include_tests |
bool |
Include test recommendations | True |
Example¶
bundle = sm.get_context_for_change(["src/auth/service.py"])
print(bundle.tldr)
print(f"Impacted specs: {len(bundle.impacted)}")
print(f"Tests to run: {bundle.recommended_tests}")
get_impacted_specs¶
Get specifications impacted by file changes.
def get_impacted_specs(
files: list[str],
depth: int = 2,
include_transitive: bool = True,
) -> list[SpecBlock]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
files |
list[str] |
Changed file paths | required |
depth |
int |
Traversal depth | 2 |
include_transitive |
bool |
Include transitive | True |
Example¶
impacted = sm.get_impacted_specs(["src/auth/service.py"])
for spec in impacted:
print(f"Impacted: {spec.path}")
get_impacted_tests¶
Get tests affected by file changes.
Example¶
validate¶
Validate all specifications.
def validate(
rules: list[str] | None = None,
min_severity: Severity = Severity.WARNING,
) -> list[ValidationIssue]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
rules |
list[str] \| None |
Rules to run | All rules |
min_severity |
Severity |
Minimum severity | WARNING |
Example¶
issues = sm.validate()
for issue in issues:
print(f"[{issue.severity}] {issue.spec}:{issue.line}")
print(f" {issue.message}")
validate_spec¶
Validate a specific specification.
Example¶
get_drift_report¶
Get specification drift report.
Example¶
drift = sm.get_drift_report()
print(f"Stale specs: {len(drift.stale)}")
print(f"Orphaned specs: {len(drift.orphaned)}")
print(f"Contradictions: {len(drift.contradictions)}")
pin_spec¶
Pin a specification for guaranteed recall.
Example¶
unpin_spec¶
Unpin a specification.
get_all_specs¶
Get all indexed specifications.
def get_all_specs(
spec_type: SpecType | None = None,
lifecycle: Lifecycle | None = None,
) -> list[SpecBlock]
Example¶
# All specs
all_specs = sm.get_all_specs()
# Only requirements
requirements = sm.get_all_specs(spec_type=SpecType.REQUIREMENT)
# Only active specs
active = sm.get_all_specs(lifecycle=Lifecycle.ACTIVE)
get_spec¶
Get a specific specification by ID or path.
Example¶
scan¶
Scan and index specifications.
Example¶
result = sm.scan(force=True)
print(f"Indexed: {result.indexed}")
print(f"Skipped: {result.skipped}")
print(f"Errors: {result.errors}")
build¶
Build the Agent Experience Pack.
Example¶
get_coverage¶
Analyze spec coverage for all features or a specific feature.
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
feature |
str \| None |
Feature name to analyze | All features |
Example¶
# Overall coverage
result = sm.get_coverage()
print(f"Coverage: {result.coverage_percentage:.1f}%")
# Specific feature
result = sm.get_coverage("user-authentication")
for match in result.features[0].criteria:
status = "✅" if match.is_covered else "⚠️"
print(f"{status} {match.criterion.number}")
get_coverage_suggestions¶
Get test suggestions for uncovered acceptance criteria.
Example¶
suggestions = sm.get_coverage_suggestions("user-authentication")
for s in suggestions:
print(f"AC {s.criterion.number}: {s.criterion.text[:50]}...")
print(f" Suggested: {s.suggested_name}")
get_coverage_badge¶
Generate a coverage badge for README files.
Example¶
badge = sm.get_coverage_badge()
print(badge)
# 
Lifecycle Methods¶
Methods for managing specification health, pruning, generation, and compression.
get_spec_health¶
Get health scores for specifications.
def get_spec_health(
spec_name: str | None = None,
stale_days: int = 90,
) -> SpecHealthScore | dict
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
spec_name |
str \| None |
Specific spec to analyze | All specs |
stale_days |
int |
Days threshold for stale detection | 90 |
Example¶
# Get health for all specs
health = sm.get_spec_health()
print(f"Total specs: {health['total_specs']}")
print(f"Orphaned: {health['orphaned_count']}")
print(f"Average score: {health['average_score']:.2f}")
# Get health for specific spec
score = sm.get_spec_health("auth-feature")
print(f"Score: {score.score:.2f}")
print(f"Orphaned: {score.is_orphaned}")
print(f"Stale: {score.is_stale}")
prune_specs¶
Prune orphaned or stale specifications.
def prune_specs(
spec_names: list[str] | None = None,
mode: str = "archive",
dry_run: bool = True,
force: bool = False,
orphaned: bool = False,
stale: bool = False,
stale_days: int = 90,
) -> list[PruneResult]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
spec_names |
list[str] \| None |
Specific specs to prune | None |
mode |
str |
"archive" or "delete" | "archive" |
dry_run |
bool |
Preview without applying | True |
force |
bool |
Skip confirmation for delete | False |
orphaned |
bool |
Prune all orphaned specs | False |
stale |
bool |
Prune all stale specs | False |
stale_days |
int |
Days threshold for stale | 90 |
Example¶
# Preview orphaned specs
results = sm.prune_specs(orphaned=True)
for r in results:
print(f"Would {r.action}: {r.spec_name} ({r.reason})")
# Actually archive orphaned specs
results = sm.prune_specs(orphaned=True, dry_run=False)
# Delete specific specs
results = sm.prune_specs(
spec_names=["old-feature", "deprecated-api"],
mode="delete",
dry_run=False,
force=True,
)
generate_specs¶
Generate specifications from code files.
def generate_specs(
files: list[str],
format: str = "kiro",
group_by: str = "directory",
write: bool = False,
) -> list[GeneratedSpec]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
files |
list[str] |
File or directory paths | required |
format |
str |
Output format ("kiro", "speckit") | "kiro" |
group_by |
str |
Grouping ("file", "directory", "module") | "directory" |
write |
bool |
Write specs to disk | False |
Example¶
# Generate specs from directory
specs = sm.generate_specs(["src/auth/"])
for spec in specs:
print(f"{spec.name}: {len(spec.functions)} functions")
# Generate and write to disk
specs = sm.generate_specs(
["src/auth.py", "src/users.py"],
format="kiro",
write=True,
)
compress_specs¶
Compress verbose specifications.
def compress_specs(
spec_names: list[str] | None = None,
threshold: int = 5000,
all_verbose: bool = False,
save: bool = False,
) -> list[CompressedSpec]
Parameters¶
| Parameter | Type | Description | Default |
|---|---|---|---|
spec_names |
list[str] \| None |
Specific specs to compress | None |
threshold |
int |
Char threshold for verbose | 5000 |
all_verbose |
bool |
Compress all verbose specs | False |
save |
bool |
Save compressed versions | False |
Example¶
# Find verbose specs
verbose = sm.compress_specs()
print(f"Verbose specs: {verbose}")
# Compress specific spec
results = sm.compress_specs(spec_names=["auth-feature"])
for r in results:
print(f"{r.spec_name}: {r.compression_ratio:.1%} reduction")
# Compress all verbose specs and save
results = sm.compress_specs(all_verbose=True, save=True)