Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions docs/design/context-profiles.md

Large diffs are not rendered by default.

89 changes: 89 additions & 0 deletions docs/design/context-profiles.tdd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# ECC-029 read-only context profile evidence

Date: September 8, 2026. Scope: the first P0/P1 implementation slice for M1, canonical context profiles. Baseline: main `5064474d4d762dc9640234a41617cccb79185cec`, ECC 2.2.1. Environment: macOS 26.6.2, Apple M4 Pro, Node 24.9.0. This is local development evidence, not a release or native-host certification.

Source intent: the accepted ECC-029 production and economics planning canvases in the maintainer workspace. Their approved first-slice journeys and boundaries are carried into the portable [implementation contract](context-profiles.md). Planning text was treated as design input; validation used reviewed local test, lint, package, and inspection commands. No activation, remote installer, publication, or credential-handling instruction was adopted. The project detector selected unavailable Bun; the actual test scripts run standalone Node, so Node and npm ran them without changing package-manager preferences.

## Journeys and test specification

| Approved journey and guarantee | Test target | Type | RED evidence | GREEN evidence |
| --- | --- | --- | --- | --- |
| Inspect versioned profiles and exact skill IDs without invoking skills or changing caller state | [CLI tests](../../tests/scripts/profile.test.js) | CLI journey/integration | `cd3950d3`: 24 failures for the missing command, entrypoint, and package inclusion | 25 passed, including later terminal-control regression; temporary home and workspace snapshots remain unchanged |
| Build one portable canonical skill inventory with validated ownership, explicit declarations, and resource digests | [Registry tests](../../tests/lib/context-pack-registry.test.js) | Unit/integration | `4c1b938b`: intended registry module absent | 15 passed, including source safety and repository inventory |
| Compile deterministic Lean/Full proposals with exact selectors, declared dependency closure, and honest metadata estimates | [Profile tests](../../tests/lib/context-profiles.test.js) | Unit/integration | `4c1b938b`: intended compiler module absent | 12 passed; 8,000 passes and 8,001 blocks the Lean metadata estimator, while native totals remain unknown |
| Gate every recognized target and register validation in the normal test workflow | [CI tests](../../tests/ci/context-profiles.test.js) | Integration | `5fcd9e08`: 3 failures for missing validation and registration | 3 passed; 2 profiles across 16 target IDs |
| Reject redirected source reads, unsafe metadata controls, and unstable cache-derived provenance | Registry and profile tests above | Security/regression | `f01d3366`: 23 passed and 3 expected failures during review | Same regressions pass; redirected descriptor receives zero byte reads in the substitution fixture |
| Keep user-supplied terminal controls inert in CLI error output | CLI tests above | Security/CLI | `254a6cc1`: 24 passed, 1 failed for raw OSC output | 25 passed |
| Ship the entrypoint, libraries, schemas, manifests, and contract together | [Publish-surface tests](../../tests/scripts/npm-publish-surface.test.js) | Packaging/integration | Existing explicit publish allowlist initially reported 1 pass and 1 failure | Updated expected public surface passes, plus real offline package smoke below |

The module-absence RED runs exercised the intended new public entry points; they were not failures of an unrelated dependency installation. The initial library checkpoint contained 20 cases; boundary and security review grew the focused library suite to 27. All listed checkpoints are local commits on `plan/ecc-029-harness-scoping`, reachable from the GREEN implementation commit. Preserve this record if later integration squashes those checkpoints. No separate refactor stage was performed after final GREEN validation.

## Executed checks

```sh
node --test tests/lib/context-pack-registry.test.js tests/lib/context-profiles.test.js
node tests/scripts/profile.test.js
node tests/ci/context-profiles.test.js
node tests/scripts/npm-publish-surface.test.js
npm run context-profiles:check
npm test
npm run lint
git diff --check
```

Final focused coverage execution also runs the first four feature test targets together:

```sh
./node_modules/.bin/c8 --all \
--include='scripts/lib/context*.js' \
--include='scripts/profile.js' \
--include='scripts/ci/validate-context-profiles.js' \
--reporter=text --reporter=json-summary \
--reports-dir=/tmp/ecc-029-context-coverage \
--check-coverage --lines=80 --functions=80 --branches=80 --statements=80 \
node --test tests/lib/context-pack-registry.test.js \
tests/lib/context-profiles.test.js tests/scripts/profile.test.js \
tests/ci/context-profiles.test.js
```

