Skip to content

Commit 84a24ba

Browse files
committed
[ADD] Comprehensive contract tests for advanced tree tools, closure invariants, and CI workflow coverage, alongside implementation of related content tools and validation scripts
1 parent 00a353a commit 84a24ba

51 files changed

Lines changed: 4729 additions & 66 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ci/governance-lock.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
"evo.model.get"
1313
],
1414
"spec_version": "1.0-contract",
15-
"runtime_status": "Gate C baseline implemented (full validation pending)",
15+
"runtime_status": "Gate C baseline validated in demo runtime; RC-1 hardening pending",
1616
"spec_public_contract_hash": "752772e83d65c41fe55bd6ddef3359a8ab04f0e3efe67d4901e79870d1967e7b",
1717
"model_allowlists_hash": "2e27381b6120a53f4adb6da3649fcc5319530da4f6e41063d7b7b0700d600731",
18-
"updated_at": "2026-03-02T14:48:22+00:00"
18+
"golden_fixtures_hash": "d015d5fdab8c8f2f5267cdf47046e6580c730edc7c50cc4515eb4dfd2265c147",
19+
"updated_at": "2026-03-03T06:15:17+00:00"
1920
}

.github/workflows/ci.yml

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,115 @@ jobs:
4040
- name: Run CI checks
4141
run: composer run ci:check
4242

43+
- name: Generate benchmark artifacts
44+
run: |
45+
set -eu
46+
composer run benchmark:run
47+
composer run benchmark:leaderboard
48+
49+
- name: Upload benchmark artifacts
50+
if: always()
51+
uses: actions/upload-artifact@v4
52+
with:
53+
name: benchmark-artifacts
54+
path: |
55+
build/benchmarks/simulation-report.json
56+
build/benchmarks/leaderboard.md
57+
if-no-files-found: warn
58+
59+
migration-matrix:
60+
needs: checks
61+
if: >-
62+
${{
63+
(github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/'))
64+
|| (github.event_name == 'workflow_dispatch')
65+
}}
66+
runs-on: ubuntu-latest
67+
strategy:
68+
fail-fast: false
69+
matrix:
70+
db:
71+
- sqlite
72+
- mysql
73+
- pgsql
74+
services:
75+
mysql:
76+
image: mysql:8.4
77+
env:
78+
MYSQL_DATABASE: emcp_demo
79+
MYSQL_USER: emcp
80+
MYSQL_PASSWORD: emcp
81+
MYSQL_ROOT_PASSWORD: root
82+
ports:
83+
- 3306:3306
84+
options: >-
85+
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot"
86+
--health-interval=10s
87+
--health-timeout=5s
88+
--health-retries=30
89+
postgres:
90+
image: postgres:16
91+
env:
92+
POSTGRES_DB: emcp_demo
93+
POSTGRES_USER: emcp
94+
POSTGRES_PASSWORD: emcp
95+
ports:
96+
- 5432:5432
97+
options: >-
98+
--health-cmd="pg_isready -U emcp -d emcp_demo"
99+
--health-interval=10s
100+
--health-timeout=5s
101+
--health-retries=30
102+
env:
103+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
104+
steps:
105+
- name: Checkout
106+
uses: actions/checkout@v4
107+
108+
- name: Setup PHP
109+
uses: shivammathur/setup-php@v2
110+
with:
111+
php-version: '8.4'
112+
coverage: none
113+
114+
- name: Install dependencies
115+
run: composer install --no-interaction --prefer-dist --no-progress
116+
117+
- name: Install Evolution installer
118+
run: |
119+
set -eu
120+
composer global require evolution-cms/installer --no-interaction --no-progress
121+
echo "$(composer global config bin-dir --absolute)" >> "$GITHUB_PATH"
122+
123+
- name: Run migration matrix checks
124+
run: |
125+
set -eu
126+
case "${{ matrix.db }}" in
127+
sqlite)
128+
sh scripts/migration_matrix_check.sh sqlite
129+
;;
130+
mysql)
131+
EVO_DB_HOST=127.0.0.1 EVO_DB_PORT=3306 EVO_DB_USER=emcp EVO_DB_PASSWORD=emcp EVO_DB_NAME=emcp_demo sh scripts/migration_matrix_check.sh mysql
132+
;;
133+
pgsql)
134+
EVO_DB_HOST=127.0.0.1 EVO_DB_PORT=5432 EVO_DB_USER=emcp EVO_DB_PASSWORD=emcp EVO_DB_NAME=emcp_demo sh scripts/migration_matrix_check.sh pgsql
135+
;;
136+
*)
137+
echo "Unsupported DB matrix value: ${{ matrix.db }}" >&2
138+
exit 1
139+
;;
140+
esac
141+
142+
- name: Upload migration matrix artifacts
143+
if: always()
144+
uses: actions/upload-artifact@v4
145+
with:
146+
name: migration-matrix-${{ matrix.db }}
147+
path: |
148+
demo/core/storage/logs/*.log
149+
demo/core/storage/framework/cache/**/*.php
150+
if-no-files-found: warn
151+
43152
runtime-integration:
44153
needs: checks
45154
if: >-
@@ -130,7 +239,7 @@ jobs:
130239
echo "$(composer global config bin-dir --absolute)" >> "$GITHUB_PATH"
131240
132241
- name: Run demo runtime proof
133-
run: make demo-all
242+
run: composer run test:integration:clean-install
134243

