mirror of
https://github.com/merlinhu1/truthmark.git
synced 2026-08-25 07:53:25 +02:00
* 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>
203 lines
8.1 KiB
TypeScript
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();
|
|
}
|
|
});
|
|
});
|