Phase 1 of Eiffel Spec Kit. Generates class skeletons with require/ensure/invariant contracts plus skeletal test classes. Contracts ARE tests brought into the class...
Purpose: Generate class skeletons with contracts before any implementation. Contracts ARE tests - brought in from external test classes to live where they have semantic meaning.
/eiffel.contracts <project-path>
Example:
/eiffel.contracts d:\prod\simple_cache
If no path provided, ask user: "Which project? Provide the full path (e.g., d:\prod\simple_cache)"
All files are created inside the PROJECT directory:
<project-path>/
āāā .eiffel-workflow/
ā āāā intent-v2.md (from Phase 0)
ā āāā evidence/
ā āāā phase1-compile.txt
āāā src/
ā āāā *.e (contract skeletons)
āāā test/
ā āāā *.e (skeletal tests)
āāā <project>.ecf
<project-path>/.eiffel-workflow/intent-v2.md exists and approvedVerify:
test -f <project-path>/.eiffel-workflow/intent-v2.md && echo "Phase 0 complete" || echo "ERROR: Run /eiffel.intent first"
Read <project-path>/.eiffel-workflow/intent-v2.md to understand requirements.
If the library depends on other simple_* libraries, use Task tool:
"What classes does simple_mml provide? Show me MML_SET and MML_MAP signatures."
Create source files in <project-path>/src/ with:
do end stubs (no implementation)ECF must include simple_mml:
<library name="simple_mml" location="$SIMPLE_EIFFEL\simple_mml\simple_mml.ecf"/>
MML Model Query Checklist (MANDATORY for collections):
| Attribute Type | Model Query Type | Example |
|---|---|---|
| HASH_TABLE [V, K] | MML_MAP [K, V] | headers_model: MML_MAP [STRING, STRING] |
| ARRAYED_LIST [T] | MML_SEQUENCE [T] | items_model: MML_SEQUENCE [ITEM] |
| Set-like collection | MML_SET [T] | keys_model: MML_SET [KEY] |
Contract Completeness Checklist: Every postcondition must answer:
old state)|=|)class SIMPLE_CACHE [K, V]
inherit
ANY
redefine
default_create
end
create
make, default_create
feature {NONE} -- Initialization
make (a_capacity: INTEGER)
-- Create cache with `a_capacity` slots.
require
positive_capacity: a_capacity > 0
do
capacity := a_capacity
create internal_table.make (a_capacity)
ensure
capacity_set: capacity = a_capacity
is_empty: count = 0
end
feature -- Model Queries (for MML postconditions)
keys_model: MML_SET [K]
-- Model of all keys in cache.
do
create Result.make_empty
across internal_table as ic loop
Result := Result & @ic.key
end
end
feature -- Commands
put (a_key: K; a_value: V)
-- Store `a_value` under `a_key`.
require
key_valid: a_key /= Void
do
-- Implementation in Phase 4
ensure
has_key: keys_model.has (a_key)
value_stored: item (a_key) = a_value
count_bounded: count <= capacity
others_unchanged: keys_model.removed (a_key) |=| old keys_model.removed (a_key)
end
invariant
count_non_negative: count >= 0
count_bounded: count <= capacity
end
Create test files in <project-path>/test/:
class TEST_SIMPLE_CACHE
inherit
EQA_TEST_SET
feature -- Tests
test_make_creates_empty_cache
-- Test that make creates an empty cache.
local
l_cache: SIMPLE_CACHE [STRING, INTEGER]
do
create l_cache.make (10)
assert ("is empty", l_cache.count = 0)
assert ("capacity set", l_cache.capacity = 10)
end
test_put_stores_value
-- Test that put stores retrievable value.
local
l_cache: SIMPLE_CACHE [STRING, INTEGER]
do
create l_cache.make (10)
l_cache.put ("key", 42)
-- Postconditions verify correctness; this confirms observable behavior
assert ("value retrieved", l_cache.item ("key") = 42)
end
test_put_on_full_cache
-- Skeletal: will be fleshed out in Phase 5.
do
-- TODO: Phase 5
end
end
Ensure <project-path>/<project>.ecf exists with proper targets.
RULE: Validate ECF against simple_* first policy from intent-v2.md.
Scan ECF for violations:
grep -E '\$ISE_LIBRARY|\$GOBO|gobo' <project-path>/<project>.ecf
Allowed ISE libraries (no simple_ equivalent):*
$ISE_LIBRARY/library/base/base.ecf - fundamental types$ISE_LIBRARY/library/time/time.ecf - DATE, TIME, DATE_TIME$ISE_LIBRARY/library/testing/testing.ecf - EQA_TEST_SETBLOCKED (simple_ exists):*
| ISE/Gobo Path | Use Instead |
|---|---|
$ISE_LIBRARY/library/process |
simple_process |
$ISE_LIBRARY/contrib/.../json |
simple_json |
$ISE_LIBRARY/library/net |
simple_http |
$ISE_LIBRARY/library/xml |
simple_xml |
$GOBO/library/regexp |
simple_regex |
$GOBO/library/string |
simple_encoding |
If violation found:
Task(subagent_type=Explore) ā "Does a simple_* library exist for [capability]?"
ECF Template (correct pattern):
<capability>
<concurrency support="scoop"/>
<void_safety support="all"/>
</capability>
<!-- ISE allowed -->
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
<library name="testing" location="$ISE_LIBRARY/library/testing/testing.ecf"/>
<!-- simple_* preferred -->
<library name="simple_json" location="$SIMPLE_EIFFEL/simple_json/simple_json.ecf"/>
<library name="simple_http" location="$SIMPLE_EIFFEL/simple_http/simple_http.ecf"/>
<library name="simple_mml" location="$SIMPLE_EIFFEL/simple_mml/simple_mml.ecf"/>
Evidence: Add to phase1-compile.txt:
ECF Dependency Audit:
- ISE allowed: base, time, testing
- simple_* used: [list]
- Violations: [none or list with justification]
- Gaps identified: [none or list for future simple_*]
CRITICAL: You MUST cd to the project directory before compiling. The EIFGENs folder is created in the current working directory, not where the ECF file is located. Compiling from the wrong directory pollutes other folders with build artifacts.
cd <project-path> && /d/prod/ec.sh -batch -config <project>.ecf -target <project>_tests -c_compile
MUST see "System Recompiled." If compilation fails, fix contracts before proceeding.
ZERO WARNINGS POLICY: If the compiler reports obsolete call warnings or any other warnings, FIX THEM IMMEDIATELY. Do not note them and move on. Do not defer them. Fix them right now before proceeding. Common fixes:
as_string_8: Use explicit {STRING_32} "literal" manifest type or .to_string_8Why: Libraries may compile standalone but break when consumed by SCOOP-enabled projects. This catches VUAR(2) type conformance errors early.
Create a minimal SCOOP consumer test file <project-path>/test/test_scoop_consumer.e:
note
description: "SCOOP consumer compatibility test"
class TEST_SCOOP_CONSUMER
feature -- Test
test_scoop_compatibility
-- Verify library types work in SCOOP context.
local
-- Declare locals using library's main types
l_instance: <MAIN_CLASS>
do
create l_instance.make
-- Minimal usage to trigger type checking
end
end
Compile with explicit SCOOP:
cd <project-path> && /d/prod/ec.sh -batch -config <project>.ecf -target <project>_tests -c_compile
The ECF already has <concurrency support="scoop"/>, so this verifies SCOOP compatibility.
If VUAR(2) errors occur: The library's generic constraints need separate keyword. See simple_mml v1.0.1 for the pattern: [G -> detachable separate ANY]
Save to <project-path>/.eiffel-workflow/evidence/phase1-compile.txt:
# Phase 1 Compilation Evidence
# Project: <project-path>
# Date: [timestamp]
# Command: /d/prod/ec.sh -batch -config <project>.ecf -target <project>_tests -c_compile
[Paste actual compilation output here]
# Status: PASS / FAIL
When compilation succeeds:
Phase 1 COMPLETE: Contracts and skeletal tests created.
Project: <project-path>
Files created:
- src/*.e (contract skeletons)
- test/*.e (skeletal tests)
- Compilation: PASS
Next: Run /eiffel.review <project-path> to submit contracts for adversarial AI review.
This skill focuses ONLY on: <project-path>
DO NOT:
DO:
Example - Ecosystem Query:
Need simple_mml API? Don't read all its files.
Instead: Task(subagent_type=Explore) ā "Show MML_SET and MML_MAP creation and query signatures"
The sub-agent searches, summarizes, and returns ONLY what you need. Your context stays focused on this project.
<project-path>/.eiffel-workflow/skill-improvements.md - do NOT modify skills mid-workflow