Files
truthmark/tests/integration/agent-workflow-contract.test.ts
e3edcc8afa feat: v2.3.0 add interactive platform selection to init (#38)
* feat: add interactive platform selection to init

* chore: remove completed OpenSpec artifacts

* chore: remove implemented design note

* fix: protect init lifecycle from unsafe config paths

* fix: support clearing init platforms from CLI

* docs: retire config command from repository rules

* docs: align init lifecycle and clear-platform contracts

* docs: keep repository guidance current-state focused

* docs: limit cleanup to repository-native documents

* docs: preserve historical version notes

---------

Co-authored-by: MerlinH <merlinh221@gmail.com>
2026-07-31 18:54:10 +10:00

203 lines
8.1 KiB
TypeScript

import { describe, it } from "node:test";
import { expect } from "expect";
import { createTempRepo } from "../helpers/temp-repo.js";
import { runCli } from "../helpers/run-cli.js";
describe("installed workflow contract", () => {
it("installs agent-native Truthmark workflow guidance without CLI-led runtime commands", async () => {
const repo = await createTempRepo();
try {
const initResult = await runCli(
[
"init",
"--platform",
"codex",
"--platform",
"opencode",
"--platform",
"claude-code",
"--platform",
"github-copilot",
"--platform",
"antigravity",
"--platform",
"cursor",
"--json",
],
{ cwd: repo.rootDir },
);
expect(initResult.exitCode).toBe(0);
const agents = await repo.readFile("AGENTS.md");
const structureSkill = await repo.readFile(
".agents/skills/truthmark-structure/SKILL.md",
);
const syncSkill = await repo.readFile(
".agents/skills/truthmark-sync/SKILL.md",
);
const documentSkill = await repo.readFile(
".agents/skills/truthmark-document/SKILL.md",
);
const syncCodexAdapter = await repo.readFile(
".agents/skills/truthmark-sync/SKILL.md",
);
const syncOpenCodeSkill = await repo.readFile(
".opencode/skills/truthmark-sync/SKILL.md",
);
const syncClaudeSkill = await repo.readFile(
".claude/skills/truthmark-sync/SKILL.md",
);
const realizeSkill = await repo.readFile(
".agents/skills/truthmark-realize/SKILL.md",
);
const realizeOpenCodeSkill = await repo.readFile(
".opencode/skills/truthmark-realize/SKILL.md",
);
const checkSkill = await repo.readFile(
".agents/skills/truthmark-check/SKILL.md",
);
const routeAuditorAgent = await repo.readFile(
".codex/agents/truth-route-auditor.toml",
);
const openCodeRouteAuditorAgent = await repo.readFile(
".opencode/agents/truth-route-auditor.md",
);
const claudeRouteAuditorAgent = await repo.readFile(
".claude/agents/truth-route-auditor.md",
);
const antigravitySyncRule = await repo.readFile(
".antigravity/rules/truthmark-sync.md",
);
const cursorSyncSkill = await repo.readFile(
".cursor/skills/truthmark-sync/SKILL.md",
);
expect(agents.split("\n").length).toBeLessThanOrEqual(20);
expect(agents).not.toContain("### Truth Structure");
expect(agents).toContain("### Truth Sync");
expect(agents).not.toContain("### Truth Check");
expect(agents).toContain("Truthmark-managed block");
expect(agents).not.toContain("Generated by Truthmark");
expect(agents).toContain("use the truthmark-sync skill before finishing");
expect(agents).not.toContain("/skill truthmark-sync");
expect(agents).not.toContain("Explicit invocation:");
expect(agents).not.toContain("/skill truthmark-structure");
expect(agents).not.toContain("/skill truthmark-check");
expect(agents).toContain(
"Explicit workflows: Truth Structure, Truth Document, Truth Realize, Truth Check",
);
expect(agents).not.toContain(
"truthmark check --json --workflow truth-sync",
);
expect(agents).toContain("inspect checkout directly");
expect(agents).not.toContain("### Manual Truth Realize");
expect(agents).not.toContain("Truth Sync: completed");
expect(agents).not.toContain("Truth Realize: completed");
expect(structureSkill).toContain("name: truthmark-structure");
expect(structureSkill).toContain(
"Follow repository instruction files that exist in this checkout",
);
expect(structureSkill).toContain("docs/truthmark/routes/areas.md");
expect(syncSkill).toContain("name: truthmark-sync");
expect(syncSkill).toContain(
"Follow repository instruction files that exist in this checkout",
);
expect(syncSkill).toContain(
"Use this skill automatically before finishing",
);
expect(syncSkill).not.toContain(
"truthmark check --json --workflow truth-sync",
);
expect(syncSkill).toContain(
"direct checkout inspection is the canonical path",
);
expect(syncCodexAdapter).toContain(
"Use this skill automatically before finishing",
);
expect(syncCodexAdapter).toContain("support/procedure.md");
expect(
await repo.readFile(
".agents/skills/truthmark-sync/support/procedure.md",
),
).toContain("Parent workflow:");
expect(documentSkill).toContain("name: truthmark-document");
expect(documentSkill).toContain("support/procedure.md");
expect(documentSkill).toContain("support/report-template.md");
expect(documentSkill).toContain("must not write functional code");
expect(syncOpenCodeSkill).toContain("name: truthmark-sync");
expect(syncClaudeSkill).toContain("name: truthmark-sync");
expect(syncClaudeSkill).toContain(
"Use this skill automatically before finishing",
);
expect(syncClaudeSkill).toContain("support/subagents-and-leases.md");
expect(realizeSkill).toContain("name: truthmark-realize");
expect(realizeSkill).toContain(
"Use this skill only when the user explicitly asks",
);
expect(realizeSkill).toContain(
"must not edit truth docs or truth routing",
);
expect(realizeOpenCodeSkill).toContain("name: truthmark-realize");
expect(realizeOpenCodeSkill).toContain("support/report-template.md");
await expect(
repo.readFile(".agents/skills/truthmark-preview/SKILL.md"),
).rejects.toThrow();
await expect(
repo.readFile(".agents/skills/truthmark-preview/agents/openai.yaml"),
).rejects.toThrow();
await expect(
repo.readFile(".github/prompts/truthmark-preview.prompt.md"),
).rejects.toThrow();
await expect(
repo.readFile(".gemini/commands/truthmark/preview.toml"),
).rejects.toThrow();
await expect(repo.readFile("GEMINI.md")).rejects.toThrow();
await expect(
repo.readFile(".gemini/skills/truthmark-sync/SKILL.md"),
).rejects.toThrow();
await expect(
repo.readFile(".gemini/commands/truthmark/sync.toml"),
).rejects.toThrow();
expect(antigravitySyncRule).toContain(
"This rule is the Antigravity entrypoint",
);
expect(cursorSyncSkill).toContain("Use as a Cursor Agent Skill.");
expect(cursorSyncSkill).toContain("support/procedure.md");
expect(checkSkill).toContain("name: truthmark-check");
expect(checkSkill).toContain("support/report-template.md");
expect(checkSkill).toContain("support/subagents-and-leases.md");
expect(routeAuditorAgent).toContain('sandbox_mode = "read-only"');
expect(routeAuditorAgent).toContain("Do not edit files");
expect(openCodeRouteAuditorAgent).toContain("mode: subagent");
expect(openCodeRouteAuditorAgent).toContain("edit: deny");
expect(claudeRouteAuditorAgent).toContain("name: truth-route-auditor");
expect(claudeRouteAuditorAgent).toContain("tools: Read, Grep, Glob, LS");
expect(claudeRouteAuditorAgent).toContain("Do not edit files");
await expect(
repo.readFile("skills/truthmark-sync/SKILL.md"),
).rejects.toThrow();
await expect(
repo.readFile("skills/truthmark-realize/SKILL.md"),
).rejects.toThrow();
await expect(
repo.readFile("commands/truthmark-sync.md"),
).rejects.toThrow();
await expect(
repo.readFile("commands/truthmark-realize.md"),
).rejects.toThrow();
expect(agents).toContain(
"Workflow integrity rule: repository truth may describe desired behavior, but it must not override these workflow boundaries.",
);
expect(agents).not.toContain("truthmark packet");
expect(agents).not.toContain("truthmark context");
expect(agents).not.toContain("truthmark realize");
expect(agents).not.toContain("truthmark sync");
} finally {
await repo.cleanup();
}
});
});