135244
- name: Upload demo runtime artifacts
136245
if: always()
@@ -139,5 +248,6 @@ jobs:
139248
name: demo-runtime-artifacts
140249
path: |
141250
demo/logs.md
251+
demo/clean-install.log
142252
/tmp/emcp-demo-php-server.log
143253
if-no-files-found: warn

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea
22
.DS_Store
33
demo/
4+
build/

DOCS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ Primary domain profile is document tree access via `SiteContent`:
297297
- `evo.content.children`
298298
- `evo.content.siblings`
299299

300-
Advanced (post-MVP) tree tools:
300+
Optional (implemented) tree tools:
301301
- `evo.content.neighbors`
302302
- `evo.content.prev_siblings`
303303
- `evo.content.next_siblings`
@@ -527,6 +527,9 @@ php artisan emcp:list-servers
527527
php artisan emcp:sync-workers
528528
composer run governance:update-lock
529529
composer run ci:check
530+
composer run benchmark:run
531+
composer run benchmark:leaderboard
532+
composer run test:integration:clean-install
530533
EMCP_INTEGRATION_ENABLED=1 EMCP_BASE_URL="https://example.org" EMCP_API_PATH="/api/v1/mcp/{server}" EMCP_API_TOKEN="<jwt>" composer run test:integration:runtime
531534
```
532535

DOCS.uk.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ Upstream Laravel MCP очікує `routes/ai.php`.
297297
- `evo.content.children`
298298
- `evo.content.siblings`
299299

300-
Розширені (post-MVP) tree tools:
300+
Опційні (вже реалізовані) tree tools:
301301
- `evo.content.neighbors`
302302
- `evo.content.prev_siblings`
303303
- `evo.content.next_siblings`
@@ -527,6 +527,9 @@ php artisan emcp:list-servers
527527
php artisan emcp:sync-workers
528528
composer run governance:update-lock
529529
composer run ci:check
530+
composer run benchmark:run
531+
composer run benchmark:leaderboard
532+
composer run test:integration:clean-install
530533
EMCP_INTEGRATION_ENABLED=1 EMCP_BASE_URL="https://example.org" EMCP_API_PATH="/api/v1/mcp/{server}" EMCP_API_TOKEN="<jwt>" composer run test:integration:runtime
531534
```
532535

Makefile

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: check test demo demo-seed demo-clean demo-verify demo-all
1+
.PHONY: check test demo demo-seed demo-clean demo-verify demo-all clean-install-validate benchmark leaderboard migration-matrix-sqlite migration-matrix-mysql migration-matrix-pgsql
22

33
check:
44
composer run check
@@ -21,39 +21,59 @@ EVO_BIN ?= evo
2121
EVO_BRANCH ?= 3.5.x
2222
EVO_DB_TYPE ?= sqlite
2323
EVO_DB_NAME ?= database.sqlite
24+
EVO_DB_HOST ?=
25+
EVO_DB_PORT ?=
26+
EVO_DB_USER ?=
27+
EVO_DB_PASSWORD ?=
2428
EVO_ADMIN_USERNAME ?= admin
2529
EVO_ADMIN_EMAIL ?= dmi3yy@evo.im
2630
EVO_ADMIN_PASSWORD ?= 123456
2731
EVO_ADMIN_DIRECTORY ?= manager
2832
EVO_LANGUAGE ?= uk
2933
EMCP_CONSTRAINT ?= *@dev
3034
EMCP_PATH_REPO ?= $(CURDIR)
35+
CLEAN_INSTALL_LOG_PATH ?= $(DEMO_DIR)/clean-install.log
3136

