pi-harness-runtime 1.1.439 → 1.1.441
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/harness/e2e/auto-test-loop.ts +8 -2
- package/harness/e2e/browser-scrapers/base-browser-scraper.ts +2 -0
- package/harness/e2e/browser-scrapers/chrome-profile-manager.ts +2 -0
- package/harness/e2e/browser-scrapers/codex-browser-scraper.ts +2 -0
- package/harness/e2e/tools-detector.ts +2 -0
- package/harness/index.ts +2 -1
- package/harness/key-loader.ts +2 -0
- package/harness/langchain/checkpointer.ts +2 -0
- package/harness/langchain/cron-cli.ts +2 -0
- package/harness/langchain/graph.ts +2 -0
- package/harness/master-planner.ts +1 -1
- package/harness/notification-center.ts +2 -0
- package/harness/output-limit-handler.ts +1 -1
- package/harness/project-detector/detector.ts +2 -4
- package/harness/secret-provider.ts +2 -0
- package/harness/task-graph.ts +460 -113
- package/index.ts +16 -7
- package/package.json +7 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/dist/extension.d.ts.map +1 -1
- package/packages/agent-policy/dist/extension.js +2 -0
- package/packages/agent-policy/dist/extension.js.map +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/agent-policy/src/extension.ts +2 -0
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/dist/minimax-browser-auth.d.ts.map +1 -1
- package/packages/auth/dist/minimax-browser-auth.js +23 -1
- package/packages/auth/dist/minimax-browser-auth.js.map +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/auth/src/minimax-browser-auth.ts +30 -5
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/dist/inbox.d.ts.map +1 -1
- package/packages/autonomous-runtime/dist/inbox.js +2 -0
- package/packages/autonomous-runtime/dist/inbox.js.map +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/autonomous-runtime/src/inbox.ts +2 -0
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/dist/src/clipboard.d.ts.map +1 -1
- package/packages/clipboard/dist/src/clipboard.js +2 -0
- package/packages/clipboard/dist/src/clipboard.js.map +1 -1
- package/packages/clipboard/dist/src/copy-sync.d.ts.map +1 -1
- package/packages/clipboard/dist/src/copy-sync.js +2 -0
- package/packages/clipboard/dist/src/copy-sync.js.map +1 -1
- package/packages/clipboard/dist/src/gist-relay.d.ts.map +1 -1
- package/packages/clipboard/dist/src/gist-relay.js +2 -0
- package/packages/clipboard/dist/src/gist-relay.js.map +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard/src/clipboard.ts +2 -0
- package/packages/clipboard/src/copy-sync.ts +2 -0
- package/packages/clipboard/src/gist-relay.ts +2 -0
- package/packages/clipboard-plugin/dist/types.d.ts +9 -2
- package/packages/clipboard-plugin/dist/types.d.ts.map +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/clipboard-plugin/src/types.ts +9 -2
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/dist/delegation-store.js +1 -4
- package/packages/contracts/dist/workspace-env.js +28 -1
- package/packages/contracts/package.json +1 -1
- package/packages/contracts/src/delegation-store.ts +9 -4
- package/packages/contracts/src/workspace-env.ts +29 -4
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/dist/src/store.d.ts.map +1 -1
- package/packages/event-store/dist/src/store.js +2 -0
- package/packages/event-store/dist/src/store.js.map +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/event-store/src/store.ts +3 -0
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/dist/analyzer.d.ts.map +1 -1
- package/packages/generic-web-plugin/dist/analyzer.js +2 -0
- package/packages/generic-web-plugin/dist/analyzer.js.map +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/generic-web-plugin/src/analyzer.ts +3 -0
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/dist/mcp-client.d.ts.map +1 -1
- package/packages/knowledge-retrieval/dist/mcp-client.js +0 -1
- package/packages/knowledge-retrieval/dist/mcp-client.js.map +1 -1
- package/packages/knowledge-retrieval/package.json +1 -4
- package/packages/knowledge-retrieval/src/mcp-client.ts +0 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/mcp-adapter/dist/server.d.ts.map +1 -1
- package/packages/mcp-adapter/dist/server.js +2 -0
- package/packages/mcp-adapter/dist/server.js.map +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/mcp-adapter/src/server.ts +3 -0
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/dist/index.d.ts.map +1 -1
- package/packages/paperclip-integration/dist/index.js +2 -0
- package/packages/paperclip-integration/dist/index.js.map +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/paperclip-integration/src/index.ts +2 -0
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/dist/audit.d.ts.map +1 -1
- package/packages/privilege-broker/dist/audit.js +2 -0
- package/packages/privilege-broker/dist/audit.js.map +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/privilege-broker/src/audit.ts +2 -0
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/dist/compiler.d.ts.map +1 -1
- package/packages/prompt-compiler/dist/compiler.js +2 -0
- package/packages/prompt-compiler/dist/compiler.js.map +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-compiler/src/compiler.ts +2 -0
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/dist/client.d.ts.map +1 -1
- package/packages/skill-mcp-client/dist/client.js +0 -1
- package/packages/skill-mcp-client/dist/client.js.map +1 -1
- package/packages/skill-mcp-client/package.json +1 -4
- package/packages/skill-mcp-client/src/client.ts +0 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/dist/parser.d.ts.map +1 -1
- package/packages/skills/dist/parser.js +2 -0
- package/packages/skills/dist/parser.js.map +1 -1
- package/packages/skills/dist/skill-versioning.d.ts.map +1 -1
- package/packages/skills/dist/skill-versioning.js +2 -0
- package/packages/skills/dist/skill-versioning.js.map +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/skills/src/parser.ts +3 -0
- package/packages/skills/src/skill-versioning.ts +2 -0
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/dist/index.js +0 -2
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/webmcp-tester/src/index.ts +0 -3
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/dist/trigger.d.ts.map +1 -1
- package/packages/write-review/dist/trigger.js +1 -2
- package/packages/write-review/dist/trigger.js.map +1 -1
- package/packages/write-review/package.json +1 -1
- package/packages/write-review/src/trigger.ts +1 -2
- package/scripts/lib/runtime-imports.ts +189 -3
- package/scripts/release-all.ts +5 -3
- package/scripts/telegram-webhook-server.ts +2 -0
- package/scripts/typecheck-packages.mjs +7 -4
- package/scripts/verify-package-contents.ts +161 -2
- package/harness/e2e/tools-detector.test.ts +0 -156
- package/harness/glm-quota-countdown.test.ts +0 -323
- package/harness/langchain/agents.test.ts +0 -39
- package/harness/langchain/checkpointer.test.ts +0 -243
- package/harness/langchain/daemon.test.ts +0 -459
- package/harness/langchain/model-router.test.ts +0 -191
- package/harness/langchain/ping-pong-middleware.test.ts +0 -69
- package/harness/langchain/scoreboard.test.ts +0 -245
- package/harness/langchain/status-line.test.ts +0 -106
- package/harness/langchain/surge.test.ts +0 -467
- package/harness/langchain/widget.test.ts +0 -251
- package/harness/skill-sync.test.ts +0 -57
- package/harness/ssh-detach-interceptor.test.ts +0 -263
- package/harness/ssh-hang-recovery.test.ts +0 -86
- package/packages/a2a-adapter/test/a2a.test.ts +0 -151
- package/packages/agent-policy/test/interlock.test.ts +0 -101
- package/packages/agent-policy/test/policy-retention.test.ts +0 -380
- package/packages/agent-policy/test/policy.test.ts +0 -387
- package/packages/auth/test/auth.test.ts +0 -238
- package/packages/autonomous-refactor/test/refactor.test.ts +0 -202
- package/packages/autonomous-runtime/test/types.test.ts +0 -95
- package/packages/cache-strategy/test/cache.test.ts +0 -137
- package/packages/capability-registry/test/registry.test.ts +0 -204
- package/packages/checkpoint/test/engine.test.ts +0 -265
- package/packages/cli-plugin-sdk/test/cli.test.ts +0 -45
- package/packages/code-generation/test/generator.test.ts +0 -238
- package/packages/code-review/test/engine.test.ts +0 -302
- package/packages/codex-adapter/test/provider.test.ts +0 -142
- package/packages/codex-watcher/test/watch.test.ts +0 -453
- package/packages/context-compiler/test/context-compiler.test.ts +0 -746
- package/packages/context-manager/test/context.test.ts +0 -198
- package/packages/contracts/test/delegation.test.ts +0 -350
- package/packages/contracts/test/workspace-env.test.ts +0 -802
- package/packages/cookie-sanitizer/test/infer.test.ts +0 -110
- package/packages/cookie-sanitizer/test/normalize.test.ts +0 -113
- package/packages/cookie-sanitizer/test/parse.test.ts +0 -204
- package/packages/cookie-sanitizer/test/sync.test.ts +0 -237
- package/packages/cookie-sanitizer/test/watcher.test.ts +0 -27
- package/packages/cost-optimizer/test/cost-optimizer.test.ts +0 -438
- package/packages/dependency-analyzer/test/analyzer.test.ts +0 -49
- package/packages/django-plugin/test/analyzer.test.ts +0 -195
- package/packages/doc-generator/test/docs.test.ts +0 -168
- package/packages/durable-review/test/acceptance.test.ts +0 -357
- package/packages/durable-review/test/smoke.test.ts +0 -107
- package/packages/evaluation-engine/test/engine.test.ts +0 -277
- package/packages/evaluation-runner/test/runner.test.ts +0 -168
- package/packages/event-bus/test/bus.test.ts +0 -100
- package/packages/event-store/test/store.test.ts +0 -115
- package/packages/experience-replay/test/replay.test.ts +0 -267
- package/packages/feedback-collector/test/collector.test.ts +0 -142
- package/packages/framework-detector/test/detector.test.ts +0 -75
- package/packages/framework-plugin-sdk/test/manager.test.ts +0 -320
- package/packages/frappe-plugin/test/analyzer.test.ts +0 -250
- package/packages/generic-web-plugin/test/analyzer.test.ts +0 -134
- package/packages/health-monitor/test/health.test.ts +0 -231
- package/packages/intent-analyzer/test/analyzer.test.ts +0 -72
- package/packages/intent-analyzer/test/ping-pong.test.ts +0 -96
- package/packages/jev-judge/tests/auto-continue-context.test.ts +0 -280
- package/packages/jev-judge/tests/continuation-controller.test.ts +0 -1396
- package/packages/jev-judge/tests/jev-provider-chain.test.ts +0 -536
- package/packages/jev-judge/tests/outcome-application.test.ts +0 -132
- package/packages/jev-judge/tests/question-risk.test.ts +0 -129
- package/packages/jev-judge/tests/typesafe-provider.test.ts +0 -640
- package/packages/jev-judge/tests/validation-ledger.test.ts +0 -181
- package/packages/jev-judge/tests/validation-plan.test.ts +0 -170
- package/packages/jev-judge/tests/validation-tie-breaker.test.ts +0 -88
- package/packages/laravel-plugin/test/analyzer.test.ts +0 -220
- package/packages/learning-engine/test/engine.test.ts +0 -331
- package/packages/logging/test/buffer.test.ts +0 -44
- package/packages/logging/test/classification.test.ts +0 -137
- package/packages/logging/test/config.test.ts +0 -97
- package/packages/logging/test/fanout.test.ts +0 -186
- package/packages/logging/test/identity-transport.test.ts +0 -197
- package/packages/logging/test/incidents.test.ts +0 -404
- package/packages/logging/test/ingest-schema.test.ts +0 -184
- package/packages/logging/test/integration.test.ts +0 -140
- package/packages/logging/test/log-http.test.ts +0 -246
- package/packages/logging/test/redact.test.ts +0 -109
- package/packages/logging/test/sampler.test.ts +0 -57
- package/packages/logging/test/server.test.ts +0 -444
- package/packages/logging/test/shipper.test.ts +0 -152
- package/packages/logging/test/spool.test.ts +0 -96
- package/packages/mcp-adapter/test/server.test.ts +0 -91
- package/packages/memory-engine/test/engine.test.ts +0 -456
- package/packages/model-registry/test/registry.test.ts +0 -342
- package/packages/nextjs-plugin/test/analyzer.test.ts +0 -149
- package/packages/notification/test/approval-payload.test.ts +0 -269
- package/packages/notification/test/detail-format.test.ts +0 -106
- package/packages/notification/test/notification.test.ts +0 -375
- package/packages/notification/test/pending-question-lifecycle.test.ts +0 -195
- package/packages/notification/test/pending-question.test.ts +0 -331
- package/packages/notification/test/tooling-proposal-payload.test.ts +0 -212
- package/packages/observability/test/observability.test.ts +0 -1350
- package/packages/performance-optimizer/test/optimizer.test.ts +0 -267
- package/packages/project-analyzer/test/index.test.ts +0 -1719
- package/packages/prompt-compiler/test/prompt-compiler.test.ts +0 -813
- package/packages/prompt-versioning/test/versioning.test.ts +0 -112
- package/packages/provider-adapter-sdk/test/sdk.test.ts +0 -220
- package/packages/provider-router/test/provider-router.test.ts +0 -405
- package/packages/provider-selector/test/selector.test.ts +0 -192
- package/packages/providers/test/providers.test.ts +0 -225
- package/packages/qdrant-skills/test/collection-info.test.ts +0 -165
- package/packages/qdrant-skills/test/embedder-batch.test.ts +0 -184
- package/packages/qdrant-skills/test/embedder.test.ts +0 -97
- package/packages/quota-manager/test/quota.test.ts +0 -432
- package/packages/rate-limiter/test/limiter.test.ts +0 -128
- package/packages/react-vite-plugin/test/analyzer.test.ts +0 -139
- package/packages/relay/test/client.test.ts +0 -446
- package/packages/relay/test/relay-e2e.test.ts +0 -299
- package/packages/relay/test/relay-endpoint.test.ts +0 -278
- package/packages/release-manager/test/release.test.ts +0 -215
- package/packages/requirement-compiler/test/requirement-compiler.test.ts +0 -743
- package/packages/runtime/test/runtime-api.test.ts +0 -169
- package/packages/runtime/test/runtime.test.ts +0 -297
- package/packages/scheduler/test/scheduler.test.ts +0 -125
- package/packages/session/test/manager.test.ts +0 -233
- package/packages/shared-context/test/shared-context.test.ts +0 -114
- package/packages/skill-registry/test/registry.test.ts +0 -508
- package/packages/skills/test/init-skills.test.ts +0 -114
- package/packages/skills/test/remote-skills.test.ts +0 -360
- package/packages/skills/test/remote-source.test.ts +0 -248
- package/packages/skills/test/sanitize.test.ts +0 -250
- package/packages/skills/test/vector-indexing.test.ts +0 -205
- package/packages/skills/test/vector-schema.test.ts +0 -180
- package/packages/skills/test/vector-threshold.test.ts +0 -108
- package/packages/sprint-planner/test/planner.test.ts +0 -187
- package/packages/task-compiler/test/task-compiler.test.ts +0 -628
- package/packages/test-data-generator/test/generator.test.ts +0 -265
- package/packages/test-generator/test/generator.test.ts +0 -156
- package/packages/token-estimation/test/token-estimation.test.ts +0 -207
- package/packages/token-optimizer/test/optimizer.test.ts +0 -141
- package/packages/tooling-preference/tests/changed-files.test.ts +0 -124
- package/packages/tooling-preference/tests/detect.test.ts +0 -188
- package/packages/tooling-preference/tests/proposal.test.ts +0 -107
- package/packages/tooling-preference/tests/quality-check.test.ts +0 -272
- package/packages/tooling-preference/tests/registry.test.ts +0 -51
- package/packages/tooling-preference/tests/store.test.ts +0 -99
- package/packages/trajectory/test/store.test.ts +0 -250
- package/packages/tui/test/harness-footer.test.ts +0 -559
- package/packages/tui/test/harness-header.test.ts +0 -590
- package/packages/two-phase-review/test/classify.test.ts +0 -102
- package/packages/two-phase-review/test/helpers.ts +0 -72
- package/packages/two-phase-review/test/rules.test.ts +0 -150
- package/packages/two-phase-review/test/runtime.test.ts +0 -362
- package/packages/two-phase-review/test/scope.test.ts +0 -186
- package/packages/two-phase-review/test/signals.test.ts +0 -183
- package/packages/two-phase-review/test/state.test.ts +0 -201
- package/packages/wiki/test/basic.test.ts +0 -242
- package/packages/workspace-scanner/test/scanner.test.ts +0 -43
- package/packages/worktree/test/worktree.test.ts +0 -163
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A2A Adapter Tests (RFC-0069)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect } from "bun:test";
|
|
6
|
-
import {
|
|
7
|
-
createAgentCard,
|
|
8
|
-
routeTask,
|
|
9
|
-
getTask,
|
|
10
|
-
cancelTask,
|
|
11
|
-
taskStatusUpdateSSE,
|
|
12
|
-
} from "../src/agent.js";
|
|
13
|
-
import { A2AClient } from "../src/client.js";
|
|
14
|
-
import { A2ATransport } from "../src/transport.js";
|
|
15
|
-
import {
|
|
16
|
-
A2A_PROTOCOL_VERSION,
|
|
17
|
-
WELL_KNOWN_AGENT_PATH,
|
|
18
|
-
} from "../src/protocol.js";
|
|
19
|
-
import type { TaskMessage } from "../src/types.js";
|
|
20
|
-
|
|
21
|
-
describe("A2A Protocol Constants", () => {
|
|
22
|
-
it("exports protocol version", () => {
|
|
23
|
-
expect(A2A_PROTOCOL_VERSION).toBe("1.0.0");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("exports well-known agent path", () => {
|
|
27
|
-
expect(WELL_KNOWN_AGENT_PATH).toBe("/.well-known/agent.json");
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe("AgentCard", () => {
|
|
32
|
-
it("creates agent card with defaults", () => {
|
|
33
|
-
const card = createAgentCard({
|
|
34
|
-
name: "pi-harness",
|
|
35
|
-
description: "AI coding harness",
|
|
36
|
-
url: "http://localhost:3000",
|
|
37
|
-
version: "0.9.4",
|
|
38
|
-
});
|
|
39
|
-
expect(card.name).toBe("pi-harness");
|
|
40
|
-
expect(card.capabilities.streaming).toBe(true);
|
|
41
|
-
expect(card.skills.length).toBeGreaterThan(0);
|
|
42
|
-
expect(card.skills[0].id).toBe("code-analysis");
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("creates agent card with custom skills", () => {
|
|
46
|
-
const card = createAgentCard({
|
|
47
|
-
name: "test-agent",
|
|
48
|
-
description: "Test",
|
|
49
|
-
url: "http://localhost:3001",
|
|
50
|
-
version: "1.0.0",
|
|
51
|
-
skills: [
|
|
52
|
-
{
|
|
53
|
-
id: "custom",
|
|
54
|
-
name: "Custom",
|
|
55
|
-
description: "Custom skill",
|
|
56
|
-
tags: ["test"],
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
});
|
|
60
|
-
expect(card.skills).toHaveLength(1);
|
|
61
|
-
expect(card.skills[0].id).toBe("custom");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("merges custom capabilities", () => {
|
|
65
|
-
const card = createAgentCard({
|
|
66
|
-
name: "test",
|
|
67
|
-
description: "Test",
|
|
68
|
-
url: "http://localhost:3002",
|
|
69
|
-
version: "1.0.0",
|
|
70
|
-
capabilities: { pushNotifications: true },
|
|
71
|
-
});
|
|
72
|
-
expect(card.capabilities.streaming).toBe(true);
|
|
73
|
-
expect(card.capabilities.pushNotifications).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("Task Routing", () => {
|
|
78
|
-
it("routes a task message", async () => {
|
|
79
|
-
const message: TaskMessage = { role: "user", content: "Analyze this code" };
|
|
80
|
-
const task = await routeTask(message);
|
|
81
|
-
expect(task.id).toMatch(/^task-/);
|
|
82
|
-
expect(task.status).toBe("completed");
|
|
83
|
-
expect(task.artifacts).toHaveLength(1);
|
|
84
|
-
expect(task.artifacts![0].parts[0].text).toContain("Analyze this code");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("stores and retrieves task", async () => {
|
|
88
|
-
const message: TaskMessage = { role: "user", content: "Test" };
|
|
89
|
-
const task = await routeTask(message);
|
|
90
|
-
const retrieved = getTask(task.id);
|
|
91
|
-
expect(retrieved).not.toBeNull();
|
|
92
|
-
expect(retrieved!.id).toBe(task.id);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("returns null for unknown task", () => {
|
|
96
|
-
expect(getTask("nonexistent-task")).toBeNull();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it("cancels a task", async () => {
|
|
100
|
-
const message: TaskMessage = { role: "user", content: "Cancel test" };
|
|
101
|
-
const task = await routeTask(message);
|
|
102
|
-
expect(task.status).toBe("completed");
|
|
103
|
-
const result = cancelTask(task.id);
|
|
104
|
-
expect(result).toBe(true);
|
|
105
|
-
expect(getTask(task.id)!.status).toBe("canceled");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("returns false when canceling unknown task", () => {
|
|
109
|
-
expect(cancelTask("nonexistent")).toBe(false);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("generates SSE status update", async () => {
|
|
113
|
-
const message: TaskMessage = { role: "user", content: "SSE test" };
|
|
114
|
-
const task = await routeTask(message);
|
|
115
|
-
const sse = taskStatusUpdateSSE(task.id);
|
|
116
|
-
expect(sse).toContain("task_status_update");
|
|
117
|
-
expect(sse).toContain(task.id);
|
|
118
|
-
expect(sse).toContain("completed");
|
|
119
|
-
expect(sse).toContain("final");
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe("A2AClient", () => {
|
|
124
|
-
it("creates client with URL", () => {
|
|
125
|
-
const client = new A2AClient("http://localhost:3000");
|
|
126
|
-
expect(client).toBeDefined();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("sendTask throws on unreachable server", async () => {
|
|
130
|
-
const client = new A2AClient("http://localhost:9999");
|
|
131
|
-
await expect(client.sendTask("test")).rejects.toThrow();
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("findAgents returns empty array", async () => {
|
|
135
|
-
const client = new A2AClient("http://localhost:3000");
|
|
136
|
-
const results = await client.findAgents({ skill: "test" });
|
|
137
|
-
expect(results).toEqual([]);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe("A2ATransport", () => {
|
|
142
|
-
it("creates transport with config", () => {
|
|
143
|
-
const t = new A2ATransport("http://localhost:3000", { timeout: 5000 });
|
|
144
|
-
expect(t).toBeDefined();
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it("getAgentCard throws on invalid URL", async () => {
|
|
148
|
-
const t = new A2ATransport("http://localhost:9999", { timeout: 2000 });
|
|
149
|
-
await expect(t.getAgentCard()).rejects.toThrow();
|
|
150
|
-
});
|
|
151
|
-
});
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, expect, test } from "bun:test";
|
|
2
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { pathToFileURL } from "node:url";
|
|
6
|
-
import { registerAgentPolicy } from "../src/extension.js";
|
|
7
|
-
import { PolicyLoader } from "../src/policy-loader.js";
|
|
8
|
-
import { resetPolicyStore } from "../src/policy-store.js";
|
|
9
|
-
|
|
10
|
-
let root: string;
|
|
11
|
-
let cwd: string;
|
|
12
|
-
let harnessRulesPath: URL;
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
resetPolicyStore();
|
|
15
|
-
root = mkdtempSync(join(tmpdir(), "policy-interlock-"));
|
|
16
|
-
cwd = join(root, "project");
|
|
17
|
-
mkdirSync(join(cwd, "src"), { recursive: true });
|
|
18
|
-
mkdirSync(join(cwd, ".git"));
|
|
19
|
-
writeFileSync(join(root, "harness.md"), "Harness mandatory rules");
|
|
20
|
-
writeFileSync(join(root, "AGENTS.md"), "Ancestor mandatory rules");
|
|
21
|
-
writeFileSync(join(cwd, "AGENTS.md"), "Project mandatory rules");
|
|
22
|
-
writeFileSync(join(cwd, "RULES.md"), "Advisory rules");
|
|
23
|
-
harnessRulesPath = pathToFileURL(join(root, "harness.md"));
|
|
24
|
-
});
|
|
25
|
-
afterEach(() => rmSync(root, { recursive: true, force: true }));
|
|
26
|
-
|
|
27
|
-
function runtime(requireReceiptBeforeMutation = true) {
|
|
28
|
-
const hooks = new Map<string, Function[]>();
|
|
29
|
-
let tool: any;
|
|
30
|
-
registerAgentPolicy({
|
|
31
|
-
on(name: string, handler: Function) {
|
|
32
|
-
hooks.set(name, [...(hooks.get(name) ?? []), handler]);
|
|
33
|
-
},
|
|
34
|
-
registerTool(value: unknown) { tool = value; },
|
|
35
|
-
} as any, { harnessRulesPath, requireReceiptBeforeMutation, lspMode: "pi-lens" });
|
|
36
|
-
return {
|
|
37
|
-
call: (params: unknown, ctx: unknown) => tool.execute("test", params, undefined, undefined, ctx),
|
|
38
|
-
gate: (ctx: unknown, path = "src/file.ts") => hooks.get("tool_call"),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
test("target checks preserve mandatory revision, ancestor rules, and cached manifest", async () => {
|
|
44
|
-
const loader = new PolicyLoader({ harnessRulesPath });
|
|
45
|
-
const manifest = await loader.load(cwd);
|
|
46
|
-
const snapshot = JSON.stringify(manifest);
|
|
47
|
-
for (const path of ["src/file.ts", join(cwd, "src/file.ts"), "packages/a/file.ts"]) {
|
|
48
|
-
const target = await loader.loadForTarget(cwd, path);
|
|
49
|
-
expect(target.revision).toBe(manifest.revision);
|
|
50
|
-
expect(target.sources.some(s => s.path === join(root, "AGENTS.md"))).toBe(true);
|
|
51
|
-
expect(JSON.stringify(manifest)).toBe(snapshot);
|
|
52
|
-
}
|
|
53
|
-
loader.invalidateCache();
|
|
54
|
-
expect((await loader.load(cwd)).revision).toBe(manifest.revision);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("acknowledgment unlocks the next target call using Pi sessionManager identity", async () => {
|
|
58
|
-
const r = runtime();
|
|
59
|
-
const context = (id = "session-a") => ({ cwd, sessionManager: { getSessionId: () => id } });
|
|
60
|
-
expect((await r.gate(context())).block).toBe(true);
|
|
61
|
-
const revision = (await r.call({ action: "manifest" }, context())).details.manifest.revision;
|
|
62
|
-
expect((await r.call({ action: "acknowledge", revision }, context())).isError).not.toBe(true);
|
|
63
|
-
expect((await r.gate(context())).block).not.toBe(true);
|
|
64
|
-
expect((await r.gate(context(), join(cwd, "src/file.ts"))).block).not.toBe(true);
|
|
65
|
-
expect((await r.gate(context("session-b"))).block).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("legacy contexts reuse a stable fallback identity", async () => {
|
|
69
|
-
const r = runtime();
|
|
70
|
-
const revision = (await r.call({ action: "manifest" }, { cwd })).details.manifest.revision;
|
|
71
|
-
await r.call({ action: "acknowledge", revision }, { cwd });
|
|
72
|
-
expect((await r.gate({ cwd })).block).not.toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test("explicitly disabled receipt enforcement allows tools without an acknowledgment", async () => {
|
|
76
|
-
const r = runtime(false);
|
|
77
|
-
expect((await r.gate({ cwd })).block).not.toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("wrong revisions remain rejected when receipt enforcement is enabled", async () => {
|
|
81
|
-
const r = runtime();
|
|
82
|
-
const ctx = { cwd, sessionId: "session-a" };
|
|
83
|
-
const result = await r.call({ action: "acknowledge", revision: "stale" }, ctx);
|
|
84
|
-
expect(result.isError).toBe(true);
|
|
85
|
-
expect((await r.gate(ctx)).block).toBe(true);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test("rule changes still require a new receipt after policy cache refresh", async () => {
|
|
89
|
-
const r = runtime();
|
|
90
|
-
const ctx = { cwd, sessionId: "session-a" };
|
|
91
|
-
const revision = (await r.call({ action: "manifest" }, ctx)).details.manifest.revision;
|
|
92
|
-
await r.call({ action: "acknowledge", revision }, ctx);
|
|
93
|
-
writeFileSync(join(cwd, "AGENTS.md"), "Updated mandatory rules");
|
|
94
|
-
// A fresh loader/registration models cache refresh without a five-second wait.
|
|
95
|
-
const refreshed = runtime();
|
|
96
|
-
expect((await refreshed.gate(ctx)).block).toBe(true);
|
|
97
|
-
const current = (await refreshed.call({ action: "manifest" }, ctx)).details.manifest.revision;
|
|
98
|
-
expect(current).not.toBe(revision);
|
|
99
|
-
await refreshed.call({ action: "acknowledge", revision: current }, ctx);
|
|
100
|
-
expect((await refreshed.gate(ctx)).block).not.toBe(true);
|
|
101
|
-
});
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Policy Retention Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests for lifecycle retention after compaction, reset, resume.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, before, after } from "node:test";
|
|
8
|
-
import assert from "node:assert";
|
|
9
|
-
import { existsSync, mkdirSync, writeFileSync, unlinkSync, rmSync } from "node:fs";
|
|
10
|
-
import { join, dirname } from "node:path";
|
|
11
|
-
import { randomUUID } from "node:crypto";
|
|
12
|
-
import type { PolicyManifest } from "../dist/types.js";
|
|
13
|
-
import { PolicyLoader } from "../dist/policy-loader.js";
|
|
14
|
-
import { getPolicyStore, resetPolicyStore } from "../dist/policy-store.js";
|
|
15
|
-
|
|
16
|
-
// Test workspace
|
|
17
|
-
const TEST_DIR = "/tmp/policy-retention-test-" + Date.now();
|
|
18
|
-
const AGENTS_MD = join(TEST_DIR, "AGENTS.md");
|
|
19
|
-
const RULES_MD = join(TEST_DIR, "RULES.md");
|
|
20
|
-
|
|
21
|
-
describe("Policy Retention Tests", () => {
|
|
22
|
-
before(() => {
|
|
23
|
-
mkdirSync(TEST_DIR, { recursive: true });
|
|
24
|
-
resetPolicyStore();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
after(() => {
|
|
28
|
-
try {
|
|
29
|
-
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
30
|
-
} catch {
|
|
31
|
-
// ignore cleanup errors
|
|
32
|
-
}
|
|
33
|
-
resetPolicyStore();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// --- Session Epoch Tests ---
|
|
37
|
-
describe("Session epochs", () => {
|
|
38
|
-
it("should track session epochs separately", async () => {
|
|
39
|
-
const store = getPolicyStore();
|
|
40
|
-
const session1 = "session-1-" + randomUUID().slice(0, 8);
|
|
41
|
-
const session2 = "session-2-" + randomUUID().slice(0, 8);
|
|
42
|
-
|
|
43
|
-
// Create a manifest
|
|
44
|
-
const manifest: PolicyManifest = {
|
|
45
|
-
revision: "abc123",
|
|
46
|
-
projectRoot: TEST_DIR,
|
|
47
|
-
trust: "unknown",
|
|
48
|
-
coverage: "complete",
|
|
49
|
-
sources: [],
|
|
50
|
-
loadedAt: Date.now(),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Note delivery for session 1
|
|
54
|
-
const receipt1 = store.noteDelivered(session1, manifest, "system_prompt");
|
|
55
|
-
assert.strictEqual(receipt1.sessionId, session1);
|
|
56
|
-
|
|
57
|
-
// Session 2 should NOT have a receipt
|
|
58
|
-
const receipt2 = store.getReceipt(session2, TEST_DIR);
|
|
59
|
-
assert.strictEqual(receipt2, null);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should not leak receipts between sessions after reset", async () => {
|
|
63
|
-
const store = getPolicyStore();
|
|
64
|
-
const sessionId = "session-reset-" + randomUUID().slice(0, 8);
|
|
65
|
-
|
|
66
|
-
const manifest: PolicyManifest = {
|
|
67
|
-
revision: "abc123",
|
|
68
|
-
projectRoot: TEST_DIR,
|
|
69
|
-
trust: "unknown",
|
|
70
|
-
coverage: "complete",
|
|
71
|
-
sources: [],
|
|
72
|
-
loadedAt: Date.now(),
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Deliver to session
|
|
76
|
-
store.noteDelivered(sessionId, manifest, "system_prompt");
|
|
77
|
-
|
|
78
|
-
// Clear session
|
|
79
|
-
store.clearSession(sessionId);
|
|
80
|
-
|
|
81
|
-
// Receipt should be gone
|
|
82
|
-
const receipt = store.getReceipt(sessionId, TEST_DIR);
|
|
83
|
-
assert.strictEqual(receipt, null);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// --- Source Change Tests ---
|
|
88
|
-
describe("Source changes", () => {
|
|
89
|
-
it("should invalidate receipts when AGENTS.md changes", async () => {
|
|
90
|
-
const store = getPolicyStore();
|
|
91
|
-
const sessionId = "session-change-" + randomUUID().slice(0, 8);
|
|
92
|
-
|
|
93
|
-
// Write initial content
|
|
94
|
-
writeFileSync(AGENTS_MD, "# Original Agents\n\nFollow the rules.", "utf8");
|
|
95
|
-
|
|
96
|
-
const loader = new PolicyLoader({
|
|
97
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Load and deliver
|
|
101
|
-
const manifest1 = await loader.load(TEST_DIR);
|
|
102
|
-
store.noteDelivered(sessionId, manifest1, "system_prompt");
|
|
103
|
-
|
|
104
|
-
// Modify file
|
|
105
|
-
writeFileSync(AGENTS_MD, "# Updated Agents\n\nDifferent rules.", "utf8");
|
|
106
|
-
|
|
107
|
-
// Invalidate cache
|
|
108
|
-
loader.invalidateCache(TEST_DIR);
|
|
109
|
-
|
|
110
|
-
// Load new manifest
|
|
111
|
-
const manifest2 = await loader.load(TEST_DIR);
|
|
112
|
-
|
|
113
|
-
// Revision should be different
|
|
114
|
-
assert.notStrictEqual(manifest1.revision, manifest2.revision);
|
|
115
|
-
|
|
116
|
-
// Old receipt should NOT cover new manifest
|
|
117
|
-
const hasCoverage = store.hasValidReceipt(sessionId, manifest2);
|
|
118
|
-
assert.strictEqual(hasCoverage, false);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("should include RULES.md in sources", async () => {
|
|
122
|
-
// Write RULES.md
|
|
123
|
-
writeFileSync(RULES_MD, "# Rules\n\nThese are rules.", "utf8");
|
|
124
|
-
|
|
125
|
-
const loader = new PolicyLoader({
|
|
126
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const manifest = await loader.load(TEST_DIR);
|
|
130
|
-
|
|
131
|
-
// RULES.md should be included as advisory at minimum
|
|
132
|
-
const rulesSource = manifest.sources.find(s => s.path.includes("RULES.md"));
|
|
133
|
-
assert.ok(rulesSource, "RULES.md should be included in sources");
|
|
134
|
-
|
|
135
|
-
// Clean up
|
|
136
|
-
unlinkSync(RULES_MD);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// --- Bounded Delivery Tests ---
|
|
141
|
-
describe("Bounded delivery", () => {
|
|
142
|
-
it("should track exact revision and source coverage", async () => {
|
|
143
|
-
const store = getPolicyStore();
|
|
144
|
-
const sessionId = "session-exact-" + randomUUID().slice(0, 8);
|
|
145
|
-
|
|
146
|
-
writeFileSync(AGENTS_MD, "# Agents\n\nContent.", "utf8");
|
|
147
|
-
|
|
148
|
-
const loader = new PolicyLoader({
|
|
149
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const manifest = await loader.load(TEST_DIR);
|
|
153
|
-
|
|
154
|
-
// Note delivery with specific sections
|
|
155
|
-
const receipt = store.noteDelivered(sessionId, manifest, "tool", ["section-1"]);
|
|
156
|
-
|
|
157
|
-
assert.strictEqual(receipt.revision, manifest.revision);
|
|
158
|
-
assert.deepStrictEqual(receipt.sectionsDelivered, ["section-1"]);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("should reject acknowledgement of wrong revision", async () => {
|
|
162
|
-
const store = getPolicyStore();
|
|
163
|
-
const sessionId = "session-wrong-rev-" + randomUUID().slice(0, 8);
|
|
164
|
-
|
|
165
|
-
writeFileSync(AGENTS_MD, "# Agents v1\n\nContent.", "utf8");
|
|
166
|
-
|
|
167
|
-
const loader = new PolicyLoader({
|
|
168
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const manifest1 = await loader.load(TEST_DIR);
|
|
172
|
-
store.noteDelivered(sessionId, manifest1, "system_prompt");
|
|
173
|
-
|
|
174
|
-
// Update content
|
|
175
|
-
writeFileSync(AGENTS_MD, "# Agents v2\n\nDifferent content.", "utf8");
|
|
176
|
-
loader.invalidateCache(TEST_DIR);
|
|
177
|
-
const manifest2 = await loader.load(TEST_DIR);
|
|
178
|
-
|
|
179
|
-
// Old receipt should NOT cover new manifest
|
|
180
|
-
const hasCoverage = store.hasValidReceipt(sessionId, manifest2);
|
|
181
|
-
assert.strictEqual(hasCoverage, false);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// --- Trust Evaluation Tests ---
|
|
186
|
-
describe("Trust evaluation", () => {
|
|
187
|
-
it("should evaluate trust appropriately", async () => {
|
|
188
|
-
// Create a .git directory (indicates repository)
|
|
189
|
-
mkdirSync(join(TEST_DIR, ".git"), { recursive: true });
|
|
190
|
-
|
|
191
|
-
const loader = new PolicyLoader({
|
|
192
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const manifest = await loader.load(TEST_DIR);
|
|
196
|
-
|
|
197
|
-
// Trust should be evaluated
|
|
198
|
-
assert.ok(["trusted", "untrusted", "unknown"].includes(manifest.trust));
|
|
199
|
-
|
|
200
|
-
// Clean up
|
|
201
|
-
rmSync(join(TEST_DIR, ".git"), { recursive: true, force: true });
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// --- Compaction Recovery Tests ---
|
|
206
|
-
describe("Compaction recovery", () => {
|
|
207
|
-
it("should invalidate receipts on session_compact event", async () => {
|
|
208
|
-
const store = getPolicyStore();
|
|
209
|
-
const sessionId = "session-compact-" + randomUUID().slice(0, 8);
|
|
210
|
-
|
|
211
|
-
writeFileSync(AGENTS_MD, "# Agents\n\nContent.", "utf8");
|
|
212
|
-
|
|
213
|
-
const loader = new PolicyLoader({
|
|
214
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
const manifest = await loader.load(TEST_DIR);
|
|
218
|
-
store.noteDelivered(sessionId, manifest, "system_prompt");
|
|
219
|
-
|
|
220
|
-
// Simulate compaction: invalidate all
|
|
221
|
-
store.invalidateAll();
|
|
222
|
-
|
|
223
|
-
// Receipt should be gone
|
|
224
|
-
const receipt = store.getReceipt(sessionId, TEST_DIR);
|
|
225
|
-
assert.strictEqual(receipt, null);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// --- Nested Scope Tests ---
|
|
230
|
-
describe("Nested scope resolution", () => {
|
|
231
|
-
it("should load scoped rules for subdirectories", async () => {
|
|
232
|
-
// Create nested structure
|
|
233
|
-
mkdirSync(join(TEST_DIR, "packages", "my-pkg"), { recursive: true });
|
|
234
|
-
writeFileSync(AGENTS_MD, "# Root Agents\n\nRoot rules.", "utf8");
|
|
235
|
-
writeFileSync(join(TEST_DIR, "packages", "AGENTS.md"), "# Package Agents\n\nPackage rules.", "utf8");
|
|
236
|
-
|
|
237
|
-
const loader = new PolicyLoader({
|
|
238
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
const manifest = await loader.load(TEST_DIR);
|
|
242
|
-
|
|
243
|
-
// Should have both root and package rules
|
|
244
|
-
assert.ok(manifest.sources.length >= 2, "Should include both root and package rules");
|
|
245
|
-
|
|
246
|
-
// Clean up nested structure
|
|
247
|
-
rmSync(join(TEST_DIR, "packages"), { recursive: true, force: true });
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// --- Delivery Deduplication Tests ---
|
|
252
|
-
describe("Delivery deduplication", () => {
|
|
253
|
-
it("should not create duplicate receipts in same session", async () => {
|
|
254
|
-
const store = getPolicyStore();
|
|
255
|
-
const sessionId = "session-dedup-" + randomUUID().slice(0, 8);
|
|
256
|
-
|
|
257
|
-
writeFileSync(AGENTS_MD, "# Agents\n\nContent.", "utf8");
|
|
258
|
-
|
|
259
|
-
const loader = new PolicyLoader({
|
|
260
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
const manifest = await loader.load(TEST_DIR);
|
|
264
|
-
|
|
265
|
-
// First delivery
|
|
266
|
-
const receipt1 = store.noteDelivered(sessionId, manifest, "system_prompt");
|
|
267
|
-
|
|
268
|
-
// Second delivery should update, not create duplicate
|
|
269
|
-
const receipt2 = store.noteDelivered(sessionId, manifest, "system_prompt");
|
|
270
|
-
|
|
271
|
-
// Should be same session
|
|
272
|
-
assert.strictEqual(receipt1.sessionId, receipt2.sessionId);
|
|
273
|
-
|
|
274
|
-
// Should have same revision
|
|
275
|
-
assert.strictEqual(receipt1.revision, receipt2.revision);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// --- Partial Read Tracking Tests ---
|
|
280
|
-
describe("Partial read tracking", () => {
|
|
281
|
-
it("should track which sections were actually delivered", async () => {
|
|
282
|
-
const store = getPolicyStore();
|
|
283
|
-
const sessionId = "session-partial-" + randomUUID().slice(0, 8);
|
|
284
|
-
|
|
285
|
-
writeFileSync(AGENTS_MD, "# Agents\n\n## Section 1\n\nContent 1.\n\n## Section 2\n\nContent 2.", "utf8");
|
|
286
|
-
|
|
287
|
-
const loader = new PolicyLoader({
|
|
288
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
const manifest = await loader.load(TEST_DIR);
|
|
292
|
-
|
|
293
|
-
// Note partial delivery (only section 1)
|
|
294
|
-
const receipt = store.noteDelivered(sessionId, manifest, "tool", ["section-1"]);
|
|
295
|
-
assert.deepStrictEqual(receipt.sectionsDelivered, ["section-1"]);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// --- Full Policy Text Delivery Tests ---
|
|
300
|
-
describe("Full policy text delivery", () => {
|
|
301
|
-
it("should compute full policy text after revision change", async () => {
|
|
302
|
-
writeFileSync(AGENTS_MD, "# Full Agents\n\n## Rule 1\n\nContent 1.\n\n## Rule 2\n\nContent 2.", "utf8");
|
|
303
|
-
|
|
304
|
-
const loader = new PolicyLoader({
|
|
305
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
const manifest = await loader.load(TEST_DIR);
|
|
309
|
-
|
|
310
|
-
// Full text should include actual content, not just contract pointers
|
|
311
|
-
const { renderFullPolicyText } = await import("../dist/index.js");
|
|
312
|
-
const fullText = renderFullPolicyText(manifest);
|
|
313
|
-
|
|
314
|
-
assert.ok(fullText.includes("Full Agents"), "Should include source title");
|
|
315
|
-
assert.ok(fullText.includes("Rule 1"), "Should include section heading");
|
|
316
|
-
assert.ok(fullText.includes("Content 1"), "Should include actual content");
|
|
317
|
-
assert.ok(fullText.includes("revision="), "Should include revision info");
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it("should detect when full policy exceeds size limit", async () => {
|
|
321
|
-
const loader = new PolicyLoader({
|
|
322
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
const manifest = await loader.load(TEST_DIR);
|
|
326
|
-
const { checkPolicyTextSize } = await import("../dist/index.js");
|
|
327
|
-
|
|
328
|
-
// With normal-sized content, should fit in 100KB limit
|
|
329
|
-
const result = checkPolicyTextSize(manifest, 100 * 1024);
|
|
330
|
-
assert.strictEqual(result.fits, true, "Normal policy should fit in 100KB");
|
|
331
|
-
|
|
332
|
-
// With very small limit, should report overflow
|
|
333
|
-
const smallResult = checkPolicyTextSize(manifest, 10);
|
|
334
|
-
assert.strictEqual(smallResult.fits, false, "Should report when limit is too small");
|
|
335
|
-
assert.ok(smallResult.reason?.includes("exceeds limit"), "Should explain overflow");
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
// --- Scope Separation Tests ---
|
|
340
|
-
describe("Scope separation", () => {
|
|
341
|
-
it("should NOT include harness rules when working outside harness repo", async () => {
|
|
342
|
-
// Create a harness rules file in a different location
|
|
343
|
-
const harnessRulesPath = join(TEST_DIR, "harness-rules", "AGENTS.md");
|
|
344
|
-
mkdirSync(dirname(harnessRulesPath), { recursive: true });
|
|
345
|
-
writeFileSync(harnessRulesPath, "# Harness Rules\n\nThese are harness-specific rules.", "utf8");
|
|
346
|
-
|
|
347
|
-
// Working in a different directory (not the harness repo)
|
|
348
|
-
const userProjectDir = join(TEST_DIR, "user-project");
|
|
349
|
-
mkdirSync(userProjectDir, { recursive: true });
|
|
350
|
-
|
|
351
|
-
const loader = new PolicyLoader({
|
|
352
|
-
harnessRulesPath: new URL(`file://${harnessRulesPath}`),
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
const manifest = await loader.load(userProjectDir);
|
|
356
|
-
|
|
357
|
-
// Harness rules should NOT be included since we're not in the harness repo
|
|
358
|
-
const harnessSources = manifest.sources.filter(s => s.harnessOwned);
|
|
359
|
-
assert.strictEqual(harnessSources.length, 0, "Harness rules should not apply outside harness repo");
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it("should include harness rules when working inside harness repo", async () => {
|
|
363
|
-
// Create a harness rules file
|
|
364
|
-
writeFileSync(AGENTS_MD, "# Harness Rules\n\nThese are harness-specific rules.", "utf8");
|
|
365
|
-
|
|
366
|
-
const harnessDir = TEST_DIR; // The harness rules are in this directory
|
|
367
|
-
|
|
368
|
-
const loader = new PolicyLoader({
|
|
369
|
-
harnessRulesPath: new URL(`file://${AGENTS_MD}`),
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// Working in the harness directory itself
|
|
373
|
-
const manifest = await loader.load(harnessDir);
|
|
374
|
-
|
|
375
|
-
// Harness rules SHOULD be included since we're in the harness repo
|
|
376
|
-
const harnessSources = manifest.sources.filter(s => s.harnessOwned);
|
|
377
|
-
assert.ok(harnessSources.length > 0, "Harness rules should apply inside harness repo");
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
});
|