feat: add takt as a target tool (map rulesync features to TAKT facets)#1539
feat: add takt as a target tool (map rulesync features to TAKT facets)#1539dyoshikawa merged 2 commits intomainfrom
Conversation
- Map rulesync features to TAKT facet directories:
- subagents -> personas/, rules -> policies/ (default),
commands -> instructions/, skills -> instructions/ (default)
- Optional takt.facet frontmatter routes rules to knowledge/output-contracts
and skills to knowledge/output-contracts; unknown values raise validation errors
- Always emit plain Markdown (frontmatter dropped); preserve source filename stem
- Optional takt.name allows renaming the emitted stem to escape collisions
(validated against path-traversal characters)
- Detect cross-feature collisions in .takt/facets/instructions/ between
commands and skills: log a warning naming both sources and skip writes
without aborting the run
- Support both project (.takt/facets/) and global (~/.takt/facets/) scopes
- Update gitignore registry to cover .takt/{runs,tasks,.cache}/ and
facet directories shared across features
- Sync README, docs/reference/{supported-tools,file-formats}.md, and
add docs/tools/takt.md
- Add happy-path e2e cases for every (takt x feature) cell in both
project and global modes plus a dedicated collision e2e
Closes #1536
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new takt tool target, generating Rulesync sources into TAKT’s faceted-prompting directory structure under .takt/facets/ (and ~/.takt/facets/ in global mode), including facet routing via takt.facet, optional renaming via takt.name, and collision handling for shared instruction facets.
Changes:
- Register
taktas a tool target across processors, schemas, docs, and spelling config. - Implement TAKT generators for rules/commands/subagents/skills + shared TAKT helpers and tests.
- Add TAKT-specific collision detection between commands and skills writing into
.takt/facets/instructions/, plus e2e coverage and gitignore registry entries.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/tool-targets.ts | Adds takt to supported tool targets list. |
| src/types/tool-targets.test.ts | Updates tool targets snapshot/expectations. |
| src/lib/generate.ts | Adds TAKT command/skill collision pre-scan and filtering hooks in generation flow. |
| src/features/takt-shared.ts | Introduces shared TAKT validation/utilities (takt.name safety, takt.facet resolution). |
| src/features/takt-shared.test.ts | Unit tests for TAKT shared helpers. |
| src/features/subagents/takt-subagent.ts | Implements TAKT subagent emission to .takt/facets/personas/*.md. |
| src/features/subagents/takt-subagent.test.ts | Unit tests for TAKT subagent behavior. |
| src/features/subagents/subagents-processor.ts | Registers takt subagent factory/metadata. |
| src/features/subagents/subagents-processor.test.ts | Updates supported-target expectations to include takt. |
| src/features/skills/takt-skill.ts | Implements TAKT skills emission as flat facet files (instructions/knowledge/output-contracts). |
| src/features/skills/takt-skill.test.ts | Unit tests for TAKT skill mapping and guards. |
| src/features/skills/skills-processor.ts | Registers takt skill factory/metadata. |
| src/features/skills/skills-processor.test.ts | Updates supported-target expectations to include takt. |
| src/features/skills/rulesync-skill.ts | Adds optional takt frontmatter keys to Rulesync skill schema/types. |
| src/features/rules/takt-rule.ts | Implements TAKT rules emission into facet dirs with takt.facet + takt.name. |
| src/features/rules/takt-rule.test.ts | Unit tests for TAKT rule mapping and validation. |
| src/features/rules/rulesync-rule.ts | Adds optional takt frontmatter keys to Rulesync rule schema. |
| src/features/rules/rules-processor.ts | Registers takt rule factory/metadata. |
| src/features/rules/rules-processor.test.ts | Updates supported-target expectations to include takt. |
| src/features/commands/takt-command.ts | Implements TAKT command emission to .takt/facets/instructions/*.md. |
| src/features/commands/takt-command.test.ts | Unit tests for TAKT command mapping and validation. |
| src/features/commands/commands-processor.ts | Registers takt command factory/metadata. |
| src/features/commands/commands-processor.test.ts | Updates supported-target expectations to include takt. |
| src/e2e/e2e-takt.spec.ts | Adds e2e coverage for command/skill instruction-facet collision behavior. |
| src/e2e/e2e-subagents.spec.ts | Adds TAKT to subagent e2e matrix (project + global). |
| src/e2e/e2e-skills.spec.ts | Adds TAKT to skills e2e matrix (project + global). |
| src/e2e/e2e-rules.spec.ts | Adds TAKT to rules e2e matrix (project + global). |
| src/e2e/e2e-commands.spec.ts | Adds TAKT to commands e2e matrix (project + global). |
| src/cli/commands/gitignore-entries.ts | Adds TAKT gitignore entries and dedupes exported entry list. |
| src/cli/commands/gitignore-entries.test.ts | Adjusts tests for intentional cross-feature gitignore entry reuse + deduped export. |
| skills/rulesync/supported-tools.md | Documents takt in supported tools matrix (skill docs sync source). |
| skills/rulesync/file-formats.md | Documents takt frontmatter keys in file format reference (skill docs sync source). |
| docs/tools/takt.md | Adds dedicated TAKT tool documentation page. |
| docs/reference/supported-tools.md | Documents takt in supported tools matrix. |
| docs/reference/file-formats.md | Documents takt frontmatter keys in file format reference. |
| cspell.json | Adds TAKT-related spelling dictionary entries. |
| README.md | Adds TAKT to the supported tools matrix. |
Comments suppressed due to low confidence (1)
src/lib/generate.ts:566
- For the
takttarget, skills are emitted as flat.mdfiles under facet dirs, but this path still goes throughprocessDirFeatureGeneration(directory-based). That means--deletecannot remove orphaned TAKT skill files (it only deletes directories), and collision filtering here may leave previously-generated colliding files on disk. Consider handling TAKT skills as file-based output (AiFile +writeAiFiles/removeOrphanAiFiles) or adding a TAKT-specific orphan-file cleanup pass that enumerates.takt/facets/{instructions,knowledge,output-contracts}/*.mdand removes non-generated stems.
| /** | ||
| * Override: TAKT skills emit a single flat file under `relativeDirPath`, | ||
| * not a nested directory keyed by `dirName`. Drop `dirName` from the path. | ||
| * | ||
| * Preserves the same path-traversal guard as `AiDir.getDirPath` so a | ||
| * malicious `relativeDirPath` cannot escape `baseDir`. | ||
| */ | ||
| override getDirPath(): string { | ||
| const fullPath = join(this.baseDir, this.relativeDirPath); | ||
|
|
||
| const resolvedFull = resolve(fullPath); | ||
| const resolvedBase = resolve(this.baseDir); | ||
| const rel = relative(resolvedBase, resolvedFull); | ||
|
|
||
| if (rel.startsWith("..") || path.isAbsolute(rel)) { | ||
| throw new Error( | ||
| `Path traversal detected: Final path escapes baseDir. ` + | ||
| `baseDir="${this.baseDir}", relativeDirPath="${this.relativeDirPath}"`, | ||
| ); | ||
| } | ||
|
|
||
| return fullPath; | ||
| } |
There was a problem hiding this comment.
Overriding getDirPath() to return the facet directory (dropping dirName) makes multiple TaktSkill instances share the same dirPath. This breaks the DirFeatureProcessor invariants: orphan cleanup can only delete directories (so old *.md facet files are never removed), and forDeletion() cannot represent deletable units. To support --delete and reliable diffs, TAKT skills likely need a file-based representation/processor (AiFile) or a custom delete implementation that operates on individual facet files rather than directories.
| static getSettablePaths({ | ||
| global, | ||
| excludeToolDir, | ||
| }: { | ||
| global?: boolean; | ||
| excludeToolDir?: boolean; | ||
| } = {}): ToolRuleSettablePaths | ToolRuleSettablePathsGlobal { | ||
| if (global) { | ||
| return { | ||
| root: { | ||
| relativeDirPath: buildToolPath( | ||
| ".takt", | ||
| join("facets", DEFAULT_TAKT_RULE_DIR), | ||
| excludeToolDir, | ||
| ), | ||
| relativeFilePath: "overview.md", | ||
| }, | ||
| }; | ||
| } | ||
| return { | ||
| nonRoot: { | ||
| relativeDirPath: buildToolPath( | ||
| ".takt", | ||
| join("facets", DEFAULT_TAKT_RULE_DIR), | ||
| excludeToolDir, | ||
| ), | ||
| }, | ||
| }; |
There was a problem hiding this comment.
getSettablePaths() only points rule discovery/deletion at .takt/facets/policies, but TAKT rules can also emit under .takt/facets/knowledge and .takt/facets/output-contracts via takt.facet. As a result, --delete and rulesync import won’t see those non-default facet files, leaving orphans when a rule changes facet. Consider setting nonRoot.relativeDirPath to .takt/facets (so the existing glob picks up all facets) and adjusting fromFile()/import mapping accordingly; also decide how root rule discovery should behave if a root rule uses a non-default facet.
| "takt", | ||
| { | ||
| class: TaktSkill, | ||
| meta: { supportsProject: true, supportsSimulated: false, supportsGlobal: true }, | ||
| }, |
There was a problem hiding this comment.
Registering takt here implies the standard SkillsProcessor behaviors (directory discovery for import and directory-based orphan deletion). But TaktSkill emits flat facet files and TaktSkill.fromDir() throws, so rulesync import --targets takt --features skills will likely just report “No skill directories found” and skip rather than throwing the explicit “not supported” error described in the PR, and --delete won’t be able to remove orphan facet files. Consider special-casing takt skills in the import/generate pipelines (or introducing a file-based skills processor for takt) before advertising full skills support.
- Add takt: frontmatter block to RulesyncCommand and RulesyncSubagent schemas so takt.facet/takt.name typos are caught at parse time, matching the existing rule/skill schemas. - TaktSkill.getRelativePathFromCwd now routes through toPosixPath so reported paths use forward slashes on Windows. - Surface previously-swallowed conversion errors in the TAKT collision pre-pass via debug logging instead of silent catch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@dyoshikawa Thank you! |
Summary
Add a new target tool
taktto rulesync so that rulesync source files (rules, subagents, commands, skills) are generated into the TAKT faceted-prompting directories under.takt/facets/(project) and~/.takt/facets/(global).Feature mapping
takt.facetoverridessubagentspersonas/personaonlyrulespolicies/policy,knowledge,output-contractcommandsinstructions/instructiononlyskillsinstructions/instruction,knowledge,output-contractHighlights
takt.namelets users rename the emitted stem to escape collisions; validated against path-traversal characters..takt/facets/instructions/between commands and skills: log a warning naming both sources and skip writes without aborting the rest of the run.gitignoreregistry covers.takt/{runs,tasks,.cache}/and shared facet directories under bothcommands/skillsandrules/skills.README.md,docs/reference/{supported-tools,file-formats}.md, and newdocs/tools/takt.mdkept in sync.Out of scope (permanently)
.takt/workflows/*.yaml),config.yaml, runtime state (tasks/,runs/),repertoirepackaging.rulesync importfor TAKT skill files: throws an explicit "Importing existing TAKT facet files into rulesync is not supported" because frontmatter is dropped on generate (lossy by design).Closes #1536
Test plan
pnpm cicheckpasses (5155 unit + 201 file + content checks)pnpm dev generate --targets taktproduces files under.takt/facets/{personas,policies,instructions,knowledge,output-contracts}/takt.nameandTaktSkill.getDirPath🤖 Generated with Claude Code