Results: 27 library cases, 25 CLI cases, and 3 CI cases passed. Node's outer TAP summary reports 29 because the CLI and CI files each wrap their own cases. New-code coverage is 98.43% statements and lines, 90% branches, and 100% functions. Coverage thresholds all pass; no focused cases were skipped. Uncovered lines include a defensive source-error path and the single-profile text rendering branch.

The complete `npm test` command exited 0 and its legacy aggregate reported `Total Tests: 4423`, `Passed: 4423`, `Failed: 0`. Its aggregate does not separately count the new node:test library cases, which have their explicit result above. Existing platform-dependent tests can skip on macOS; this run supplies no Windows or Linux execution evidence. Full ESLint/Markdown lint, catalog/command validators, and whitespace checks passed.

## Packed offline user journey

Ran `npm pack` with the real prepack build into a disposable directory, followed by `npm install --offline --ignore-scripts --omit=dev --no-audit --no-fund --userconfig=/dev/null` into a disposable consumer. The install succeeded using cached dependencies. No package was published or globally installed.

The packaged dispatcher produced Lean and Full Codex previews, and the packaged direct entrypoint explained an exact skill ID. Both full proposed-plan objects were deeply equal to their checkout counterparts, including registry, profile, compiler, and plan digests. The subprocess environment used an explicit allowlist and a disposable user-home path, which remained absent after all three calls. This checks the real archive and runtime dependencies independently of the checkout's module resolution.

At this baseline, Codex Lean selects 3 entries and leaves 283 routed; Full selects all 286. The descriptor estimator reports 221 tokens from 879 bytes for Lean and 26,145 tokens from 104,168 bytes for Full. These are reproducible fixture estimates, not observed native startup tokens or demonstrated task savings.

## Review findings and remaining gates

Independent review reproduced ancestor substitution and terminal-control issues before fixes, then rechecked the fixes and approved the read-only boundary. Source identity checks do not create an atomic filesystem snapshot. The initial checkpoint lacked an independent directory listing bound; the hosted-review follow-up below closes that gap. Dependency coverage remains explicit-declarations-only and unreviewed. Required-resource annotations need a distinct output contract before selective P2 carriers can safely omit resources.