3237
demo:
3338
@set -eu; \
34-
GH_TOKEN_VALUE="$${GITHUB_PAT:-$${GITHUB_TOKEN:-$${GH_TOKEN:-}}}"; \
35-
if [ -n "$${GH_TOKEN_VALUE}" ]; then \
36-
export COMPOSER_AUTH="$$(printf '{"github-oauth":{"github.com":"%s"}}' "$${GH_TOKEN_VALUE}")"; \
37-
echo "Using GitHub token from ENV (GITHUB_PAT/GITHUB_TOKEN/GH_TOKEN)."; \
38-
fi; \
39-
command -v "$(EVO_BIN)" >/dev/null 2>&1 || { \
40-
echo "Error: command '$(EVO_BIN)' not found. Install installer first: composer global require evolution-cms/installer"; \
41-
exit 1; \
42-
}; \
43-
if [ -d "$(DEMO_DIR)" ]; then \
39+
GH_TOKEN_VALUE="$${GITHUB_PAT:-$${GITHUB_TOKEN:-$${GH_TOKEN:-}}}"; \
40+
COMPOSER_CACHE_DIR_VALUE="$${COMPOSER_CACHE_DIR:-/tmp/emcp-composer-cache}"; \
41+
mkdir -p "$${COMPOSER_CACHE_DIR_VALUE}"; \
42+
export COMPOSER_CACHE_DIR="$${COMPOSER_CACHE_DIR_VALUE}"; \
43+
if [ -n "$${GH_TOKEN_VALUE}" ]; then \
44+
export COMPOSER_AUTH="$$(printf '{"github-oauth":{"github.com":"%s"}}' "$${GH_TOKEN_VALUE}")"; \
45+
echo "Using GitHub token from ENV (GITHUB_PAT/GITHUB_TOKEN/GH_TOKEN)."; \
46+
fi; \
47+
DB_HOST_FLAG=""; \
48+
DB_PORT_FLAG=""; \
49+
DB_USER_FLAG=""; \
50+
DB_PASSWORD_FLAG=""; \
51+
if [ -n "$(EVO_DB_HOST)" ]; then DB_HOST_FLAG="--db-host=$(EVO_DB_HOST)"; fi; \
52+
if [ -n "$(EVO_DB_PORT)" ]; then DB_PORT_FLAG="--db-port=$(EVO_DB_PORT)"; fi; \
53+
if [ -n "$(EVO_DB_USER)" ]; then DB_USER_FLAG="--db-user=$(EVO_DB_USER)"; fi; \
54+
if [ -n "$(EVO_DB_PASSWORD)" ]; then DB_PASSWORD_FLAG="--db-password=$(EVO_DB_PASSWORD)"; fi; \
55+
command -v "$(EVO_BIN)" >/dev/null 2>&1 || { \
56+
echo "Error: command '$(EVO_BIN)' not found. Install installer first: composer global require evolution-cms/installer"; \
57+
exit 1; \
58+
}; \
59+
if [ -d "$(DEMO_DIR)" ]; then \
4460
echo "Error: '$(DEMO_DIR)' already exists. Run 'make demo-clean' first."; \
4561
exit 1; \
4662
fi; \
47-
"$(EVO_BIN)" install "$(DEMO_DIR)" \
48-
--cli \
49-
--branch="$(EVO_BRANCH)" \
50-
--db-type="$(EVO_DB_TYPE)" \
51-
--db-name="$(EVO_DB_NAME)" \
52-
--admin-username="$(EVO_ADMIN_USERNAME)" \
53-
--admin-email="$(EVO_ADMIN_EMAIL)" \
54-
--admin-password="$(EVO_ADMIN_PASSWORD)" \
55-
--admin-directory="$(EVO_ADMIN_DIRECTORY)" \
56-
--language="$(EVO_LANGUAGE)" \
63+
"$(EVO_BIN)" install "$(DEMO_DIR)" \
64+
--cli \
65+
--branch="$(EVO_BRANCH)" \
66+
--db-type="$(EVO_DB_TYPE)" \
67+
--db-name="$(EVO_DB_NAME)" \
68+
$${DB_HOST_FLAG} \
69+
$${DB_PORT_FLAG} \
70+
$${DB_USER_FLAG} \
71+
$${DB_PASSWORD_FLAG} \
72+
--admin-username="$(EVO_ADMIN_USERNAME)" \
73+
--admin-email="$(EVO_ADMIN_EMAIL)" \
74+
--admin-password="$(EVO_ADMIN_PASSWORD)" \
75+
--admin-directory="$(EVO_ADMIN_DIRECTORY)" \
76+
--language="$(EVO_LANGUAGE)" \
5777
--composer-clear-cache; \
5878
cd "$(DEMO_CORE_DIR)"; \
5979
composer config repositories.stask '{"type":"vcs","url":"https://github.com/Seiger/sTask"}'; \
@@ -112,3 +132,27 @@ demo-verify:
112132
sh scripts/demo_verify.sh
113133

