diff --git a/package.json b/package.json index ef295130..0cf2e218 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "scripts": { "build": "tsc -p tsconfig.json", "check": "tsc -p tsconfig.json --noEmit", - "test": "node --test --test-concurrency=4 dist/test/*.test.js", + "test": "T2C_USE_SUBLLM=false node --test --test-concurrency=4 dist/test/*.test.js", "verify:no-llm": "node scripts/verify-no-llm-imports.mjs", "verify:modules": "node scripts/verify-module-boundaries.mjs", "verify:env": "node scripts/verify-env-contract.mjs", diff --git a/project/TICKETS.md b/project/TICKETS.md index 1ee40406..73ca3a8e 100644 --- a/project/TICKETS.md +++ b/project/TICKETS.md @@ -62,4 +62,6 @@ of `project/README.md`, which remains a generated technical-analysis artifact. | **ticket-084** | [`README.md`](./ticket-084/README.md) | [`preprompt.md`](./ticket-084/preprompt.md) | - | [`ai-codex.md`](./ticket-084/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-084/ai-codex-logs.txt) | [`changelog.md`](./ticket-084/changelog.md) | | **ticket-085** | [`README.md`](./ticket-085/README.md) | [`preprompt.md`](./ticket-085/preprompt.md) | - | [`ai-codex.md`](./ticket-085/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-085/ai-codex-logs.txt) | [`changelog.md`](./ticket-085/changelog.md) | | **ticket-087** | [`README.md`](./ticket-087/README.md) | [`preprompt.md`](./ticket-087/preprompt.md) | - | [`ai-codex.md`](./ticket-087/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-087/ai-codex-logs.txt) | [`changelog.md`](./ticket-087/changelog.md) | +| **ticket-088** | [`README.md`](./ticket-088/README.md) | [`preprompt.md`](./ticket-088/preprompt.md) | - | [`ai-codex.md`](./ticket-088/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-088/ai-codex-logs.txt) | [`changelog.md`](./ticket-088/changelog.md) | +| **ticket-089** | [`README.md`](./ticket-089/README.md) | [`preprompt.md`](./ticket-089/preprompt.md) | - | [`ai-codex.md`](./ticket-089/ai-codex.md) | [`ai-codex-logs.txt`](./ticket-089/ai-codex-logs.txt) | [`changelog.md`](./ticket-089/changelog.md) | diff --git a/project/ticket-089/README.md b/project/ticket-089/README.md new file mode 100644 index 00000000..4ae006fc --- /dev/null +++ b/project/ticket-089/README.md @@ -0,0 +1,27 @@ +# Ticket 089: Use public SubLLM direct Z.AI GLM 5.3 + +- **ID**: ticket-089 +- **Owner**: founder +- **Status**: ACTIVE +- **Workflow state**: PUBLICATION +- **Created**: 2026-08-26 + +## Goal and scope + +Make the public `subactor/subllm` policy the default route for every semantic +LLM request. The central policy selects direct Z.AI GLM 5.3. Keep the legacy +OpenRouter path only behind an explicit `T2C_USE_SUBLLM=false` compatibility +override; never silently bypass a requested or default SubLLM route. + +## Acceptance criteria + +- [x] AC-01: Scope is explicitly approved by the Founder in the originating request. +- [x] AC-02: SubLLM is enabled when no routing environment variable is set. +- [x] AC-03: The resolved direct Z.AI route uses `glm-5.3` and the public Todo2code repository URL. +- [x] AC-04: `T2C_USE_SUBLLM=false` remains the only explicit compatibility opt-out. +- [x] AC-05: The repository verification suite passes (429 passed, 1 skipped, 0 failed). + +## Participants + +- Human participant: Founder approval captured in the originating request; no user-* file was created. +- Agent participant: [ai-codex.md](ai-codex.md) diff --git a/project/ticket-089/ai-codex-logs.txt b/project/ticket-089/ai-codex-logs.txt new file mode 100644 index 00000000..e69de29b diff --git a/project/ticket-089/ai-codex.md b/project/ticket-089/ai-codex.md new file mode 100644 index 00000000..32e46d93 --- /dev/null +++ b/project/ticket-089/ai-codex.md @@ -0,0 +1,31 @@ +--- +participant-id: agent:codex +participant: codex +role: agent +ticket: ticket-089 +--- +# Participant: codex (AI agent) + +## Understanding + +The existing bridge already resolves and executes public SubLLM routes, but it +only activates automatically when local SubLLM-specific environment variables +or a sibling source checkout are present. Ordinary installations therefore +silently continue through the legacy OpenRouter transport. + +## Execution plan + +1. Make SubLLM the default routing policy while preserving explicit opt-out. +2. Update the direct Z.AI fixture to GLM 5.3 and the canonical repository URL. +3. Run the repository verification suite and publish through the governed PR flow. + +## Actual changes + +- Changed semantic LLM routing to SubLLM-by-default. +- Preserved `T2C_USE_SUBLLM=false` for explicit compatibility and isolated legacy unit fixtures. +- Updated the central-route contract fixture from GLM 5.2 to direct Z.AI GLM 5.3. +- Verified TypeScript, module boundaries, environment/workflow contracts, generated schemas and 430 tests (429 passed, 1 skipped, 0 failed). + +## Blockers + +- None. diff --git a/project/ticket-089/changelog.md b/project/ticket-089/changelog.md new file mode 100644 index 00000000..4ee67852 --- /dev/null +++ b/project/ticket-089/changelog.md @@ -0,0 +1,11 @@ +# Ticket Changelog (ticket-089) + +## [0.1.0] - 2026-08-26 + +- Initial governance scaffold created. +- No human participant identity or content was generated. +# Changelog + +- Default semantic LLM requests to the public `subactor/subllm` policy. +- Expect the direct Z.AI `glm-5.3` route and canonical `autogrammar/todo2code` provenance. +- Retain legacy OpenRouter behavior only through explicit `T2C_USE_SUBLLM=false`. diff --git a/project/ticket-089/intent.json b/project/ticket-089/intent.json new file mode 100644 index 00000000..b1e400c6 --- /dev/null +++ b/project/ticket-089/intent.json @@ -0,0 +1,25 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-089", + "summary": "Use public SubLLM direct Z.AI GLM 5.3", + "workstream": "llm", + "classification": { + "kind": "SERVICE", + "priority": "P2", + "origin": "health" + }, + "allowedPaths": [ + "src/llm/subllm.ts", + "test/helpers.ts", + "test/cli-summary.test.ts", + "test/subllm.test.ts", + "project/ticket-089/**", + "TODO.md", + "project/TICKETS.md" + ], + "forbiddenPaths": ["project/ticket-*/user-*.md"], + "stacks": ["typescript", "node", "subllm", "zai"], + "dependsOn": [], + "conflictsWith": [], + "integrationTicket": "ticket-090" +} diff --git a/project/ticket-089/preprompt.md b/project/ticket-089/preprompt.md new file mode 100644 index 00000000..621c40f1 --- /dev/null +++ b/project/ticket-089/preprompt.md @@ -0,0 +1,8 @@ +# Ticket preprompt + +- **Task ID**: ticket-089 +- **Task title**: Use public SubLLM direct Z.AI GLM 5.3 +- **Created**: 2026-08-26T06:07:17Z + +Keep executable implementation outside this governance/evidence directory. +Read a human-owned user-*.md file only when one exists. diff --git a/project/ticket-090/README.md b/project/ticket-090/README.md new file mode 100644 index 00000000..6c9e6a36 --- /dev/null +++ b/project/ticket-090/README.md @@ -0,0 +1,30 @@ +# Ticket 090: Hermetic test routing for SubLLM default + +- **ID**: ticket-090 +- **Owner**: founder +- **Status**: ACTIVE +- **Workflow state**: PUBLICATION +- **Created**: 2026-08-26 + +## Goal and scope + +Keep the unit and gold-evaluation suites deterministic after ticket-089 makes +SubLLM the production default. The test command must explicitly select the +legacy fixture transport, while SubLLM bridge tests opt in independently and +continue to exercise direct Z.AI GLM 5.3. + +The Founder explicitly authorized continuation and repair. `--force-new` was +used because stale ticket-054 still reserves the integration workstream in its +publication phase but has no open pull request. + +## Acceptance criteria + +- [x] AC-01: Scope is approved by the Founder in the originating request. +- [x] AC-02: `npm test` has a hermetic `T2C_USE_SUBLLM=false` environment. +- [x] AC-03: SubLLM bridge tests explicitly opt in and still verify direct Z.AI GLM 5.3. +- [x] AC-04: Full local Node 22 verification passes (429 passed, 1 skipped, 0 failed); hosted verification is publication evidence. + +## Participants + +- Human participant: Founder approval captured in the originating request; no user-* file was created. +- Agent participant: [ai-antigravity.md](ai-antigravity.md) diff --git a/project/ticket-090/ai-antigravity-logs.txt b/project/ticket-090/ai-antigravity-logs.txt new file mode 100644 index 00000000..e69de29b diff --git a/project/ticket-090/ai-antigravity.md b/project/ticket-090/ai-antigravity.md new file mode 100644 index 00000000..8cda0816 --- /dev/null +++ b/project/ticket-090/ai-antigravity.md @@ -0,0 +1,29 @@ +--- +participant-id: agent:antigravity +participant: antigravity +role: agent +ticket: ticket-090 +--- +# Participant: antigravity (AI agent) + +## Understanding + +Ticket-089 intentionally changes the production default to SubLLM. The test +runner currently inherits that default and therefore allows ambient runner +credentials to alter offline gold-evaluation results. + +## Execution plan + +1. Pin the test process to the explicit legacy compatibility route. +2. Remove ambient test-helper mutation. +3. Re-run the complete repository verification and hosted checks. + +## Actual changes + +- Made the test command explicitly hermetic with `T2C_USE_SUBLLM=false`. +- Kept production and explicit SubLLM bridge tests unchanged. +- Verified the complete suite on Node 22: 429 passed, 1 skipped, 0 failed. + +## Blockers + +- None. diff --git a/project/ticket-090/changelog.md b/project/ticket-090/changelog.md new file mode 100644 index 00000000..c793d115 --- /dev/null +++ b/project/ticket-090/changelog.md @@ -0,0 +1,10 @@ +# Ticket Changelog (ticket-090) + +## [0.1.0] - 2026-08-26 + +- Initial governance scaffold created. +- No human participant identity or content was generated. +# Changelog + +- Isolate offline and unit tests from ambient SubLLM credentials. +- Preserve explicit direct Z.AI GLM 5.3 bridge coverage. diff --git a/project/ticket-090/intent.json b/project/ticket-090/intent.json new file mode 100644 index 00000000..f5977cb6 --- /dev/null +++ b/project/ticket-090/intent.json @@ -0,0 +1,17 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-090", + "summary": "Hermetic test routing for SubLLM default", + "workstream": "integration", + "classification": { + "kind": "SERVICE", + "priority": "P1", + "origin": "health" + }, + "allowedPaths": ["package.json", "project/ticket-090/**", "TODO.md", "project/TICKETS.md"], + "forbiddenPaths": ["project/ticket-*/user-*.md"], + "stacks": ["node", "typescript", "subllm", "ci"], + "dependsOn": ["ticket-089"], + "conflictsWith": [], + "integrationTicket": "ticket-090" +} diff --git a/project/ticket-090/preprompt.md b/project/ticket-090/preprompt.md new file mode 100644 index 00000000..5c25d9f9 --- /dev/null +++ b/project/ticket-090/preprompt.md @@ -0,0 +1,8 @@ +# Ticket preprompt + +- **Task ID**: ticket-090 +- **Task title**: Hermetic test routing for SubLLM default +- **Created**: 2026-08-26T06:20:04Z + +Keep executable implementation outside this governance/evidence directory. +Read a human-owned user-*.md file only when one exists. diff --git a/src/llm/subllm.ts b/src/llm/subllm.ts index 25ccdc0b..017b688f 100644 --- a/src/llm/subllm.ts +++ b/src/llm/subllm.ts @@ -38,7 +38,7 @@ export function lastResolvedSubllmRoute(): SubllmPublicRoute | null { export function shouldUseSubllm( environment: NodeJS.ProcessEnv = process.env, - cwd = process.cwd(), + _cwd = process.cwd(), ): boolean { const explicit = environment.T2C_USE_SUBLLM?.trim().toLowerCase(); if (explicit && FALSE_VALUES.has(explicit)) return false; @@ -49,7 +49,7 @@ export function shouldUseSubllm( if (environment.SUBLLM_ENV_FILE || environment.SUBLLM_POLICY_FILE || environment.SUBLLM_PYTHONPATH) { return true; } - return Boolean(localSubllmPythonPath(cwd)); + return true; } export async function resolveSubllmRoute( diff --git a/test/cli-summary.test.ts b/test/cli-summary.test.ts index 3923f640..ee744b61 100644 --- a/test/cli-summary.test.ts +++ b/test/cli-summary.test.ts @@ -23,7 +23,12 @@ test('CLI summarize exposes deterministic, prefer-llm and require-llm modes', as const diagnostics = diagnoseGraph(graph, '2026-07-30T00:00:00.000Z'); await fs.writeFile(path.join(root, 'graph.json'), `${JSON.stringify(graph)}\n`, 'utf8'); await fs.writeFile(path.join(root, 'diagnostics.json'), `${JSON.stringify(diagnostics)}\n`, 'utf8'); - const environment = { ...process.env, OPENROUTER_API_KEY: '', T2C_ENV_FILE: 'missing.env' }; + const environment = { + ...process.env, + OPENROUTER_API_KEY: '', + T2C_ENV_FILE: 'missing.env', + T2C_USE_SUBLLM: 'false', + }; const base = ['summarize', 'graph.json', '--diagnostics', 'diagnostics.json']; const deterministic = await exec(process.execPath, [cli, ...base, '--mode', 'deterministic'], { diff --git a/test/subllm.test.ts b/test/subllm.test.ts index e2efd4a7..77a52d4a 100644 --- a/test/subllm.test.ts +++ b/test/subllm.test.ts @@ -34,15 +34,15 @@ if args[:3] == ["resolve", "todo2code", "semantic"]: print(json.dumps({ "application": "todo2code", "application_name": "todo2code", - "application_url": "https://github.com/semcod/todo2code", + "application_url": "https://github.com/autogrammar/todo2code", "function": "semantic", "provider": "zai", - "model": "glm-5.2", - "priority": 10, + "model": "glm-5.3", + "priority": 0, "api_base": "https://api.z.ai/api/coding/paas/v4", "api_key_env": "ZAI_API_KEY", - "litellm_model": "zai/glm-5.2", - "wire_model": "glm-5.2", + "litellm_model": "zai/glm-5.3", + "wire_model": "glm-5.3", "extra_headers": {}, })) elif args == ["env", "path"]: @@ -92,7 +92,7 @@ test('SubLLM bridge resolves the selected central route without command-shell in assert.equal(shouldUseSubllm(), true); const resolved = await resolveSubllmRoute(); assert.equal(resolved.route.provider, 'zai'); - assert.equal(resolved.route.wire_model, 'glm-5.2'); + assert.equal(resolved.route.wire_model, 'glm-5.3'); assert.equal(resolved.route.application, 'todo2code'); assert.equal(resolved.credential, FIXTURE_CREDENTIAL); assert.equal(JSON.stringify(resolved.route).includes('fixture-value'), false); @@ -116,7 +116,7 @@ test('todo2code sends structured semantic requests through direct Z.AI resolved return new Response(JSON.stringify({ id: 'zai-fixture-response', request_id: body.request_id, - model: 'glm-5.2', + model: 'glm-5.3', usage: { prompt_tokens: 12, completion_tokens: 4, total_tokens: 16 }, choices: [{ message: { content: responseContent } }], }), { status: 200, headers: { 'Content-Type': 'application/json' } }); @@ -131,13 +131,13 @@ test('todo2code sends structured semantic requests through direct Z.AI resolved ); assert.deepEqual(result.value, { ok: true }); - assert.equal(result.metadata.model, 'glm-5.2'); + assert.equal(result.metadata.model, 'glm-5.3'); assert.equal(result.metadata.provider, 'zai'); assert.equal(url, 'https://api.z.ai/api/coding/paas/v4/chat/completions'); assert.equal(headers.Authorization, `Bearer ${FIXTURE_CREDENTIAL}`); assert.equal(headers['X-OpenRouter-Title'], undefined); assert.equal(headers['HTTP-Referer'], undefined); - assert.equal(body.model, 'glm-5.2'); + assert.equal(body.model, 'glm-5.3'); assert.equal(body.user_id, 'todo2code'); assert.match(String(body.request_id), /^todo2code-semantic-[0-9a-f]{32}$/u); assert.deepEqual(body.response_format, { type: 'json_object' }); @@ -154,9 +154,9 @@ test('todo2code sends structured semantic requests through direct Z.AI resolved application: 'todo2code', function: 'semantic', provider: 'zai', - model: 'glm-5.2', - wireModel: 'glm-5.2', - priority: 10, + model: 'glm-5.3', + wireModel: 'glm-5.3', + priority: 0, apiBase: 'https://api.z.ai/api/coding/paas/v4', }); assert.equal(JSON.stringify(audit).includes('fixture-value'), false); @@ -174,6 +174,12 @@ test('todo2code sends structured semantic requests through direct Z.AI resolved } }); +test('SubLLM is the default semantic route and legacy OpenRouter requires an explicit opt-out', () => { + assert.equal(shouldUseSubllm({}), true); + assert.equal(shouldUseSubllm({ T2C_USE_SUBLLM: 'true' }), true); + assert.equal(shouldUseSubllm({ T2C_USE_SUBLLM: 'false' }), false); +}); + test('explicitly requested SubLLM fails closed when its package is unavailable', async () => { const previousUse = process.env.T2C_USE_SUBLLM; const previousPath = process.env.SUBLLM_PYTHONPATH;