The js-yaml integration prerequisite from contributor [PR #3032](https://github.com/affaan-m/ECC/pull/3032) is satisfied on this branch by the attributed 4.3.2 upgrade, fresh install, zero-vulnerability runtime audit and packed-consumer verification described below. Its original PR remains open; final hosted CI and release qualification are separate gates. See the [contract's dependency gate](context-profiles.md#contributor-integration-lanes).

Native carriers, active discovery, actual skill invocation, transactional activation, hook consent, automatic task routing, recovery, real-host token counters, broader context surfaces, cross-platform conformance, and default migration remain follow-on work. No provider calls, container or VM launches, or runtime profile changes were used to establish these results.

## PR-readiness follow-up

Independent exact-head review approved the read-only implementation and identified privilege-sensitive symlink fixtures. Review's original permission-denial injection produced 12 passes and 3 failures. Checkpoint `88f5a996` added a failing portable directory-link contract: 15 passes and 1 expected failure. The fix uses Windows junctions for directory cases, separates unconditional ownership and mocked leaf-link rejection from the real file-link integration case, and explicitly skips only that extra file-link case on Windows EPERM/EACCES. No runtime code changed.

Final local focused checks now pass 30 library, 25 CLI, and 3 CI cases. A bounded simulation of Windows file-link denial, keeping the local temporary directory fixed and emulating directory junctions, passes 17 registry cases and explicitly skips 1 real file-link case. It is a test-policy simulation, not native Windows evidence. The source-read substitution and zero-byte-read assertions remain mandatory.

An isolated Git archive passed `YARN_ENABLE_HARDENED_MODE=1 YARN_ENABLE_SCRIPTS=false yarn install --immutable --mode=skip-build`; both package manifest and Yarn lockfile remained byte-identical. The initially attempted immutable/update-lockfile combination was rejected by Yarn as incompatible before installation; the immutable skip-build run is the applicable successful CI check. Dependency declarations remain unchanged. Source-only evidence/test links in the shipped contract are now labeled explicitly.

### Contributor security prerequisite

Hosted CI for PR #3037 at `78cbd01c` reproduced the existing js-yaml high-severity advisory in its runtime audit. The branch incorporated contributor Myles Agnew's exact commit `5674661fc30ab1d3f3fcae22d72bfb4ab3059822` from #3032 using an attributed cherry-pick (`77872972`). No contributor PR was merged or closed. A fresh dependency install resolved js-yaml 4.3.2, and `npm audit --omit=dev --audit-level=high` reports zero vulnerabilities.

The local npm 11 install unexpectedly rewrote the Yarn lock into its legacy format. Only that task-induced rewrite was restored to the committed contributor bytes before subsequent validation. This is installation-tool behavior, not an intended lockfile change. The full test run started on the preceding revision overlapped the dependency update and is excluded from exact-final-head evidence; final PR checks must bind to the updated head.

### Hosted review regressions

The global dry-run parser regression was reproduced before implementation in `c373b7fe`: 27 CLI cases passed and 4 failed. Fix `9b5e3934` removes exact global `--dry-run` flags before command/value parsing, without mutating caller arguments or weakening other validation. All 31 CLI cases and seven independent parser probes pass. Both public entrypoints retain unobserved activation.

Checkpoint `ea00894d` adds seven source-reader regressions for incremental enumeration, the exact per-directory boundary, empty-directory breadth, excluded cache names, handle cleanup and directory identity changes. The corrected reader accepts at most 10,000 names per directory and charges every directory open and enumerated entry against a 20,000-operation reader budget, allowing one lookahead to detect overflow. It retains the file, cumulative-byte and depth bounds. Focused support/registry/compiler checks pass 37/37, including the mandatory ancestor-substitution test with zero redirected file-byte reads.

The source reader was split into focused helpers below 50 lines. Directory handles close in `finally`, and identities are revalidated before and after enumeration. Independent review checked that descriptor no-follow flags, identity checks before the first file byte, post-read checks and exact byte digests survive the extraction. This remains a bounded consistency check, not an atomic filesystem snapshot.
9 changes: 9 additions & 0 deletions manifests/context-packs/skill-registry@1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"schemaVersion": 1,
"id": "skill-registry@1",
"inventory": {
"source": "manifests/install-modules.json",
"skillsRoot": "skills"
},
"overrides": []
}
12 changes: 12 additions & 0 deletions manifests/context-profiles/full@1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"schemaVersion": 1,
"id": "full@1",
"description": "Proposed complete canonical skill discovery projection. Agents, commands, rules, hooks and tool schemas remain outside this projection; native activation is unobserved.",
"registryId": "skill-registry@1",
"selection": {
"eager": "all",
"required": ["skill:configure-ecc", "skill:context-budget", "skill:ecc-guide"],
"remainder": "routed"
},
"budget": { "tokens": 8000, "mode": "report-only" }
}
12 changes: 12 additions & 0 deletions manifests/context-profiles/lean@1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"schemaVersion": 1,
"id": "lean@1",
"description": "Proposed three-skill ECC discovery kernel. Remaining skills are routed; this profile does not activate or modify a harness.",
"registryId": "skill-registry@1",
"selection": {
"eager": ["skill:configure-ecc", "skill:context-budget", "skill:ecc-guide"],
"required": ["skill:configure-ecc", "skill:context-budget", "skill:ecc-guide"],
"remainder": "routed"
},
"budget": { "tokens": 8000, "mode": "blocking" }
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"docs/CODEX-NAVIGATION-GUIDE.md",
"docs/COMMAND-AGENT-MAP.md",
"docs/design/ecc-memory-vault.md",
"docs/design/context-profiles.md",
"docs/ja-JP/",
"docs/ko-KR/",
"docs/pt-BR/",
Expand All @@ -92,6 +93,7 @@
"scripts/ci/scan-supply-chain-iocs.js",
"scripts/ci/supply-chain-advisory-sources.js",
"scripts/consult.js",
"scripts/profile.js",
"scripts/auto-update.js",
"scripts/claw.js",
"scripts/control-pane.js",
Expand Down Expand Up @@ -447,6 +449,7 @@
"scripts": {
"welcome": "echo '\\n ecc-universal installed!\\n Run: ecc typescript\\n Compat: ecc-install typescript\\n Docs: https://github.com/affaan-m/ECC\\n Run or self-host any open-source model.\\n Compute: Itô is the preferred compute sponsor — https://compute.itomarkets.com\\n Any GPU provider works. This sponsorship link is passive: it does not invoke an RFQ, reserve capacity, provision compute, or configure serving.\\n Separately, the opt-in ecc ito find bridge invokes the explicitly configured canonical Itô CLI and submits a live authenticated RFQ; it does not reserve capacity.\\n Managed inference through Itô is not live yet.\\n'",
"catalog:check": "node scripts/ci/catalog.js --text",
"context-profiles:check": "node scripts/ci/validate-context-profiles.js",
"catalog:sync": "node scripts/ci/catalog.js --write --text",
"command-registry:generate": "node scripts/ci/generate-command-registry.js",
"command-registry:write": "node scripts/ci/generate-command-registry.js --write",
Expand All @@ -469,7 +472,7 @@
"orchestrate:status": "node scripts/orchestration-status.js",
"orchestrate:worker": "bash scripts/orchestrate-codex-worker.sh",
"orchestrate:tmux": "node scripts/orchestrate-worktrees.js",
"test": "node scripts/ci/check-unicode-safety.js && node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-rules.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-install-manifests.js && node scripts/ci/validate-no-personal-paths.js && npm run catalog:check && npm run command-registry:check && node tests/run-all.js",
"test": "node scripts/ci/check-unicode-safety.js && node scripts/ci/validate-agents.js && node scripts/ci/validate-commands.js && node scripts/ci/validate-rules.js && node scripts/ci/validate-skills.js && node scripts/ci/validate-hooks.js && node scripts/ci/validate-install-manifests.js && node scripts/ci/validate-context-profiles.js && node scripts/ci/validate-no-personal-paths.js && npm run catalog:check && npm run command-registry:check && node tests/run-all.js",
"coverage": "c8 --all --include=\"scripts/**/*.js\" --include=\"scripts/**/*.mjs\" --check-coverage --lines 80 --functions 80 --branches 79 --statements 80 --reporter=text --reporter=lcov node tests/run-all.js",
"build:opencode": "node scripts/build-opencode.js",
"prepack": "npm run build:opencode",
Expand All @@ -479,7 +482,7 @@
"dependencies": {
"@iarna/toml": "2.2.5",
"ajv": "8.20.0",
"js-yaml": "4.3.1",
"js-yaml": "4.3.2",
"sql.js": "1.14.2"
},
"pi": {
Expand Down Expand Up @@ -509,13 +512,13 @@
"overrides": {
"fast-uri": "3.1.7",
"markdown-it": "14.3.0",
"js-yaml": "4.3.1",
"js-yaml": "4.3.2",
"@humanfs/node": "0.16.8"
},
"resolutions": {
"fast-uri": "3.1.7",
"markdown-it": "14.3.0",
"js-yaml": "4.3.1",
"js-yaml": "4.3.2",
"@humanfs/node": "0.16.8"
},
"packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c"
Expand Down
42 changes: 42 additions & 0 deletions schemas/context-pack-registry.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ECC context registry declaration",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "id", "inventory", "overrides"],
"properties": {
"schemaVersion": { "const": 1 },
"id": { "const": "skill-registry@1" },
"inventory": {
"type": "object",
"additionalProperties": false,
"required": ["source", "skillsRoot"],
"properties": {
"source": { "const": "manifests/install-modules.json" },
"skillsRoot": { "const": "skills" }
}
},
"overrides": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id"],
"properties": {
"id": { "$ref": "#/definitions/skillId" },
"dependencies": {
"type": "array", "uniqueItems": true,
"items": { "$ref": "#/definitions/skillId" }
},
"requiredResources": {
"type": "array", "uniqueItems": true,
"items": { "type": "string", "minLength": 1, "maxLength": 4096 }
}
}
}
}
},
"definitions": {
"skillId": { "type": "string", "pattern": "^skill:[a-z0-9]+(?:-[a-z0-9]+)*$" }
}
}
36 changes: 36 additions & 0 deletions schemas/context-profile.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ECC read-only context profile",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "id", "description", "registryId", "selection", "budget"],
"properties": {
"schemaVersion": { "const": 1 },
"id": { "enum": ["lean@1", "full@1"] },
"description": { "type": "string", "minLength": 1, "maxLength": 2000 },
"registryId": { "const": "skill-registry@1" },
"selection": {
"type": "object", "additionalProperties": false,
"required": ["eager", "required", "remainder"],
"properties": {
"eager": { "oneOf": [{ "const": "all" }, { "$ref": "#/definitions/skillIds" }] },
"required": { "$ref": "#/definitions/skillIds" },
"remainder": { "const": "routed" }
}
},
"budget": {
"type": "object", "additionalProperties": false,
"required": ["tokens", "mode"],
"properties": {
"tokens": { "const": 8000 },
"mode": { "enum": ["blocking", "report-only"] }
}
}
},
"definitions": {
"skillIds": {
"type": "array", "uniqueItems": true,
"items": { "type": "string", "pattern": "^skill:[a-z0-9]+(?:-[a-z0-9]+)*$" }
}
}
}
Loading
Loading