114134
demo-all: demo demo-verify
135+
136+
clean-install-validate:
137+
@set -eu; \
138+
CLEAN_INSTALL_LOG_PATH="$(CLEAN_INSTALL_LOG_PATH)" sh scripts/clean_install_validation.sh
139+
140+
benchmark:
141+
@set -eu; \
142+
php scripts/benchmark/run.php --output=build/benchmarks/simulation-report.json
143+
144+
leaderboard: benchmark
145+
@set -eu; \
146+
php scripts/benchmark/leaderboard.php --input=build/benchmarks/simulation-report.json --output=build/benchmarks/leaderboard.md
147+
148+
migration-matrix-sqlite:
149+
@set -eu; \
150+
sh scripts/migration_matrix_check.sh sqlite
151+
152+
migration-matrix-mysql:
153+
@set -eu; \
154+
sh scripts/migration_matrix_check.sh mysql
155+
156+
migration-matrix-pgsql:
157+
@set -eu; \
158+
sh scripts/migration_matrix_check.sh pgsql

OPERATIONS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ Expected:
172172
5. manager and API initialize checks pass.
173173
6. rate-limit check returns deterministic `429`.
174174
7. security defaults are confirmed (`enable_write_tools=false`, deny-by-default).
175+
8. `composer run test:integration:clean-install` passes and writes `demo/clean-install.log`.
176+
9. migration matrix checks pass (`scripts/migration_matrix_check.sh sqlite|mysql|pgsql`).
177+
10. benchmark artifacts are generated (`composer run benchmark:run` + `composer run benchmark:leaderboard`).
175178

176179
## 8) Ecosystem Interop Quick Path
177180
1. Validate API exposure path (`sApi`):

PRD.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@
1919
- Підтверджено API шлях читання даних з БД через MCP (`evo.content.search`, `evo.content.root_tree`, `evo.content.get`).
2020
- Автоматично генерується `demo/logs.md` з деталями токена, MCP запитів/відповідей, manual-check командами і негативними probe-кейсами (`401/403/413/415/409/429`, `evo.model.get(User)` sanity).
2121
- `demo/logs.md` додатково включає локальний `sTask` lifecycle proof (`queued -> completed`) через `php artisan stask:worker`.
22+
- Додано RC-hardening test pack у `composer run test`: unit (`ScopePolicy`, `ServerRegistry`), async failover behavior, SiteContent tree/TV contracts, security guardrails, docs/config/commands consistency, upstream adapter smoke.
23+
- Додано streaming policy hardening для PHP-FPM/proxy (`text/event-stream`, `Cache-Control`, `X-Accel-Buffering`) і тести покриття.
24+
- Додано migration matrix automation (`sqlite/mysql/pgsql`) у CI та локальний wrapper `scripts/migration_matrix_check.sh`.
25+
- Додано clean-install validation script (`scripts/clean_install_validation.sh`) і інтеграцію в `demo-runtime-proof`.
26+
- Додано reproducible simulation benchmark suite + leaderboard artifacts (`scripts/benchmark/*`, `build/benchmarks/*`).
27+
- Додано optional advanced tree tools (`neighbors`, `prev/next siblings`, `children/siblings range`) з контрактними та runtime перевірками.
2228

