onto-mcp 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.onto/processes/reconstruct/actionable-ontology-seed-recomposition-design.md +447 -0
- package/.onto/processes/reconstruct/foundry-style-ontology-seed-contract.md +934 -0
- package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +303 -725
- package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +1645 -0
- package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +26 -22
- package/.onto/processes/reconstruct/source-profile-contract.md +49 -23
- package/.onto/processes/reconstruct/source-profiles/code.md +6 -3
- package/.onto/processes/reconstruct/source-profiles/database.md +5 -2
- package/.onto/processes/reconstruct/source-profiles/document.md +5 -2
- package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +5 -4
- package/.onto/processes/review/review-execution-ux-contract.md +40 -0
- package/.onto/processes/shared/pipeline-execution-ledger-contract.md +26 -10
- package/.onto/processes/shared/target-material-kind-contract.md +29 -16
- package/AGENTS.md +6 -4
- package/README.md +149 -76
- package/dist/cli.js +8 -8
- package/dist/core-api/reconstruct-api.js +117 -31
- package/dist/core-api/review-api.js +47 -0
- package/dist/core-runtime/cli/codex-review-unit-executor.js +39 -2
- package/dist/core-runtime/cli/complete-review-session.js +2 -2
- package/dist/core-runtime/cli/mock-review-unit-executor.js +1 -1
- package/dist/core-runtime/cli/review-invoke.js +9 -9
- package/dist/core-runtime/cli/run-review-prompt-execution.js +39 -5
- package/dist/core-runtime/cli/spawn-watcher.js +266 -47
- package/dist/core-runtime/cli/start-review-session.js +3 -3
- package/dist/core-runtime/llm/llm-caller.js +11 -0
- package/dist/core-runtime/llm/llm-tool-loop.js +2 -0
- package/dist/core-runtime/observability/runtime-stream-observation.js +118 -0
- package/dist/core-runtime/onboard/cli-host.js +174 -0
- package/dist/core-runtime/onboard/host-target.js +22 -0
- package/dist/core-runtime/onboard/json-config-host.js +122 -0
- package/dist/core-runtime/onboard/path-scan.js +26 -0
- package/dist/core-runtime/onboard/prompt.js +51 -0
- package/dist/core-runtime/onboard/register.js +214 -0
- package/dist/core-runtime/onboard/types.js +27 -0
- package/dist/core-runtime/reconstruct/actionable-seed-validation.js +1777 -0
- package/dist/core-runtime/reconstruct/artifact-types.js +10 -4
- package/dist/core-runtime/reconstruct/contract-registry.js +623 -0
- package/dist/core-runtime/reconstruct/domain-id.js +10 -0
- package/dist/core-runtime/reconstruct/governing-snapshot.js +716 -0
- package/dist/core-runtime/reconstruct/material-profile-validation.js +191 -0
- package/dist/core-runtime/reconstruct/materialize-preparation.js +49 -11
- package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +269 -79
- package/dist/core-runtime/reconstruct/post-seed-validation.js +1194 -51
- package/dist/core-runtime/reconstruct/record.js +104 -20
- package/dist/core-runtime/reconstruct/run.js +2107 -413
- package/dist/core-runtime/reconstruct/seed-claim-projections.js +268 -0
- package/dist/core-runtime/reconstruct/source-profiles.js +93 -4
- package/dist/core-runtime/reconstruct/terminal-validation.js +807 -0
- package/dist/core-runtime/review/review-invocation-runner.js +4 -4
- package/dist/mcp/server.js +110 -38
- package/dist/mcp/tool-schemas.js +20 -6
- package/package.json +8 -17
- package/scripts/onto-review-watch.sh +486 -0
- package/scripts/onto-runtime-watch.sh +122 -0
- package/scripts/postinstall-hint.js +22 -0
- package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +0 -387
- package/dist/core-runtime/cli/bootstrap-review-binding.js +0 -186
- package/dist/core-runtime/cli/codex-nested-dispatch.test.js +0 -390
- package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +0 -335
- package/dist/core-runtime/cli/coordinator-helpers.js +0 -583
- package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +0 -167
- package/dist/core-runtime/cli/coordinator-state-machine.js +0 -794
- package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +0 -615
- package/dist/core-runtime/cli/e2e-start-review-session.test.js +0 -312
- package/dist/core-runtime/cli/health.js +0 -44
- package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +0 -567
- package/dist/core-runtime/cli/materialize-review-execution-preparation.js +0 -104
- package/dist/core-runtime/cli/migrate-session-roots.js +0 -118
- package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +0 -106
- package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +0 -268
- package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +0 -136
- package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +0 -201
- package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +0 -192
- package/dist/core-runtime/cli/session-root-guard.js +0 -168
- package/dist/core-runtime/cli/spawn-watcher.test.js +0 -457
- package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +0 -79
- package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +0 -412
- package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +0 -351
- package/dist/core-runtime/cli/topology-executor-mapping.js +0 -139
- package/dist/core-runtime/cli/topology-executor-mapping.test.js +0 -173
- package/dist/core-runtime/cli/write-review-interpretation.js +0 -81
- package/dist/core-runtime/config/onto-config-cli.js +0 -278
- package/dist/core-runtime/config/onto-config-key-path.js +0 -288
- package/dist/core-runtime/config/onto-config-key-path.test.js +0 -195
- package/dist/core-runtime/config/onto-config-preview.js +0 -108
- package/dist/core-runtime/config/onto-config-preview.test.js +0 -132
- package/dist/core-runtime/discovery/config-chain.js +0 -118
- package/dist/core-runtime/discovery/config-chain.test.js +0 -103
- package/dist/core-runtime/discovery/config-profile.js +0 -199
- package/dist/core-runtime/discovery/config-profile.test.js +0 -233
- package/dist/core-runtime/discovery/host-detection.test.js +0 -186
- package/dist/core-runtime/discovery/installation-paths.test.js +0 -65
- package/dist/core-runtime/discovery/lens-registry.test.js +0 -81
- package/dist/core-runtime/discovery/path-normalization.test.js +0 -22
- package/dist/core-runtime/discovery/plugin-path.js +0 -72
- package/dist/core-runtime/discovery/plugin-path.test.js +0 -95
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +0 -344
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +0 -915
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +0 -564
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +0 -708
- package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +0 -165
- package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +0 -227
- package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +0 -59
- package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +0 -205
- package/dist/core-runtime/evolve/adapters/methodology/adapter.js +0 -16
- package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +0 -9
- package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +0 -298
- package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +0 -70
- package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +0 -46
- package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +0 -73
- package/dist/core-runtime/evolve/adapters/registry.js +0 -47
- package/dist/core-runtime/evolve/adapters/registry.test.js +0 -67
- package/dist/core-runtime/evolve/cli.js +0 -256
- package/dist/core-runtime/evolve/commands/align.js +0 -194
- package/dist/core-runtime/evolve/commands/align.test.js +0 -82
- package/dist/core-runtime/evolve/commands/apply.js +0 -161
- package/dist/core-runtime/evolve/commands/apply.test.js +0 -138
- package/dist/core-runtime/evolve/commands/close.js +0 -39
- package/dist/core-runtime/evolve/commands/close.test.js +0 -99
- package/dist/core-runtime/evolve/commands/defer.js +0 -40
- package/dist/core-runtime/evolve/commands/defer.test.js +0 -134
- package/dist/core-runtime/evolve/commands/draft.js +0 -323
- package/dist/core-runtime/evolve/commands/draft.test.js +0 -178
- package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +0 -208
- package/dist/core-runtime/evolve/commands/error-messages.js +0 -125
- package/dist/core-runtime/evolve/commands/error-messages.test.js +0 -167
- package/dist/core-runtime/evolve/commands/propose-align.js +0 -222
- package/dist/core-runtime/evolve/commands/propose-align.test.js +0 -136
- package/dist/core-runtime/evolve/commands/reconstruct.js +0 -330
- package/dist/core-runtime/evolve/commands/reconstruct.test.js +0 -278
- package/dist/core-runtime/evolve/commands/shared.js +0 -22
- package/dist/core-runtime/evolve/commands/stale-check.js +0 -103
- package/dist/core-runtime/evolve/commands/stale-check.test.js +0 -84
- package/dist/core-runtime/evolve/commands/start.js +0 -887
- package/dist/core-runtime/evolve/commands/start.test.js +0 -396
- package/dist/core-runtime/evolve/config/project-config.js +0 -99
- package/dist/core-runtime/evolve/config/project-config.test.js +0 -170
- package/dist/core-runtime/evolve/renderers/align-packet.js +0 -280
- package/dist/core-runtime/evolve/renderers/align-packet.test.js +0 -332
- package/dist/core-runtime/evolve/renderers/draft-packet.js +0 -303
- package/dist/core-runtime/evolve/renderers/draft-packet.test.js +0 -377
- package/dist/core-runtime/evolve/renderers/format.js +0 -5
- package/dist/core-runtime/evolve/renderers/scope-md.js +0 -237
- package/dist/core-runtime/evolve/renderers/scope-md.test.js +0 -306
- package/dist/core-runtime/govern/cli.js +0 -369
- package/dist/core-runtime/govern/cli.test.js +0 -314
- package/dist/core-runtime/govern/drift-engine.js +0 -103
- package/dist/core-runtime/govern/drift-engine.test.js +0 -319
- package/dist/core-runtime/govern/promote-principle.js +0 -206
- package/dist/core-runtime/govern/promote-principle.test.js +0 -368
- package/dist/core-runtime/govern/queue.js +0 -81
- package/dist/core-runtime/govern/types.js +0 -16
- package/dist/core-runtime/install/cli.js +0 -530
- package/dist/core-runtime/install/detect.js +0 -128
- package/dist/core-runtime/install/detect.test.js +0 -155
- package/dist/core-runtime/install/gitignore-update.js +0 -74
- package/dist/core-runtime/install/gitignore-update.test.js +0 -64
- package/dist/core-runtime/install/install-integration.test.js +0 -373
- package/dist/core-runtime/install/prompts.js +0 -389
- package/dist/core-runtime/install/prompts.test.js +0 -293
- package/dist/core-runtime/install/types.js +0 -26
- package/dist/core-runtime/install/validation.js +0 -295
- package/dist/core-runtime/install/validation.test.js +0 -313
- package/dist/core-runtime/install/writer.js +0 -254
- package/dist/core-runtime/install/writer.test.js +0 -218
- package/dist/core-runtime/learning/extractor.js +0 -461
- package/dist/core-runtime/learning/feedback.js +0 -179
- package/dist/core-runtime/learning/health-report.js +0 -165
- package/dist/core-runtime/learning/health-report.test.js +0 -169
- package/dist/core-runtime/learning/loader.js +0 -388
- package/dist/core-runtime/learning/loader.test.js +0 -102
- package/dist/core-runtime/learning/promote/apply-state.js +0 -240
- package/dist/core-runtime/learning/promote/audit-obligation.js +0 -195
- package/dist/core-runtime/learning/promote/collector.js +0 -432
- package/dist/core-runtime/learning/promote/degraded-state.js +0 -125
- package/dist/core-runtime/learning/promote/domain-doc-proposer.js +0 -166
- package/dist/core-runtime/learning/promote/e2e-promote.test.js +0 -6385
- package/dist/core-runtime/learning/promote/health-snapshot.js +0 -150
- package/dist/core-runtime/learning/promote/insight-reclassifier.js +0 -544
- package/dist/core-runtime/learning/promote/judgment-auditor.js +0 -517
- package/dist/core-runtime/learning/promote/panel-reviewer.js +0 -1158
- package/dist/core-runtime/learning/promote/promote-executor.js +0 -1675
- package/dist/core-runtime/learning/promote/promoter.js +0 -307
- package/dist/core-runtime/learning/promote/retirement.js +0 -122
- package/dist/core-runtime/learning/promote/types.js +0 -23
- package/dist/core-runtime/learning/prompt-sections.js +0 -51
- package/dist/core-runtime/learning/shared/artifact-registry-init.js +0 -45
- package/dist/core-runtime/learning/shared/artifact-registry.js +0 -254
- package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +0 -73
- package/dist/core-runtime/learning/shared/audit-state.js +0 -99
- package/dist/core-runtime/learning/shared/duplicate-check.js +0 -28
- package/dist/core-runtime/learning/shared/llm-caller.js +0 -831
- package/dist/core-runtime/learning/shared/llm-caller.test.js +0 -601
- package/dist/core-runtime/learning/shared/llm-tool-loop.js +0 -393
- package/dist/core-runtime/learning/shared/mode.js +0 -25
- package/dist/core-runtime/learning/shared/paths.js +0 -84
- package/dist/core-runtime/learning/shared/paths.test.js +0 -79
- package/dist/core-runtime/learning/shared/patterns.js +0 -37
- package/dist/core-runtime/learning/shared/recoverability.js +0 -355
- package/dist/core-runtime/learning/shared/recovery-context.js +0 -374
- package/dist/core-runtime/learning/shared/scope.js +0 -1
- package/dist/core-runtime/learning/shared/semantic-classifier.js +0 -94
- package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +0 -42
- package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +0 -37
- package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +0 -39
- package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +0 -41
- package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +0 -38
- package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +0 -43
- package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +0 -113
- package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +0 -36
- package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +0 -48
- package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +0 -43
- package/dist/core-runtime/learning/shared/specs/spec-helpers.js +0 -64
- package/dist/core-runtime/learning/usage-tracker.js +0 -190
- package/dist/core-runtime/learning/usage-tracker.test.js +0 -176
- package/dist/core-runtime/onboard/detect-review-axes.js +0 -122
- package/dist/core-runtime/onboard/detect-review-axes.test.js +0 -127
- package/dist/core-runtime/onboard/write-review-block.js +0 -188
- package/dist/core-runtime/onboard/write-review-block.test.js +0 -240
- package/dist/core-runtime/readers/brownfield-builder.js +0 -150
- package/dist/core-runtime/readers/brownfield-builder.test.js +0 -136
- package/dist/core-runtime/readers/code-chunk-collector.js +0 -53
- package/dist/core-runtime/readers/code-chunk-collector.test.js +0 -136
- package/dist/core-runtime/readers/file-utils.js +0 -240
- package/dist/core-runtime/readers/file-utils.test.js +0 -146
- package/dist/core-runtime/readers/lexicon-citation-check.js +0 -93
- package/dist/core-runtime/readers/lexicon-citation-check.test.js +0 -77
- package/dist/core-runtime/readers/mcp-figma.js +0 -30
- package/dist/core-runtime/readers/mcp-figma.test.js +0 -82
- package/dist/core-runtime/readers/mcp-generic.js +0 -31
- package/dist/core-runtime/readers/mcp-generic.test.js +0 -76
- package/dist/core-runtime/readers/ontology-index.js +0 -148
- package/dist/core-runtime/readers/ontology-index.test.js +0 -245
- package/dist/core-runtime/readers/ontology-query.js +0 -168
- package/dist/core-runtime/readers/ontology-query.test.js +0 -311
- package/dist/core-runtime/readers/ontology-resolve.js +0 -48
- package/dist/core-runtime/readers/ontology-resolve.test.js +0 -48
- package/dist/core-runtime/readers/patterns/index.js +0 -7
- package/dist/core-runtime/readers/review-log.js +0 -213
- package/dist/core-runtime/readers/review-log.test.js +0 -313
- package/dist/core-runtime/readers/scan-local.js +0 -102
- package/dist/core-runtime/readers/scan-local.test.js +0 -102
- package/dist/core-runtime/readers/scan-tarball.js +0 -121
- package/dist/core-runtime/readers/scan-tarball.test.js +0 -283
- package/dist/core-runtime/readers/scan-vault.js +0 -34
- package/dist/core-runtime/readers/scan-vault.test.js +0 -81
- package/dist/core-runtime/readers/types.js +0 -42
- package/dist/core-runtime/readers/types.test.js +0 -94
- package/dist/core-runtime/readers/viewpoint-collectors.js +0 -229
- package/dist/core-runtime/reconstruct/seed-candidate-validation.js +0 -385
- package/dist/core-runtime/review/citation-audit.test.js +0 -165
- package/dist/core-runtime/review/execution-plan-resolver.js +0 -247
- package/dist/core-runtime/review/execution-plan-resolver.test.js +0 -243
- package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +0 -246
- package/dist/core-runtime/review/execution-topology-resolver.js +0 -401
- package/dist/core-runtime/review/execution-topology-resolver.test.js +0 -315
- package/dist/core-runtime/review/inline-context-embedder.test.js +0 -154
- package/dist/core-runtime/review/legacy-mode-policy.js +0 -88
- package/dist/core-runtime/review/materializers-effort-persist.test.js +0 -79
- package/dist/core-runtime/review/ontology-path-classifier.js +0 -179
- package/dist/core-runtime/review/ontology-path-classifier.test.js +0 -216
- package/dist/core-runtime/review/packet-boundary-policy.test.js +0 -107
- package/dist/core-runtime/review/participating-lens-paths.test.js +0 -73
- package/dist/core-runtime/review/review-config-legacy-translate.js +0 -244
- package/dist/core-runtime/review/review-config-legacy-translate.test.js +0 -161
- package/dist/core-runtime/review/review-config-validator.js +0 -289
- package/dist/core-runtime/review/review-config-validator.test.js +0 -236
- package/dist/core-runtime/review/shape-pipeline-audit.test.js +0 -311
- package/dist/core-runtime/review/shape-to-topology-id.js +0 -117
- package/dist/core-runtime/review/shape-to-topology-id.test.js +0 -132
- package/dist/core-runtime/review/topology-shape-derivation.js +0 -155
- package/dist/core-runtime/review/topology-shape-derivation.test.js +0 -195
- package/dist/core-runtime/scope-runtime/constants.js +0 -12
- package/dist/core-runtime/scope-runtime/constraint-pool.js +0 -166
- package/dist/core-runtime/scope-runtime/constraint-pool.test.js +0 -674
- package/dist/core-runtime/scope-runtime/domain-validation-log.js +0 -135
- package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +0 -156
- package/dist/core-runtime/scope-runtime/eval-persistence.js +0 -65
- package/dist/core-runtime/scope-runtime/eval-persistence.test.js +0 -84
- package/dist/core-runtime/scope-runtime/event-pipeline.js +0 -64
- package/dist/core-runtime/scope-runtime/event-pipeline.test.js +0 -450
- package/dist/core-runtime/scope-runtime/event-store.js +0 -39
- package/dist/core-runtime/scope-runtime/event-store.test.js +0 -95
- package/dist/core-runtime/scope-runtime/gate-guard.js +0 -348
- package/dist/core-runtime/scope-runtime/gate-guard.test.js +0 -1047
- package/dist/core-runtime/scope-runtime/hash.js +0 -4
- package/dist/core-runtime/scope-runtime/hash.test.js +0 -33
- package/dist/core-runtime/scope-runtime/id.js +0 -4
- package/dist/core-runtime/scope-runtime/id.test.js +0 -17
- package/dist/core-runtime/scope-runtime/reducer.js +0 -297
- package/dist/core-runtime/scope-runtime/reducer.test.js +0 -759
- package/dist/core-runtime/scope-runtime/scope-manager.js +0 -161
- package/dist/core-runtime/scope-runtime/state-machine.js +0 -309
- package/dist/core-runtime/scope-runtime/state-machine.test.js +0 -704
- package/dist/core-runtime/scope-runtime/types.js +0 -116
- package/dist/core-runtime/scope-runtime/types.test.js +0 -69
- package/dist/core-runtime/translate/render-for-user.js +0 -169
- package/dist/core-runtime/translate/render-for-user.test.js +0 -122
- package/dist/providers/capability-contract.js +0 -1
|
@@ -1,457 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
|
|
5
|
-
// Module-level mock of node:child_process.spawnSync. Hoisted by vitest
|
|
6
|
-
// before the spawn-watcher import below, so spawn-watcher.ts picks up
|
|
7
|
-
// the mocked binding at module-load time. The dry-run test paths in
|
|
8
|
-
// other describe blocks never call spawnSync (they short-circuit on
|
|
9
|
-
// `dry_run: true`), so the mock is inert for them.
|
|
10
|
-
vi.mock("node:child_process", async (importOriginal) => {
|
|
11
|
-
const actual = await importOriginal();
|
|
12
|
-
return {
|
|
13
|
-
...actual,
|
|
14
|
-
spawnSync: vi.fn(),
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
import { spawnSync } from "node:child_process";
|
|
18
|
-
import { spawnWatcherPane } from "./spawn-watcher.js";
|
|
19
|
-
const mockedSpawnSync = vi.mocked(spawnSync);
|
|
20
|
-
function mkProjectRoot(withWatcherScript) {
|
|
21
|
-
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), "onto-watcher-test-"));
|
|
22
|
-
const sessionRoot = path.join(projectRoot, ".onto", "review", "20260422-fixture");
|
|
23
|
-
fs.mkdirSync(sessionRoot, { recursive: true });
|
|
24
|
-
if (withWatcherScript) {
|
|
25
|
-
const scriptsDir = path.join(projectRoot, "scripts");
|
|
26
|
-
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
27
|
-
fs.writeFileSync(path.join(scriptsDir, "onto-review-watch.sh"), "#!/usr/bin/env bash\n# test fixture — no-op\n", { mode: 0o755 });
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
projectRoot,
|
|
31
|
-
sessionRoot,
|
|
32
|
-
cleanup: () => fs.rmSync(projectRoot, { recursive: true, force: true }),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
// Platform stubbing — iTerm2 / Apple Terminal branches gate on
|
|
37
|
-
// `process.platform === "darwin"`. Tests must match so they exercise
|
|
38
|
-
// the same branches regardless of the host OS running vitest.
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
function stubDarwin() {
|
|
41
|
-
const original = Object.getOwnPropertyDescriptor(process, "platform");
|
|
42
|
-
Object.defineProperty(process, "platform", {
|
|
43
|
-
value: "darwin",
|
|
44
|
-
configurable: true,
|
|
45
|
-
});
|
|
46
|
-
return () => {
|
|
47
|
-
if (original) {
|
|
48
|
-
Object.defineProperty(process, "platform", original);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// Env stubbing — save + restore the env vars `spawnWatcherPane` inspects.
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
const WATCHED_ENV_KEYS = [
|
|
56
|
-
"ONTO_WATCHER_DRY_RUN",
|
|
57
|
-
"TMUX",
|
|
58
|
-
"TMUX_PANE",
|
|
59
|
-
"TERM_PROGRAM",
|
|
60
|
-
"ITERM_SESSION_ID",
|
|
61
|
-
];
|
|
62
|
-
function saveEnv() {
|
|
63
|
-
const snapshot = {};
|
|
64
|
-
for (const key of WATCHED_ENV_KEYS) {
|
|
65
|
-
snapshot[key] = process.env[key];
|
|
66
|
-
}
|
|
67
|
-
return snapshot;
|
|
68
|
-
}
|
|
69
|
-
function clearWatchedEnv() {
|
|
70
|
-
for (const key of WATCHED_ENV_KEYS) {
|
|
71
|
-
delete process.env[key];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function restoreEnv(snapshot) {
|
|
75
|
-
for (const key of WATCHED_ENV_KEYS) {
|
|
76
|
-
const prev = snapshot[key];
|
|
77
|
-
if (prev === undefined) {
|
|
78
|
-
delete process.env[key];
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
process.env[key] = prev;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
// Tests
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
describe("spawnWatcherPane — prereq failure", () => {
|
|
89
|
-
let fixture;
|
|
90
|
-
let envSnapshot;
|
|
91
|
-
beforeEach(() => {
|
|
92
|
-
envSnapshot = saveEnv();
|
|
93
|
-
clearWatchedEnv();
|
|
94
|
-
});
|
|
95
|
-
afterEach(() => {
|
|
96
|
-
restoreEnv(envSnapshot);
|
|
97
|
-
if (fixture)
|
|
98
|
-
fixture.cleanup();
|
|
99
|
-
});
|
|
100
|
-
it("returns spawned=false when watcher script is missing", () => {
|
|
101
|
-
fixture = mkProjectRoot(false);
|
|
102
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
103
|
-
process.env.ONTO_WATCHER_DRY_RUN = "1";
|
|
104
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
105
|
-
expect(result.spawned).toBe(false);
|
|
106
|
-
expect(result.reason).toContain("watcher script not found");
|
|
107
|
-
});
|
|
108
|
-
it("returns spawned=false when no terminal multiplexer signal detected", () => {
|
|
109
|
-
fixture = mkProjectRoot(true);
|
|
110
|
-
// Every detection-priority env is unset — even dry-run cannot fake a
|
|
111
|
-
// mechanism that has no signal to match.
|
|
112
|
-
process.env.ONTO_WATCHER_DRY_RUN = "1";
|
|
113
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
114
|
-
expect(result.spawned).toBe(false);
|
|
115
|
-
expect(result.reason).toContain("no supported terminal multiplexer");
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
describe("spawnWatcherPane — ontoHome fallback", () => {
|
|
119
|
-
let projectFixture;
|
|
120
|
-
let ontoHomeFixture;
|
|
121
|
-
let envSnapshot;
|
|
122
|
-
beforeEach(() => {
|
|
123
|
-
envSnapshot = saveEnv();
|
|
124
|
-
clearWatchedEnv();
|
|
125
|
-
process.env.ONTO_WATCHER_DRY_RUN = "1";
|
|
126
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
127
|
-
});
|
|
128
|
-
afterEach(() => {
|
|
129
|
-
restoreEnv(envSnapshot);
|
|
130
|
-
if (projectFixture)
|
|
131
|
-
projectFixture.cleanup();
|
|
132
|
-
if (ontoHomeFixture)
|
|
133
|
-
ontoHomeFixture.cleanup();
|
|
134
|
-
});
|
|
135
|
-
it("finds watcher script in ontoHome when projectRoot has none", () => {
|
|
136
|
-
// Regression guard for 2026-04-22 self-review finding: scripts/review-pr.sh
|
|
137
|
-
// puts config.yml + target.diff in an isolated tmp project-root that has
|
|
138
|
-
// no scripts/ subdirectory. Without ontoHome fallback the watcher would
|
|
139
|
-
// silently degrade to `watcher script not found` and emit the manual-hint
|
|
140
|
-
// branch instead of the intended dry-run detection.
|
|
141
|
-
projectFixture = mkProjectRoot(false); // no scripts/ in project
|
|
142
|
-
ontoHomeFixture = mkProjectRoot(true); // scripts/ present here
|
|
143
|
-
const result = spawnWatcherPane(projectFixture.projectRoot, projectFixture.sessionRoot, ontoHomeFixture.projectRoot);
|
|
144
|
-
expect(result.spawned).toBe(true);
|
|
145
|
-
expect(result.mechanism).toBe("tmux");
|
|
146
|
-
});
|
|
147
|
-
it("prefers projectRoot over ontoHome when both have the script", () => {
|
|
148
|
-
projectFixture = mkProjectRoot(true);
|
|
149
|
-
ontoHomeFixture = mkProjectRoot(true);
|
|
150
|
-
const result = spawnWatcherPane(projectFixture.projectRoot, projectFixture.sessionRoot, ontoHomeFixture.projectRoot);
|
|
151
|
-
expect(result.spawned).toBe(true);
|
|
152
|
-
});
|
|
153
|
-
it("still fails when neither projectRoot nor ontoHome has the script", () => {
|
|
154
|
-
projectFixture = mkProjectRoot(false);
|
|
155
|
-
ontoHomeFixture = mkProjectRoot(false);
|
|
156
|
-
const result = spawnWatcherPane(projectFixture.projectRoot, projectFixture.sessionRoot, ontoHomeFixture.projectRoot);
|
|
157
|
-
expect(result.spawned).toBe(false);
|
|
158
|
-
expect(result.reason).toContain("watcher script not found");
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
describe("spawnWatcherPane — dry-run detection priority", () => {
|
|
162
|
-
let fixture;
|
|
163
|
-
let envSnapshot;
|
|
164
|
-
let restorePlatform;
|
|
165
|
-
beforeEach(() => {
|
|
166
|
-
envSnapshot = saveEnv();
|
|
167
|
-
clearWatchedEnv();
|
|
168
|
-
fixture = mkProjectRoot(true);
|
|
169
|
-
process.env.ONTO_WATCHER_DRY_RUN = "1";
|
|
170
|
-
// spawn-watcher's iTerm2 and Apple Terminal branches require
|
|
171
|
-
// process.platform === "darwin". Stub so the tests exercise the
|
|
172
|
-
// intended branches on any host OS.
|
|
173
|
-
restorePlatform = stubDarwin();
|
|
174
|
-
});
|
|
175
|
-
afterEach(() => {
|
|
176
|
-
restorePlatform();
|
|
177
|
-
restoreEnv(envSnapshot);
|
|
178
|
-
if (fixture)
|
|
179
|
-
fixture.cleanup();
|
|
180
|
-
});
|
|
181
|
-
it("detects tmux when $TMUX is set (priority 1)", () => {
|
|
182
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
183
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
184
|
-
expect(result.spawned).toBe(true);
|
|
185
|
-
expect(result.mechanism).toBe("tmux");
|
|
186
|
-
expect(result.dry_run).toBe(true);
|
|
187
|
-
});
|
|
188
|
-
it("detects iTerm2 when TERM_PROGRAM=iTerm.app AND ITERM_SESSION_ID is set (priority 2)", () => {
|
|
189
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
190
|
-
process.env.ITERM_SESSION_ID = "w0t0p0:ABCD1234-FAKE-UUID";
|
|
191
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
192
|
-
expect(result.spawned).toBe(true);
|
|
193
|
-
expect(result.mechanism).toBe("iterm2");
|
|
194
|
-
expect(result.dry_run).toBe(true);
|
|
195
|
-
});
|
|
196
|
-
it("detects Apple Terminal when TERM_PROGRAM=Apple_Terminal (priority 3)", () => {
|
|
197
|
-
process.env.TERM_PROGRAM = "Apple_Terminal";
|
|
198
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
199
|
-
expect(result.spawned).toBe(true);
|
|
200
|
-
expect(result.mechanism).toBe("apple_terminal");
|
|
201
|
-
expect(result.dry_run).toBe(true);
|
|
202
|
-
});
|
|
203
|
-
it("prefers tmux over iTerm2 when both signals present (priority order)", () => {
|
|
204
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
205
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
206
|
-
process.env.ITERM_SESSION_ID = "w0t0p0:ABCD1234-FAKE-UUID";
|
|
207
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
208
|
-
expect(result.mechanism).toBe("tmux");
|
|
209
|
-
});
|
|
210
|
-
it("iTerm2 without ITERM_SESSION_ID falls through (does NOT spawn)", () => {
|
|
211
|
-
// Regression guard: spawning into the currently-focused iTerm2 tab
|
|
212
|
-
// would land on the wrong tab. spawn-watcher.ts must refuse, not
|
|
213
|
-
// fall back.
|
|
214
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
215
|
-
// ITERM_SESSION_ID intentionally unset.
|
|
216
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
217
|
-
expect(result.spawned).toBe(false);
|
|
218
|
-
expect(result.reason).toContain("no supported terminal multiplexer");
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
describe("spawnWatcherPane — darwin platform gate", () => {
|
|
222
|
-
let fixture;
|
|
223
|
-
let envSnapshot;
|
|
224
|
-
beforeEach(() => {
|
|
225
|
-
envSnapshot = saveEnv();
|
|
226
|
-
clearWatchedEnv();
|
|
227
|
-
fixture = mkProjectRoot(true);
|
|
228
|
-
process.env.ONTO_WATCHER_DRY_RUN = "1";
|
|
229
|
-
});
|
|
230
|
-
afterEach(() => {
|
|
231
|
-
restoreEnv(envSnapshot);
|
|
232
|
-
if (fixture)
|
|
233
|
-
fixture.cleanup();
|
|
234
|
-
});
|
|
235
|
-
it("iTerm2 branch skips when process.platform !== darwin", () => {
|
|
236
|
-
// On non-darwin platforms, the iTerm2 osascript path would fail;
|
|
237
|
-
// spawn-watcher must gate on platform and fall through. Regression
|
|
238
|
-
// guard: Apple Terminal / iTerm2 SHOULD NOT fire on Linux/Windows
|
|
239
|
-
// even if (somehow) the env vars match.
|
|
240
|
-
const restore = (() => {
|
|
241
|
-
const original = Object.getOwnPropertyDescriptor(process, "platform");
|
|
242
|
-
Object.defineProperty(process, "platform", {
|
|
243
|
-
value: "linux",
|
|
244
|
-
configurable: true,
|
|
245
|
-
});
|
|
246
|
-
return () => {
|
|
247
|
-
if (original)
|
|
248
|
-
Object.defineProperty(process, "platform", original);
|
|
249
|
-
};
|
|
250
|
-
})();
|
|
251
|
-
try {
|
|
252
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
253
|
-
process.env.ITERM_SESSION_ID = "w0t0p0:fake";
|
|
254
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
255
|
-
expect(result.spawned).toBe(false);
|
|
256
|
-
}
|
|
257
|
-
finally {
|
|
258
|
-
restore();
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
it("Apple Terminal branch skips when process.platform !== darwin", () => {
|
|
262
|
-
const restore = (() => {
|
|
263
|
-
const original = Object.getOwnPropertyDescriptor(process, "platform");
|
|
264
|
-
Object.defineProperty(process, "platform", {
|
|
265
|
-
value: "linux",
|
|
266
|
-
configurable: true,
|
|
267
|
-
});
|
|
268
|
-
return () => {
|
|
269
|
-
if (original)
|
|
270
|
-
Object.defineProperty(process, "platform", original);
|
|
271
|
-
};
|
|
272
|
-
})();
|
|
273
|
-
try {
|
|
274
|
-
process.env.TERM_PROGRAM = "Apple_Terminal";
|
|
275
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
276
|
-
expect(result.spawned).toBe(false);
|
|
277
|
-
}
|
|
278
|
-
finally {
|
|
279
|
-
restore();
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
// ---------------------------------------------------------------------------
|
|
284
|
-
// PR #185 follow-up #2 — real-attach paths via child_process.spawnSync mock.
|
|
285
|
-
//
|
|
286
|
-
// Why this exists:
|
|
287
|
-
// The dry-run describe block above covers detection priority, but the
|
|
288
|
-
// actual osascript / tmux split-window invocation paths (spawn-watcher.ts
|
|
289
|
-
// L118-L122 tmux, L180-L185 iterm2, L206-L209 apple_terminal) are NEVER
|
|
290
|
-
// exercised by dry-run (it returns early on `dry_run: true` before the
|
|
291
|
-
// spawnSync call). Smoke scripts run with `ONTO_WATCHER_DRY_RUN=1` for
|
|
292
|
-
// the same reason — they cannot regress-guard the real spawnSync
|
|
293
|
-
// arguments. A change to `split-window` flags or the iTerm2 osascript
|
|
294
|
-
// "matched" sentinel parsing would slip through both layers silently.
|
|
295
|
-
//
|
|
296
|
-
// What this block adds:
|
|
297
|
-
// spawnSync is mocked at the module boundary (top of this file). Each
|
|
298
|
-
// test sets ONTO_WATCHER_DRY_RUN unset (so the real-attach path runs)
|
|
299
|
-
// and asserts on the args + return contract.
|
|
300
|
-
// ---------------------------------------------------------------------------
|
|
301
|
-
describe("spawnWatcherPane — real-attach (spawnSync mock)", () => {
|
|
302
|
-
let fixture;
|
|
303
|
-
let envSnapshot;
|
|
304
|
-
let restorePlatform;
|
|
305
|
-
beforeEach(() => {
|
|
306
|
-
envSnapshot = saveEnv();
|
|
307
|
-
clearWatchedEnv();
|
|
308
|
-
fixture = mkProjectRoot(true);
|
|
309
|
-
// Real-attach path requires dry-run UNSET. Tests below add per-case env.
|
|
310
|
-
restorePlatform = stubDarwin();
|
|
311
|
-
mockedSpawnSync.mockReset();
|
|
312
|
-
});
|
|
313
|
-
afterEach(() => {
|
|
314
|
-
restorePlatform();
|
|
315
|
-
restoreEnv(envSnapshot);
|
|
316
|
-
if (fixture)
|
|
317
|
-
fixture.cleanup();
|
|
318
|
-
});
|
|
319
|
-
it("tmux real-attach passes split-window args + targets $TMUX_PANE + refocuses", () => {
|
|
320
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
321
|
-
process.env.TMUX_PANE = "%5";
|
|
322
|
-
// Two spawnSync calls expected: split-window then select-pane -l.
|
|
323
|
-
mockedSpawnSync
|
|
324
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
325
|
-
.mockReturnValueOnce({ status: 0, stdout: "", stderr: "", pid: 1, output: [], signal: null })
|
|
326
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
|
-
.mockReturnValueOnce({ status: 0, stdout: "", stderr: "", pid: 2, output: [], signal: null });
|
|
328
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
329
|
-
expect(result.spawned).toBe(true);
|
|
330
|
-
expect(result.mechanism).toBe("tmux");
|
|
331
|
-
expect(result.dry_run).toBeUndefined();
|
|
332
|
-
expect(mockedSpawnSync).toHaveBeenCalledTimes(2);
|
|
333
|
-
const [tmuxBin, tmuxArgs] = mockedSpawnSync.mock.calls[0];
|
|
334
|
-
expect(tmuxBin).toBe("tmux");
|
|
335
|
-
// Args contract (regression guard for split-window flags + pane target):
|
|
336
|
-
// split-window -h -l 60 -t %5 <bash watcher cmd>
|
|
337
|
-
expect(tmuxArgs).toEqual([
|
|
338
|
-
"split-window",
|
|
339
|
-
"-h",
|
|
340
|
-
"-l",
|
|
341
|
-
"60",
|
|
342
|
-
"-t",
|
|
343
|
-
"%5",
|
|
344
|
-
expect.stringContaining("onto-review-watch.sh"),
|
|
345
|
-
]);
|
|
346
|
-
// Refocus call comes second.
|
|
347
|
-
const [refocusBin, refocusArgs] = mockedSpawnSync.mock.calls[1];
|
|
348
|
-
expect(refocusBin).toBe("tmux");
|
|
349
|
-
expect(refocusArgs).toEqual(["select-pane", "-l"]);
|
|
350
|
-
});
|
|
351
|
-
it("tmux without TMUX_PANE omits the -t flag", () => {
|
|
352
|
-
// Regression guard: spawn-watcher pushes -t only when TMUX_PANE is set.
|
|
353
|
-
// If someone always passes -t with empty value, tmux would error out.
|
|
354
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
355
|
-
// TMUX_PANE intentionally unset.
|
|
356
|
-
mockedSpawnSync
|
|
357
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
358
|
-
.mockReturnValueOnce({ status: 0, stdout: "", stderr: "", pid: 1, output: [], signal: null })
|
|
359
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
360
|
-
.mockReturnValueOnce({ status: 0, stdout: "", stderr: "", pid: 2, output: [], signal: null });
|
|
361
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
362
|
-
expect(result.spawned).toBe(true);
|
|
363
|
-
const [, tmuxArgs] = mockedSpawnSync.mock.calls[0];
|
|
364
|
-
expect(tmuxArgs).not.toContain("-t");
|
|
365
|
-
expect(tmuxArgs).toEqual([
|
|
366
|
-
"split-window",
|
|
367
|
-
"-h",
|
|
368
|
-
"-l",
|
|
369
|
-
"60",
|
|
370
|
-
expect.stringContaining("onto-review-watch.sh"),
|
|
371
|
-
]);
|
|
372
|
-
});
|
|
373
|
-
it("tmux split failing (status != 0) falls through, no spawned=true", () => {
|
|
374
|
-
process.env.TMUX = "/tmp/tmux-1000/default,12345,0";
|
|
375
|
-
// Tmux split returns non-zero. Without other multiplexer signals,
|
|
376
|
-
// the function must report spawned=false (NOT bubble the failed
|
|
377
|
-
// split as a success).
|
|
378
|
-
mockedSpawnSync
|
|
379
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
380
|
-
.mockReturnValueOnce({ status: 1, stdout: "", stderr: "split failed", pid: 1, output: [], signal: null });
|
|
381
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
382
|
-
expect(result.spawned).toBe(false);
|
|
383
|
-
expect(result.reason).toContain("no supported terminal multiplexer");
|
|
384
|
-
// Refocus must NOT run when split itself failed.
|
|
385
|
-
expect(mockedSpawnSync).toHaveBeenCalledTimes(1);
|
|
386
|
-
});
|
|
387
|
-
it("iTerm2 real-attach passes osascript with embedded UUID + 'matched' sentinel grants success", () => {
|
|
388
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
389
|
-
process.env.ITERM_SESSION_ID = "w0t1p2:ABCD1234-FAKE-UUID";
|
|
390
|
-
mockedSpawnSync.mockReturnValueOnce({
|
|
391
|
-
status: 0,
|
|
392
|
-
stdout: "matched",
|
|
393
|
-
stderr: "",
|
|
394
|
-
pid: 1,
|
|
395
|
-
output: [],
|
|
396
|
-
signal: null,
|
|
397
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
398
|
-
});
|
|
399
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
400
|
-
expect(result.spawned).toBe(true);
|
|
401
|
-
expect(result.mechanism).toBe("iterm2");
|
|
402
|
-
expect(mockedSpawnSync).toHaveBeenCalledTimes(1);
|
|
403
|
-
const [bin, args] = mockedSpawnSync.mock.calls[0];
|
|
404
|
-
expect(bin).toBe("osascript");
|
|
405
|
-
// -e flag + script string. The script must reference both the UUID
|
|
406
|
-
// suffix and the full session id (spawn-watcher matches either form).
|
|
407
|
-
expect(args[0]).toBe("-e");
|
|
408
|
-
const script = String(args[1]);
|
|
409
|
-
expect(script).toContain("ABCD1234-FAKE-UUID");
|
|
410
|
-
expect(script).toContain("w0t1p2:ABCD1234-FAKE-UUID");
|
|
411
|
-
expect(script).toContain("split vertically");
|
|
412
|
-
expect(script).toContain("onto-review-watch.sh");
|
|
413
|
-
expect(script).toContain('return "matched"');
|
|
414
|
-
});
|
|
415
|
-
it("iTerm2 osascript returning 'no-match' falls through, no spawned=true", () => {
|
|
416
|
-
// Regression guard: spawn-watcher requires the explicit "matched"
|
|
417
|
-
// sentinel. If the originating tab is closed (no-match), the osascript
|
|
418
|
-
// returns "no-match" and we must NOT report spawned=true (which would
|
|
419
|
-
// imply a pane is visible, when none was attached).
|
|
420
|
-
process.env.TERM_PROGRAM = "iTerm.app";
|
|
421
|
-
process.env.ITERM_SESSION_ID = "w0t1p2:ABCD1234-FAKE-UUID";
|
|
422
|
-
mockedSpawnSync.mockReturnValueOnce({
|
|
423
|
-
status: 0,
|
|
424
|
-
stdout: "no-match",
|
|
425
|
-
stderr: "",
|
|
426
|
-
pid: 1,
|
|
427
|
-
output: [],
|
|
428
|
-
signal: null,
|
|
429
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
430
|
-
});
|
|
431
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
432
|
-
expect(result.spawned).toBe(false);
|
|
433
|
-
expect(result.reason).toContain("no supported terminal multiplexer");
|
|
434
|
-
});
|
|
435
|
-
it("Apple Terminal real-attach passes osascript with do-script", () => {
|
|
436
|
-
process.env.TERM_PROGRAM = "Apple_Terminal";
|
|
437
|
-
mockedSpawnSync.mockReturnValueOnce({
|
|
438
|
-
status: 0,
|
|
439
|
-
stdout: "",
|
|
440
|
-
stderr: "",
|
|
441
|
-
pid: 1,
|
|
442
|
-
output: [],
|
|
443
|
-
signal: null,
|
|
444
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
445
|
-
});
|
|
446
|
-
const result = spawnWatcherPane(fixture.projectRoot, fixture.sessionRoot);
|
|
447
|
-
expect(result.spawned).toBe(true);
|
|
448
|
-
expect(result.mechanism).toBe("apple_terminal");
|
|
449
|
-
const [bin, args] = mockedSpawnSync.mock.calls[0];
|
|
450
|
-
expect(bin).toBe("osascript");
|
|
451
|
-
expect(args[0]).toBe("-e");
|
|
452
|
-
const script = String(args[1]);
|
|
453
|
-
expect(script).toContain('tell application "Terminal"');
|
|
454
|
-
expect(script).toContain("do script");
|
|
455
|
-
expect(script).toContain("onto-review-watch.sh");
|
|
456
|
-
});
|
|
457
|
-
});
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { stripWrappingCodeFence } from "./strip-wrapping-code-fence.js";
|
|
3
|
-
describe("stripWrappingCodeFence", () => {
|
|
4
|
-
it("strips ```yaml wrapper observed on 30B synthesize output", () => {
|
|
5
|
-
const raw = [
|
|
6
|
-
"```yaml",
|
|
7
|
-
"---",
|
|
8
|
-
"deliberation_status: performed",
|
|
9
|
-
"---",
|
|
10
|
-
"### Consensus",
|
|
11
|
-
"- All three lenses identify a systemic pattern.",
|
|
12
|
-
"```",
|
|
13
|
-
].join("\n");
|
|
14
|
-
const stripped = stripWrappingCodeFence(raw);
|
|
15
|
-
expect(stripped.startsWith("---")).toBe(true);
|
|
16
|
-
expect(stripped.endsWith("- All three lenses identify a systemic pattern.")).toBe(true);
|
|
17
|
-
expect(stripped).not.toContain("```");
|
|
18
|
-
});
|
|
19
|
-
it("strips ```markdown wrapper", () => {
|
|
20
|
-
const raw = "```markdown\n### Consensus\n- one\n```";
|
|
21
|
-
expect(stripWrappingCodeFence(raw)).toBe("### Consensus\n- one");
|
|
22
|
-
});
|
|
23
|
-
it("strips fence with no language tag", () => {
|
|
24
|
-
const raw = "```\n### Consensus\n- one\n```";
|
|
25
|
-
expect(stripWrappingCodeFence(raw)).toBe("### Consensus\n- one");
|
|
26
|
-
});
|
|
27
|
-
it("tolerates leading and trailing whitespace around the fence", () => {
|
|
28
|
-
const raw = " \n```yaml\nbody\n```\n \n";
|
|
29
|
-
expect(stripWrappingCodeFence(raw)).toBe("body");
|
|
30
|
-
});
|
|
31
|
-
it("tolerates trailing whitespace on the closing fence line", () => {
|
|
32
|
-
const raw = "```yaml\nbody\n``` ";
|
|
33
|
-
expect(stripWrappingCodeFence(raw)).toBe("body");
|
|
34
|
-
});
|
|
35
|
-
it("preserves inner code blocks within a wrapped outer fence", () => {
|
|
36
|
-
const raw = [
|
|
37
|
-
"```markdown",
|
|
38
|
-
"### Example",
|
|
39
|
-
"```ts",
|
|
40
|
-
"const x = 1;",
|
|
41
|
-
"```",
|
|
42
|
-
"end of example",
|
|
43
|
-
"```",
|
|
44
|
-
].join("\n");
|
|
45
|
-
const stripped = stripWrappingCodeFence(raw);
|
|
46
|
-
expect(stripped.startsWith("### Example")).toBe(true);
|
|
47
|
-
expect(stripped.endsWith("end of example")).toBe(true);
|
|
48
|
-
expect(stripped).toContain("```ts");
|
|
49
|
-
expect(stripped).toContain("const x = 1;");
|
|
50
|
-
});
|
|
51
|
-
it("is a no-op when no outer wrapping fence is present", () => {
|
|
52
|
-
const raw = "### Consensus\n- some finding\n\n```ts\nconst x = 1;\n```\n\n### Disagreement\n- another";
|
|
53
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw.trim());
|
|
54
|
-
});
|
|
55
|
-
it("is a no-op on plain markdown without any fences", () => {
|
|
56
|
-
const raw = "---\ndeliberation_status: not_needed\n---\n### Consensus\n- finding";
|
|
57
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw);
|
|
58
|
-
});
|
|
59
|
-
it("leaves partial fence (open without close) untouched", () => {
|
|
60
|
-
const raw = "```yaml\n---\ndeliberation_status: performed\n---\n### Consensus\n- finding";
|
|
61
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw);
|
|
62
|
-
});
|
|
63
|
-
it("leaves partial fence (close without open) untouched", () => {
|
|
64
|
-
const raw = "### Consensus\n- finding\n```";
|
|
65
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw);
|
|
66
|
-
});
|
|
67
|
-
it("handles CRLF line endings", () => {
|
|
68
|
-
const raw = "```yaml\r\nbody line\r\n```";
|
|
69
|
-
expect(stripWrappingCodeFence(raw)).toBe("body line");
|
|
70
|
-
});
|
|
71
|
-
it("does not strip when opening fence is not at the very start", () => {
|
|
72
|
-
const raw = "Prefix text\n```yaml\nbody\n```";
|
|
73
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw);
|
|
74
|
-
});
|
|
75
|
-
it("does not strip when closing fence has trailing content after it", () => {
|
|
76
|
-
const raw = "```yaml\nbody\n```\nTrailing commentary";
|
|
77
|
-
expect(stripWrappingCodeFence(raw)).toBe(raw);
|
|
78
|
-
});
|
|
79
|
-
});
|