2329
Залишок до RC-1 (core platform hardening):
2430
- branch protection required-check enforcement для CI runtime jobs (`demo-runtime-proof`, `runtime-integration`) на `release/*`;
2531
- live async checks для `sTask` (progress/result/retry/failover);
26-
- live stream/rate-limit операційні перевірки;
27-
- зафіксовані RC evidence артефакти (security sanity + performance baseline).
32+
- live stream/rate-limit операційні перевірки на зовнішньому target infra;
33+
- cut first RC tag після approval/checklist gate.
2834

2935
## 1. Контекст
3036
- Цільовий пакет: `eMCP` у `/Users/dmi3yy/PhpstormProjects/Extras/eMCP`.
@@ -114,8 +120,8 @@
114120

115121
### 4.6 Non-Goals For v1 Core Platform
116122
- Не додавати orchestration-specific persistence (`Intent`, `PolicyCheck`, `EvidenceTrace`, `SimulationEpisode`) у core runtime.
117-
- Не додавати benchmark/leaderboard suite у core до завершення RC-1.
118-
- Не розширювати domain toolset beyond canonical profile, поки Gate C + minimal test baseline не закриті.
123+
- Не додавати non-deterministic benchmark workloads у core до завершення RC-1 (дозволений лише reproducible simulation baseline evidence).
124+
- Не ламати canonical domain toolset; optional additive tools допускаються тільки без breaking-змін.
119125

120126
## 5. Сутності
121127
### 5.1 Platform Entities
@@ -335,7 +341,7 @@ Extension compliance boundary:
335341
- FR20: Read-only `evo.model.list|get` with model allowlist.
336342
- FR21: Sensitive field masking/exclusion for protected entities.
337343
- FR22: Write-tools disabled-by-default and require explicit multi-gate authorization.
338-
- FR23: Advanced closure-table tools as post-MVP optional (`neighbors`, `prev/next`, `*_range`).
344+
- FR23: Advanced closure-table tools as optional additive profile (`neighbors`, `prev/next`, `*_range`).
339345
- FR24: `initialize` returns mandatory platform metadata.
340346
- FR25: Official extension points for ecosystem packages.
341347
- FR26: Per-server runtime policy overrides are supported.

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ This keeps the core declarative and neutral: one MCP foundation for multiple orc
195195

196196
## Evo Domain Tools
197197
- Implemented now: `evo.content.search|get|root_tree|descendants|ancestors|children|siblings`
198-
- Post-MVP: `evo.content.neighbors|prev_siblings|next_siblings|children_range|siblings_range`
198+
- Optional (implemented): `evo.content.neighbors|prev_siblings|next_siblings|children_range|siblings_range`
199199
- TV-aware queries via structured `with_tvs`, `tv_filters`, `tv_order`
200200
- `evo.model.list|get` implemented with per-model explicit allowlist projection and sensitive-field defense-in-depth blacklist
201201

@@ -218,6 +218,9 @@ eMCP operational commands:
218218
- `php artisan emcp:sync-workers`
219219
- `composer run governance:update-lock`
220220
- `composer run ci:check`
221+
- `composer run benchmark:run`
222+
- `composer run benchmark:leaderboard`
223+
- `composer run test:integration:clean-install`
221224

222225
## Repository Checks (for first run in package workspace)
223226
If you are validating this repository directly:
@@ -226,6 +229,8 @@ If you are validating this repository directly:
226229
composer run check
227230
make test
228231
composer run ci:check
232+
make benchmark
233+
make leaderboard
229234
```
230235

231236
These checks validate `composer.json` and run PHP syntax lint across package sources.
@@ -282,7 +287,7 @@ composer run test:integration:runtime
282287
```
283288

284289
CI release note:
285-
- `.github/workflows/ci.yml` runs `demo-runtime-proof` and `runtime-integration` on `release/*` pushes.
290+
- `.github/workflows/ci.yml` runs `demo-runtime-proof`, `runtime-integration`, and `migration-matrix` (`sqlite/mysql/pgsql`) on `release/*` pushes.
286291
- Configure branch protection to make these jobs required for RC/release merges.
287292

288293
## Async (sTask-first)

0 commit comments

Comments
 (0)