@open-agent-toolkit/cli 0.2.59 → 0.2.63
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/assets/agents/oat-phase-implementer.md +27 -4
- package/assets/agents/oat-reviewer.md +25 -14
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/config-and-local-state.md +1 -0
- package/assets/docs/cli-utilities/configuration.md +10 -8
- package/assets/docs/cli-utilities/project-log.md +16 -0
- package/assets/docs/cli-utilities/workflow-gates.md +127 -19
- package/assets/docs/provider-sync/commands.md +3 -0
- package/assets/docs/provider-sync/instruction-sync.md +107 -0
- package/assets/docs/reference/cli-reference.md +26 -9
- package/assets/docs/reference/oat-directory-structure.md +33 -31
- package/assets/docs/workflows/ideas/index.md +1 -1
- package/assets/docs/workflows/index.md +1 -0
- package/assets/docs/workflows/projects/artifacts.md +24 -3
- package/assets/docs/workflows/projects/hill-checkpoints.md +21 -0
- package/assets/docs/workflows/projects/implementation-execution.md +5 -0
- package/assets/docs/workflows/projects/lifecycle.md +169 -7
- package/assets/docs/workflows/projects/picking-up-projects.md +14 -0
- package/assets/docs/workflows/projects/pr-flow.md +2 -0
- package/assets/docs/workflows/projects/reviews.md +1 -1
- package/assets/docs/workflows/projects/state-machine.md +20 -0
- package/assets/docs/workflows/skills/explainer-kit.md +10 -4
- package/assets/docs/workflows/skills/index.md +2 -1
- package/assets/docs/workflows/skills/repo-improve.md +15 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-brainstorm/SKILL.md +61 -12
- package/assets/skills/oat-docs/SKILL.md +13 -8
- package/assets/skills/oat-doctor/SKILL.md +3 -3
- package/assets/skills/oat-explainer-kit/SKILL.md +14 -1
- package/assets/skills/oat-explainer-kit/references/config-contract.md +12 -0
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +57 -10
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +28 -5
- package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +371 -0
- package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +123 -1
- package/assets/skills/oat-pjm-review-backlog/SKILL.md +2 -2
- package/assets/skills/oat-project-autonomous/SKILL.md +23 -9
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +164 -150
- package/assets/skills/oat-project-capture/SKILL.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +134 -4
- package/assets/skills/oat-project-discover/SKILL.md +6 -5
- package/assets/skills/oat-project-document/SKILL.md +11 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-implement/SKILL.md +3 -3
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +144 -21
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-implement/references/phase-execution.md +16 -1
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +19 -1
- package/assets/skills/oat-project-import-plan/SKILL.md +47 -3
- package/assets/skills/oat-project-lite/SKILL.md +467 -0
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +331 -0
- package/assets/skills/oat-project-next/SKILL.md +75 -16
- package/assets/skills/oat-project-plan/SKILL.md +44 -6
- package/assets/skills/oat-project-plan-writing/SKILL.md +6 -3
- package/assets/skills/oat-project-pr-final/SKILL.md +33 -7
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-pr-progress/SKILL.md +3 -3
- package/assets/skills/oat-project-progress/SKILL.md +27 -5
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +3 -1
- package/assets/skills/oat-project-quick-start/SKILL.md +264 -4
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-review-provide/SKILL.md +25 -6
- package/assets/skills/oat-project-summary/SKILL.md +61 -26
- package/assets/skills/oat-repo-improve/SKILL.md +40 -5
- package/assets/skills/oat-repo-improve/references/plan-template.md +84 -7
- package/assets/templates/plan-lite.md +165 -0
- package/assets/templates/plan.md +1 -1
- package/assets/templates/state.md +1 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +401 -18
- package/dist/commands/gate/index.d.ts +3 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +699 -211
- package/dist/commands/init/tools/shared/skill-script-references.d.ts +126 -0
- package/dist/commands/init/tools/shared/skill-script-references.d.ts.map +1 -0
- package/dist/commands/init/tools/shared/skill-script-references.js +311 -0
- package/dist/commands/instructions/instructions.types.d.ts +63 -0
- package/dist/commands/instructions/instructions.types.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.d.ts +51 -2
- package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.js +201 -4
- package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
- package/dist/commands/instructions/sync/sync.js +12 -1
- package/dist/commands/instructions/validate/validate.d.ts.map +1 -1
- package/dist/commands/instructions/validate/validate.js +12 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/project/log/append.d.ts +195 -0
- package/dist/commands/project/log/append.d.ts.map +1 -1
- package/dist/commands/project/log/append.js +1034 -11
- package/dist/commands/project/new/index.d.ts +3 -2
- package/dist/commands/project/new/index.d.ts.map +1 -1
- package/dist/commands/project/new/index.js +2 -1
- package/dist/commands/project/new/scaffold.d.ts +5 -3
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +38 -10
- package/dist/commands/project/promote/index.d.ts +2 -0
- package/dist/commands/project/promote/index.d.ts.map +1 -0
- package/dist/commands/project/promote/index.js +1 -0
- package/dist/commands/project/promote/promote.d.ts +47 -0
- package/dist/commands/project/promote/promote.d.ts.map +1 -0
- package/dist/commands/project/promote/promote.js +322 -0
- package/dist/commands/project/split/run.d.ts.map +1 -1
- package/dist/commands/project/split/run.js +8 -1
- package/dist/commands/project/validate-plan/index.d.ts.map +1 -1
- package/dist/commands/project/validate-plan/index.js +25 -1
- package/dist/commands/project/validate-plan/validate-plan.d.ts +8 -0
- package/dist/commands/project/validate-plan/validate-plan.d.ts.map +1 -1
- package/dist/commands/project/validate-plan/validate-plan.js +49 -0
- package/dist/commands/shared/frontmatter.d.ts +1 -1
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +1 -0
- package/dist/commands/state/generate.d.ts.map +1 -1
- package/dist/commands/state/generate.js +23 -0
- package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-manifest.js +2 -0
- package/dist/config/oat-config.d.ts +41 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +111 -0
- package/package.json +2 -2
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill-to-script reference integrity.
|
|
3
|
+
*
|
|
4
|
+
* A shipped skill may name a helper script through its installed destination,
|
|
5
|
+
* `.oat/scripts/<name>`. Nothing in the install path proves the pack that ships
|
|
6
|
+
* the skill also ships that script, so a rename or a pack move can leave a
|
|
7
|
+
* skill pointing at a file its own installation never materializes.
|
|
8
|
+
*
|
|
9
|
+
* This module supplies the join: a syntax-aware extractor for the reference
|
|
10
|
+
* spellings authored Markdown actually uses, a manifest-derived view of the
|
|
11
|
+
* shipped skill surface, and an owning-pack resolver. Callers compare the two
|
|
12
|
+
* and fail when a shipped skill references a script its owning pack does not
|
|
13
|
+
* ship.
|
|
14
|
+
*
|
|
15
|
+
* The shipped surface is derived from the pack manifest, never from the
|
|
16
|
+
* canonical `.agents/skills` directory listing: that listing is a superset that
|
|
17
|
+
* also holds repository-local authoring and utility skills no pack ships. Those
|
|
18
|
+
* directories are classified and reported, never resolved to a pack and never a
|
|
19
|
+
* failure by themselves.
|
|
20
|
+
*
|
|
21
|
+
* Scan boundary: `extractScriptReferences` takes any text, but the shipping
|
|
22
|
+
* caller feeds it authored Markdown only — every `**\/*.md` under a skill
|
|
23
|
+
* directory except the vendored `references/docs/` copies. That covers every
|
|
24
|
+
* reference in the tree today, since each of the six skill files naming
|
|
25
|
+
* `.oat/scripts` is a `SKILL.md`. A skill that ships a non-Markdown asset
|
|
26
|
+
* carrying a script reference would fall outside this scan, so widen the caller
|
|
27
|
+
* deliberately rather than assuming this module already sees it.
|
|
28
|
+
*/
|
|
29
|
+
import type { PackDefinition, PackName } from '../../../tools/shared/types.js';
|
|
30
|
+
/** Installed destination prefix produced by the manifest's `script()` helper. */
|
|
31
|
+
export declare const SCRIPT_DESTINATION_PREFIX = ".oat/scripts/";
|
|
32
|
+
/** One extracted reference, kept line-addressed so failures cite a location. */
|
|
33
|
+
export interface ScriptReference {
|
|
34
|
+
/** Manifest-comparable destination, e.g. `.oat/scripts/resolve-tracking.sh`. */
|
|
35
|
+
reference: string;
|
|
36
|
+
/** 1-based line number of the occurrence within the scanned text. */
|
|
37
|
+
line: number;
|
|
38
|
+
}
|
|
39
|
+
/** Authored text belonging to one skill, ready to be scanned. */
|
|
40
|
+
export interface SkillScriptSource {
|
|
41
|
+
/** Canonical skill name, as shipped by a pack. */
|
|
42
|
+
skill: string;
|
|
43
|
+
/** Display path used in failure messages. */
|
|
44
|
+
file: string;
|
|
45
|
+
/** File contents. */
|
|
46
|
+
text: string;
|
|
47
|
+
}
|
|
48
|
+
/** A shipped skill naming a script its owning pack does not ship. */
|
|
49
|
+
export interface ScriptReferenceViolation {
|
|
50
|
+
skill: string;
|
|
51
|
+
file: string;
|
|
52
|
+
line: number;
|
|
53
|
+
reference: string;
|
|
54
|
+
/** Every pack that ships the skill; membership in any one satisfies the check. */
|
|
55
|
+
packs: PackName[];
|
|
56
|
+
/** Script destinations those packs do ship, for an actionable message. */
|
|
57
|
+
shipped: string[];
|
|
58
|
+
}
|
|
59
|
+
/** How a canonical `.agents/skills` directory relates to the pack manifest. */
|
|
60
|
+
export type CanonicalSkillDirClass = 'shipped' | 'canonical-unshipped';
|
|
61
|
+
/** Split of canonical skill directories by manifest membership. */
|
|
62
|
+
export interface CanonicalSkillDirClassification {
|
|
63
|
+
shipped: string[];
|
|
64
|
+
canonicalUnshipped: string[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Extract every `.oat/scripts/<name>` reference from authored text.
|
|
68
|
+
*
|
|
69
|
+
* Scanning is line-by-line so each occurrence carries its own line number, and
|
|
70
|
+
* so a reference can never be assembled across a line break.
|
|
71
|
+
*
|
|
72
|
+
* A reference is returned essentially as authored. Nothing is truncated to a
|
|
73
|
+
* shipped-looking prefix, and the only edits are dropping the Markdown
|
|
74
|
+
* decoration around it — a closing emphasis run and at most one prose mark — so
|
|
75
|
+
* a malformed name reaches the manifest comparison intact and fails there
|
|
76
|
+
* rather than being normalized into a name that happens to exist.
|
|
77
|
+
*/
|
|
78
|
+
export declare function extractScriptReferences(text: string): ScriptReference[];
|
|
79
|
+
/**
|
|
80
|
+
* The union of every pack's skill assets: the surface the manifest claims to
|
|
81
|
+
* ship, which is what the contract checks.
|
|
82
|
+
*/
|
|
83
|
+
export declare function listShippedSkills(manifest?: readonly PackDefinition[]): string[];
|
|
84
|
+
/** Script destinations shipped by one pack. */
|
|
85
|
+
export declare function listPackScriptDestinations(pack: PackName, manifest?: readonly PackDefinition[]): string[];
|
|
86
|
+
/**
|
|
87
|
+
* Classify a canonical skill directory against the manifest.
|
|
88
|
+
*
|
|
89
|
+
* `canonical-unshipped` is an ordinary, expected state: repository-local
|
|
90
|
+
* authoring and utility skills live under `.agents/skills` without belonging to
|
|
91
|
+
* any pack. It is reported, never failed.
|
|
92
|
+
*/
|
|
93
|
+
export declare function classifyCanonicalSkillDir(name: string, manifest?: readonly PackDefinition[]): CanonicalSkillDirClass;
|
|
94
|
+
/** Classify a whole directory listing in one pass. */
|
|
95
|
+
export declare function classifyCanonicalSkillDirs(names: readonly string[], manifest?: readonly PackDefinition[]): CanonicalSkillDirClassification;
|
|
96
|
+
/**
|
|
97
|
+
* Shipped skills the manifest names but whose canonical directory is absent.
|
|
98
|
+
*
|
|
99
|
+
* The inverse of `classifyCanonicalSkillDirs`, and unlike an unshipped
|
|
100
|
+
* directory this *is* a failure: the manifest promises to install something the
|
|
101
|
+
* repository does not contain.
|
|
102
|
+
*/
|
|
103
|
+
export declare function findMissingShippedSkillDirs(existingDirs: readonly string[], manifest?: readonly PackDefinition[]): string[];
|
|
104
|
+
/**
|
|
105
|
+
* Every pack that ships `skillName`.
|
|
106
|
+
*
|
|
107
|
+
* Throws for a name no pack ships. That is a caller bug rather than a repository
|
|
108
|
+
* defect: callers drive from `listShippedSkills`, so an unshipped canonical
|
|
109
|
+
* directory never reaches here.
|
|
110
|
+
*
|
|
111
|
+
* A skill carried by more than one pack resolves to all of them, and membership
|
|
112
|
+
* in any one satisfies the reference check — the same shared-ownership rule the
|
|
113
|
+
* manifest applies to a script shipped by two packs under one `sharedOwner`.
|
|
114
|
+
*/
|
|
115
|
+
export declare function resolveOwningPack(skillName: string, manifest?: readonly PackDefinition[]): PackName[];
|
|
116
|
+
/**
|
|
117
|
+
* The contract itself: every script reference authored by a shipped skill must
|
|
118
|
+
* name a `kind: 'script'` destination of a pack that ships that skill.
|
|
119
|
+
*
|
|
120
|
+
* Sources for skills no pack ships must not be passed; drive callers from
|
|
121
|
+
* `listShippedSkills` so `resolveOwningPack` stays a caller-bug signal.
|
|
122
|
+
*/
|
|
123
|
+
export declare function findUnshippedScriptReferences(sources: readonly SkillScriptSource[], manifest?: readonly PackDefinition[]): ScriptReferenceViolation[];
|
|
124
|
+
/** Render one violation so the failure names the skill, reference, and pack. */
|
|
125
|
+
export declare function formatScriptReferenceViolation({ skill, file, line, reference, packs, shipped, }: ScriptReferenceViolation): string;
|
|
126
|
+
//# sourceMappingURL=skill-script-references.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-script-references.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-script-references.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAEV,cAAc,EACd,QAAQ,EACT,MAAM,8BAA8B,CAAC;AAEtC,iFAAiF;AACjF,eAAO,MAAM,yBAAyB,kBAAkB,CAAC;AAiKzD,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qEAAqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,+EAA+E;AAC/E,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,qBAAqB,CAAC;AAEvE,mEAAmE;AACnE,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CA4BvE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,MAAM,EAAE,CAUV;AAED,+CAA+C;AAC/C,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,QAAQ,EACd,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,MAAM,EAAE,CAQV;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,sBAAsB,CAIxB;AAED,sDAAsD;AACtD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,+BAA+B,CAOjC;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,MAAM,EAAE,CAGV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,QAAQ,EAAE,CAgBZ;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,wBAAwB,EAAE,CAkB5B;AAED,gFAAgF;AAChF,wBAAgB,8BAA8B,CAAC,EAC7C,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,KAAK,EACL,OAAO,GACR,EAAE,wBAAwB,GAAG,MAAM,CAInC"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill-to-script reference integrity.
|
|
3
|
+
*
|
|
4
|
+
* A shipped skill may name a helper script through its installed destination,
|
|
5
|
+
* `.oat/scripts/<name>`. Nothing in the install path proves the pack that ships
|
|
6
|
+
* the skill also ships that script, so a rename or a pack move can leave a
|
|
7
|
+
* skill pointing at a file its own installation never materializes.
|
|
8
|
+
*
|
|
9
|
+
* This module supplies the join: a syntax-aware extractor for the reference
|
|
10
|
+
* spellings authored Markdown actually uses, a manifest-derived view of the
|
|
11
|
+
* shipped skill surface, and an owning-pack resolver. Callers compare the two
|
|
12
|
+
* and fail when a shipped skill references a script its owning pack does not
|
|
13
|
+
* ship.
|
|
14
|
+
*
|
|
15
|
+
* The shipped surface is derived from the pack manifest, never from the
|
|
16
|
+
* canonical `.agents/skills` directory listing: that listing is a superset that
|
|
17
|
+
* also holds repository-local authoring and utility skills no pack ships. Those
|
|
18
|
+
* directories are classified and reported, never resolved to a pack and never a
|
|
19
|
+
* failure by themselves.
|
|
20
|
+
*
|
|
21
|
+
* Scan boundary: `extractScriptReferences` takes any text, but the shipping
|
|
22
|
+
* caller feeds it authored Markdown only — every `**\/*.md` under a skill
|
|
23
|
+
* directory except the vendored `references/docs/` copies. That covers every
|
|
24
|
+
* reference in the tree today, since each of the six skill files naming
|
|
25
|
+
* `.oat/scripts` is a `SKILL.md`. A skill that ships a non-Markdown asset
|
|
26
|
+
* carrying a script reference would fall outside this scan, so widen the caller
|
|
27
|
+
* deliberately rather than assuming this module already sees it.
|
|
28
|
+
*/
|
|
29
|
+
import { PACK_MANIFEST } from '../../../tools/shared/pack-manifest.js';
|
|
30
|
+
/** Installed destination prefix produced by the manifest's `script()` helper. */
|
|
31
|
+
export const SCRIPT_DESTINATION_PREFIX = '.oat/scripts/';
|
|
32
|
+
// Extraction runs in two stages, and the split is the whole point.
|
|
33
|
+
//
|
|
34
|
+
// Stage one finds where a reference starts. The lookbehind rejects a candidate
|
|
35
|
+
// glued to an identifier, so `myrepo.oat/scripts/…` never matches, while every
|
|
36
|
+
// rooted spelling authored today still does: a leading `/` is explicitly
|
|
37
|
+
// allowed, which covers `$SCOPE_ROOT/.oat/scripts/…`, `${HOME}/.oat/scripts/…`,
|
|
38
|
+
// `~/.oat/scripts/…`, and the plain relative form. The trailing slash is
|
|
39
|
+
// required, so a mention of the directory itself — `${HOME}/.oat/scripts` — is
|
|
40
|
+
// not a reference start at all.
|
|
41
|
+
//
|
|
42
|
+
// `_` is absent from the lookbehind on purpose, so an italic `_.oat/scripts/…_`
|
|
43
|
+
// still starts a match. The glued-identifier case it used to cover —
|
|
44
|
+
// `myrepo_.oat/scripts/…` — is rejected instead by `readOpeningEmphasis`, which
|
|
45
|
+
// can tell an emphasis delimiter at a word boundary from an underscore inside a
|
|
46
|
+
// name. A lookbehind cannot make that distinction, and a wrongly rejected start
|
|
47
|
+
// is a silent miss.
|
|
48
|
+
const SCRIPT_REFERENCE_START = /(?<![A-Za-z0-9.-])\.oat\/scripts\//g;
|
|
49
|
+
// Characters that may not sit next to an emphasis delimiter for it to read as
|
|
50
|
+
// emphasis rather than as part of an identifier.
|
|
51
|
+
const IDENTIFIER_CHARACTER = /[\p{L}\p{N}._-]/u;
|
|
52
|
+
// Stage two reads the name that follows, losslessly, up to the first character
|
|
53
|
+
// that closes the surrounding Markdown construct: whitespace, the backtick or
|
|
54
|
+
// quote closing an inline span, the `)` or `>` closing a link target, or a
|
|
55
|
+
// list/table separator.
|
|
56
|
+
//
|
|
57
|
+
// Reading the whole token rather than matching a "valid-looking" name is what
|
|
58
|
+
// makes the check fail closed. A name class that stopped at the first
|
|
59
|
+
// unexpected character would quietly truncate `…/resolve-tracking.sh/<file>`
|
|
60
|
+
// down to the shipped `resolve-tracking.sh` and report success, and a class
|
|
61
|
+
// that required a leading alphanumeric would drop `_missing.sh` on the floor
|
|
62
|
+
// instead of flagging it. Both are fail-open, and a fail-open integrity check
|
|
63
|
+
// is worse than none.
|
|
64
|
+
//
|
|
65
|
+
// Only true closers belong here, never ordinary punctuation. Every character in
|
|
66
|
+
// this set truncates the token, so admitting one that can appear mid-path would
|
|
67
|
+
// reintroduce exactly the truncation this design removes.
|
|
68
|
+
const REFERENCE_TOKEN_TERMINATOR = /[\s`"'),;\]|>]/;
|
|
69
|
+
// Prose puts a mark after a path without making it part of the path, and each
|
|
70
|
+
// of these is a real authored spelling: `run .oat/scripts/x.sh.`,
|
|
71
|
+
// `did you run .oat/scripts/x.sh?`, `run .oat/scripts/x.sh: it resolves…`.
|
|
72
|
+
//
|
|
73
|
+
// Exactly one such character is dropped, and only in the final position. That
|
|
74
|
+
// is deliberately weaker than trimming a run: a doubled `x.sh..` keeps a period
|
|
75
|
+
// and still fails, so a malformed spelling cannot be normalized into a shipped
|
|
76
|
+
// name. Position-anchored trimming also cannot truncate a path the way a
|
|
77
|
+
// terminator does.
|
|
78
|
+
const TRAILING_PROSE_MARK = /[.:!?]$/;
|
|
79
|
+
// A token carrying shell, glob, or documentation-placeholder syntax names no
|
|
80
|
+
// concrete file: `~/.oat/scripts/<file>` and `.oat/scripts/${NAME}` are prose
|
|
81
|
+
// about the directory, not references into it. These negatives are as
|
|
82
|
+
// load-bearing as the matches, since a false positive here blocks CI on
|
|
83
|
+
// documentation that is entirely correct.
|
|
84
|
+
//
|
|
85
|
+
// This test runs after every trailing decoration is dropped, so a `?` that
|
|
86
|
+
// merely ended a question, or a `*` that merely closed an emphasis span, is
|
|
87
|
+
// gone before it can be mistaken for a glob.
|
|
88
|
+
const PLACEHOLDER_SYNTAX = /[<{}$*?]/;
|
|
89
|
+
function readReferenceToken(line, from) {
|
|
90
|
+
let end = from;
|
|
91
|
+
while (end < line.length && !REFERENCE_TOKEN_TERMINATOR.test(line[end])) {
|
|
92
|
+
end += 1;
|
|
93
|
+
}
|
|
94
|
+
return line.slice(from, end);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The emphasis run opening this reference, or `null` when the run is glued to a
|
|
98
|
+
* name and therefore opened nothing.
|
|
99
|
+
*
|
|
100
|
+
* The opening run is the only reliable evidence that a trailing delimiter is
|
|
101
|
+
* emphasis rather than content, and both delimiters need that evidence:
|
|
102
|
+
*
|
|
103
|
+
* - `_` is a legal filename character, so `.oat/scripts/x.sh_` with no opening
|
|
104
|
+
* run keeps its underscore. That is what makes a typo such as
|
|
105
|
+
* `resolve-tracking.sh_` still fail instead of being normalized into the
|
|
106
|
+
* shipped name.
|
|
107
|
+
* - `*` is not a legal filename character, but it *is* glob syntax, which this
|
|
108
|
+
* module treats as prose about the directory. An unpaired
|
|
109
|
+
* `.oat/scripts/resolve-tracking.sh*` is a glob, and stripping its star would
|
|
110
|
+
* normalize it into a shipped name — the exact fail-open this design exists to
|
|
111
|
+
* prevent. Leaving it attached keeps it a glob, which is skipped.
|
|
112
|
+
*
|
|
113
|
+
* `null` rejects the match outright for `myrepo_.oat/scripts/x.sh`, where the
|
|
114
|
+
* underscore is glued to an identifier. The identifier test is Unicode-aware so
|
|
115
|
+
* `café_.oat/scripts/x.sh` is rejected too.
|
|
116
|
+
*/
|
|
117
|
+
function readOpeningEmphasis(line, at) {
|
|
118
|
+
let start = at;
|
|
119
|
+
while (start > 0 && (line[start - 1] === '_' || line[start - 1] === '*')) {
|
|
120
|
+
start -= 1;
|
|
121
|
+
}
|
|
122
|
+
const run = line.slice(start, at);
|
|
123
|
+
if (run.length === 0)
|
|
124
|
+
return { asterisks: 0, underscores: 0 };
|
|
125
|
+
const preceding = start > 0 ? line[start - 1] : '';
|
|
126
|
+
if (IDENTIFIER_CHARACTER.test(preceding))
|
|
127
|
+
return null;
|
|
128
|
+
return {
|
|
129
|
+
asterisks: run.split('').filter((char) => char === '*').length,
|
|
130
|
+
underscores: run.split('').filter((char) => char === '_').length,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Drop the decoration Markdown and prose leave on the end of a reference.
|
|
135
|
+
*
|
|
136
|
+
* Each delimiter comes off only up to the length of its opening run, so an
|
|
137
|
+
* unpaired trailing `*` or `_` survives as part of the name and is judged on its
|
|
138
|
+
* merits downstream. At most one prose mark is dropped in total, so a doubled
|
|
139
|
+
* `x.sh..` keeps a period and still fails the manifest comparison.
|
|
140
|
+
*
|
|
141
|
+
* A single ordered pass is not enough, because the layers interleave:
|
|
142
|
+
* `**x.sh**.` closes its emphasis outside the sentence period, and `_*x.sh*_`
|
|
143
|
+
* nests two delimiters. The loop peels whichever layer is currently outermost
|
|
144
|
+
* until no budget is left.
|
|
145
|
+
*/
|
|
146
|
+
function stripTrailingDecoration(token, opening) {
|
|
147
|
+
let name = token;
|
|
148
|
+
let asterisks = opening.asterisks;
|
|
149
|
+
let underscores = opening.underscores;
|
|
150
|
+
let proseMarkDropped = false;
|
|
151
|
+
for (;;) {
|
|
152
|
+
if (asterisks > 0 && name.endsWith('*')) {
|
|
153
|
+
name = name.slice(0, -1);
|
|
154
|
+
asterisks -= 1;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (underscores > 0 && name.endsWith('_')) {
|
|
158
|
+
name = name.slice(0, -1);
|
|
159
|
+
underscores -= 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!proseMarkDropped && TRAILING_PROSE_MARK.test(name)) {
|
|
163
|
+
name = name.replace(TRAILING_PROSE_MARK, '');
|
|
164
|
+
proseMarkDropped = true;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
return name;
|
|
170
|
+
}
|
|
171
|
+
function skillNameOf(asset) {
|
|
172
|
+
return asset.id.slice('skill:'.length);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Extract every `.oat/scripts/<name>` reference from authored text.
|
|
176
|
+
*
|
|
177
|
+
* Scanning is line-by-line so each occurrence carries its own line number, and
|
|
178
|
+
* so a reference can never be assembled across a line break.
|
|
179
|
+
*
|
|
180
|
+
* A reference is returned essentially as authored. Nothing is truncated to a
|
|
181
|
+
* shipped-looking prefix, and the only edits are dropping the Markdown
|
|
182
|
+
* decoration around it — a closing emphasis run and at most one prose mark — so
|
|
183
|
+
* a malformed name reaches the manifest comparison intact and fails there
|
|
184
|
+
* rather than being normalized into a name that happens to exist.
|
|
185
|
+
*/
|
|
186
|
+
export function extractScriptReferences(text) {
|
|
187
|
+
const references = [];
|
|
188
|
+
for (const [index, line] of text.split(/\r?\n/).entries()) {
|
|
189
|
+
for (const match of line.matchAll(SCRIPT_REFERENCE_START)) {
|
|
190
|
+
const opening = readOpeningEmphasis(line, match.index);
|
|
191
|
+
// A delimiter glued to a name, so it never opened emphasis.
|
|
192
|
+
if (opening === null)
|
|
193
|
+
continue;
|
|
194
|
+
const name = stripTrailingDecoration(readReferenceToken(line, match.index + match[0].length), opening);
|
|
195
|
+
// Prose about the directory, not a reference into it.
|
|
196
|
+
if (PLACEHOLDER_SYNTAX.test(name))
|
|
197
|
+
continue;
|
|
198
|
+
// A bare `.oat/scripts/` mention names no script.
|
|
199
|
+
if (name.length === 0)
|
|
200
|
+
continue;
|
|
201
|
+
references.push({
|
|
202
|
+
reference: `${SCRIPT_DESTINATION_PREFIX}${name}`,
|
|
203
|
+
line: index + 1,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return references;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* The union of every pack's skill assets: the surface the manifest claims to
|
|
211
|
+
* ship, which is what the contract checks.
|
|
212
|
+
*/
|
|
213
|
+
export function listShippedSkills(manifest = PACK_MANIFEST) {
|
|
214
|
+
const names = new Set();
|
|
215
|
+
for (const pack of manifest) {
|
|
216
|
+
for (const asset of pack.assets) {
|
|
217
|
+
if (asset.kind === 'skill')
|
|
218
|
+
names.add(skillNameOf(asset));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return [...names].sort();
|
|
222
|
+
}
|
|
223
|
+
/** Script destinations shipped by one pack. */
|
|
224
|
+
export function listPackScriptDestinations(pack, manifest = PACK_MANIFEST) {
|
|
225
|
+
const definition = manifest.find(({ name }) => name === pack);
|
|
226
|
+
if (!definition)
|
|
227
|
+
throw new Error(`Unknown pack: ${pack}`);
|
|
228
|
+
return definition.assets
|
|
229
|
+
.filter((asset) => asset.kind === 'script')
|
|
230
|
+
.map(({ destination }) => destination)
|
|
231
|
+
.sort();
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Classify a canonical skill directory against the manifest.
|
|
235
|
+
*
|
|
236
|
+
* `canonical-unshipped` is an ordinary, expected state: repository-local
|
|
237
|
+
* authoring and utility skills live under `.agents/skills` without belonging to
|
|
238
|
+
* any pack. It is reported, never failed.
|
|
239
|
+
*/
|
|
240
|
+
export function classifyCanonicalSkillDir(name, manifest = PACK_MANIFEST) {
|
|
241
|
+
return listShippedSkills(manifest).includes(name)
|
|
242
|
+
? 'shipped'
|
|
243
|
+
: 'canonical-unshipped';
|
|
244
|
+
}
|
|
245
|
+
/** Classify a whole directory listing in one pass. */
|
|
246
|
+
export function classifyCanonicalSkillDirs(names, manifest = PACK_MANIFEST) {
|
|
247
|
+
const shipped = new Set(listShippedSkills(manifest));
|
|
248
|
+
return {
|
|
249
|
+
shipped: names.filter((name) => shipped.has(name)).sort(),
|
|
250
|
+
canonicalUnshipped: names.filter((name) => !shipped.has(name)).sort(),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Shipped skills the manifest names but whose canonical directory is absent.
|
|
255
|
+
*
|
|
256
|
+
* The inverse of `classifyCanonicalSkillDirs`, and unlike an unshipped
|
|
257
|
+
* directory this *is* a failure: the manifest promises to install something the
|
|
258
|
+
* repository does not contain.
|
|
259
|
+
*/
|
|
260
|
+
export function findMissingShippedSkillDirs(existingDirs, manifest = PACK_MANIFEST) {
|
|
261
|
+
const existing = new Set(existingDirs);
|
|
262
|
+
return listShippedSkills(manifest).filter((name) => !existing.has(name));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Every pack that ships `skillName`.
|
|
266
|
+
*
|
|
267
|
+
* Throws for a name no pack ships. That is a caller bug rather than a repository
|
|
268
|
+
* defect: callers drive from `listShippedSkills`, so an unshipped canonical
|
|
269
|
+
* directory never reaches here.
|
|
270
|
+
*
|
|
271
|
+
* A skill carried by more than one pack resolves to all of them, and membership
|
|
272
|
+
* in any one satisfies the reference check — the same shared-ownership rule the
|
|
273
|
+
* manifest applies to a script shipped by two packs under one `sharedOwner`.
|
|
274
|
+
*/
|
|
275
|
+
export function resolveOwningPack(skillName, manifest = PACK_MANIFEST) {
|
|
276
|
+
const packs = manifest
|
|
277
|
+
.filter((pack) => pack.assets.some((asset) => asset.kind === 'skill' && skillNameOf(asset) === skillName))
|
|
278
|
+
.map(({ name }) => name);
|
|
279
|
+
if (packs.length === 0) {
|
|
280
|
+
throw new Error(`resolveOwningPack: skill "${skillName}" is shipped by no pack; pass a name from listShippedSkills()`);
|
|
281
|
+
}
|
|
282
|
+
return packs;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The contract itself: every script reference authored by a shipped skill must
|
|
286
|
+
* name a `kind: 'script'` destination of a pack that ships that skill.
|
|
287
|
+
*
|
|
288
|
+
* Sources for skills no pack ships must not be passed; drive callers from
|
|
289
|
+
* `listShippedSkills` so `resolveOwningPack` stays a caller-bug signal.
|
|
290
|
+
*/
|
|
291
|
+
export function findUnshippedScriptReferences(sources, manifest = PACK_MANIFEST) {
|
|
292
|
+
const violations = [];
|
|
293
|
+
for (const { skill, file, text } of sources) {
|
|
294
|
+
const packs = resolveOwningPack(skill, manifest);
|
|
295
|
+
const shipped = [
|
|
296
|
+
...new Set(packs.flatMap((pack) => listPackScriptDestinations(pack, manifest))),
|
|
297
|
+
].sort();
|
|
298
|
+
for (const { reference, line } of extractScriptReferences(text)) {
|
|
299
|
+
if (shipped.includes(reference))
|
|
300
|
+
continue;
|
|
301
|
+
violations.push({ skill, file, line, reference, packs, shipped });
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return violations;
|
|
305
|
+
}
|
|
306
|
+
/** Render one violation so the failure names the skill, reference, and pack. */
|
|
307
|
+
export function formatScriptReferenceViolation({ skill, file, line, reference, packs, shipped, }) {
|
|
308
|
+
const owner = `pack${packs.length > 1 ? 's' : ''} ${packs.join(', ')}`;
|
|
309
|
+
const available = shipped.length > 0 ? shipped.join(', ') : 'no scripts';
|
|
310
|
+
return `${skill} (${owner}) references ${reference} at ${file}:${line}, but ${owner} ${packs.length > 1 ? 'ship' : 'ships'} ${available}`;
|
|
311
|
+
}
|
|
@@ -35,10 +35,67 @@ export interface InstructionsJsonPayload {
|
|
|
35
35
|
summary: InstructionsSummary;
|
|
36
36
|
entries: InstructionEntry[];
|
|
37
37
|
actions: InstructionActionRecord[];
|
|
38
|
+
/**
|
|
39
|
+
* The normalized repo-relative exclusions this scan was *configured* with, in
|
|
40
|
+
* resolution order. An entry here is a statement of intent, not a guarantee:
|
|
41
|
+
* it may name a directory that does not exist, differ in case from the real
|
|
42
|
+
* path on a case-insensitive filesystem, or be shadowed by the `.oat/repo`
|
|
43
|
+
* carve-in.
|
|
44
|
+
*
|
|
45
|
+
* Read `effectiveExcludedPaths` to learn what was actually protected.
|
|
46
|
+
*
|
|
47
|
+
* Additive and omitted entirely when nothing was configured, so payloads from
|
|
48
|
+
* repositories without a documentation root are byte-identical to the
|
|
49
|
+
* pre-exclusion shape.
|
|
50
|
+
*/
|
|
51
|
+
excludedPaths?: string[];
|
|
52
|
+
/**
|
|
53
|
+
* The subset of `excludedPaths` that names a real, case-exact directory the
|
|
54
|
+
* scan can actually prune. This is the field a consumer should trust when
|
|
55
|
+
* deciding whether a tree is protected; every configured entry missing from
|
|
56
|
+
* it was also reported as a warning on stderr.
|
|
57
|
+
*
|
|
58
|
+
* Present whenever `excludedPaths` is, including as an empty array when every
|
|
59
|
+
* configured entry turned out to be inert; omitted only when nothing was
|
|
60
|
+
* configured at all.
|
|
61
|
+
*/
|
|
62
|
+
effectiveExcludedPaths?: string[];
|
|
63
|
+
/**
|
|
64
|
+
* One message per configured exclusion that will not protect anything, the
|
|
65
|
+
* same text written to stderr in human mode.
|
|
66
|
+
*
|
|
67
|
+
* This field is why the JSON surface is complete. `logger.warn` is suppressed
|
|
68
|
+
* under `--json`, and an entry rejected during normalization (an absolute
|
|
69
|
+
* path, or one escaping the repository) never reaches `excludedPaths` either
|
|
70
|
+
* — so without this a `--json` consumer would see no trace at all of an
|
|
71
|
+
* exclusion that silently does nothing. Omitted when empty.
|
|
72
|
+
*/
|
|
73
|
+
exclusionWarnings?: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The resolved exclusion set, split so that intent and effect cannot be
|
|
77
|
+
* confused. A configured entry that protects nothing is the failure mode this
|
|
78
|
+
* split exists to surface: silently reporting it as applied would let an
|
|
79
|
+
* operator believe a documentation tree is safe while pointers are written
|
|
80
|
+
* into it.
|
|
81
|
+
*/
|
|
82
|
+
export interface InstructionPointerExclusions {
|
|
83
|
+
/** Normalized entries exactly as configured, in resolution order. */
|
|
84
|
+
configured: string[];
|
|
85
|
+
/** The subset that names a real, case-exact, prunable directory. */
|
|
86
|
+
effective: string[];
|
|
87
|
+
/** One human-readable warning per configured entry that will do nothing. */
|
|
88
|
+
warnings: string[];
|
|
38
89
|
}
|
|
39
90
|
export interface InstructionsScanOptions {
|
|
40
91
|
strategy?: InstructionSyncStrategy;
|
|
41
92
|
debug?: (message: string) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Repo-root-relative directories whose subtrees are left out of the scan.
|
|
95
|
+
* Applied after the excluded-root carve-in, so excluding a directory can
|
|
96
|
+
* never strand a subtree the carve-in re-entered (`.oat/repo/**`).
|
|
97
|
+
*/
|
|
98
|
+
excludedPaths?: string[];
|
|
42
99
|
}
|
|
43
100
|
export interface InstructionsScanDependencies {
|
|
44
101
|
readdir: (path: string, options: {
|
|
@@ -53,6 +110,12 @@ export interface InstructionsScanDependencies {
|
|
|
53
110
|
export interface InstructionsValidateCommandDependencies {
|
|
54
111
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
55
112
|
resolveProjectRoot: (cwd: string) => Promise<string>;
|
|
113
|
+
/**
|
|
114
|
+
* The single exclusion path both commands resolve through. Sync inherits it
|
|
115
|
+
* from this interface rather than resolving its own, so validate can never
|
|
116
|
+
* report drift that sync would refuse to fix.
|
|
117
|
+
*/
|
|
118
|
+
resolveInstructionPointerExcludes: (repoRoot: string) => Promise<InstructionPointerExclusions>;
|
|
56
119
|
scanInstructionFiles: (repoRoot: string, options?: InstructionsScanOptions, overrides?: Partial<InstructionsScanDependencies>) => Promise<InstructionEntry[]>;
|
|
57
120
|
}
|
|
58
121
|
export interface InstructionsSyncCommandDependencies extends InstructionsValidateCommandDependencies {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.types.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,eAAO,MAAM,2BAA2B,YACtC,SAAS,EACT,SAAS,EACT,MAAM,CACE,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,GAAG,OAAO,CAAC;AAEhF,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjE,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,uBAAuB,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"instructions.types.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,64 @@
|
|
|
1
|
-
import type { InstructionSyncStrategy, InstructionActionRecord, InstructionEntry, InstructionsJsonPayload, InstructionsMode, InstructionsScanOptions, InstructionsScanDependencies, InstructionsSummary } from './instructions.types.js';
|
|
1
|
+
import type { InstructionSyncStrategy, InstructionActionRecord, InstructionEntry, InstructionsJsonPayload, InstructionsMode, InstructionPointerExclusions, InstructionsScanOptions, InstructionsScanDependencies, InstructionsSummary } from './instructions.types.js';
|
|
2
2
|
export declare const EXPECTED_CLAUDE_CONTENT = "@AGENTS.md\n";
|
|
3
3
|
export declare const DEFAULT_INSTRUCTION_SYNC_STRATEGY: InstructionSyncStrategy;
|
|
4
4
|
interface BuildInstructionsPayloadArgs {
|
|
5
5
|
mode: InstructionsMode;
|
|
6
6
|
entries: InstructionEntry[];
|
|
7
7
|
actions: InstructionActionRecord[];
|
|
8
|
+
excludedPaths?: string[];
|
|
9
|
+
effectiveExcludedPaths?: string[];
|
|
10
|
+
exclusionWarnings?: string[];
|
|
8
11
|
}
|
|
9
12
|
export declare function resolveInstructionSyncStrategy(strategy?: InstructionSyncStrategy): InstructionSyncStrategy;
|
|
13
|
+
/**
|
|
14
|
+
* Canonicalize repo-relative exclusion entries into the exact form the scan
|
|
15
|
+
* compares against: POSIX separators, collapsed `.` and `..` segments and
|
|
16
|
+
* duplicate slashes, no trailing slash, de-duplicated, order-preserving.
|
|
17
|
+
*
|
|
18
|
+
* Full normalization is what makes the comparison trustworthy. The scan tests
|
|
19
|
+
* an exclusion against `relative(repoRoot, entryPath)`, which is always
|
|
20
|
+
* already-normalized, so an un-normalized entry like `apps/./docs` or
|
|
21
|
+
* `apps//docs` would silently never match and quietly fail open.
|
|
22
|
+
*
|
|
23
|
+
* Two classes of entry are dropped rather than normalized:
|
|
24
|
+
*
|
|
25
|
+
* - anything resolving to the repository root (`.`, `` , `./`), because
|
|
26
|
+
* excluding the root would silence the entire scan — including the
|
|
27
|
+
* `.oat/repo` carve-in — from one stray config value; and
|
|
28
|
+
* - absolute paths and entries escaping the repository (`..`, `../x`), which
|
|
29
|
+
* can never name a directory inside the tree being scanned. Dropping them
|
|
30
|
+
* keeps a malformed value from masquerading as a matchable exclusion.
|
|
31
|
+
*/
|
|
32
|
+
export declare function normalizeExcludedPaths(excludedPaths?: readonly string[]): string[];
|
|
33
|
+
/**
|
|
34
|
+
* The directories `oat instructions sync` and `oat instructions validate` skip:
|
|
35
|
+
* the derived documentation content root first, then the explicit
|
|
36
|
+
* `documentation.instructionPointerExcludes` opt-outs.
|
|
37
|
+
*
|
|
38
|
+
* Both commands resolve exclusions through this one function. That is the
|
|
39
|
+
* property that matters: if they computed exclusions separately, validate
|
|
40
|
+
* could report drift in a directory sync refuses to touch, and the repository
|
|
41
|
+
* would have no clean state to reach.
|
|
42
|
+
*
|
|
43
|
+
* Every configured entry is classified rather than trusted. An entry that is
|
|
44
|
+
* dropped during normalization, names an unexcludable carve-in root, or does
|
|
45
|
+
* not resolve to a real case-exact directory is reported as a warning and kept
|
|
46
|
+
* out of `effective`, so no caller can mistake a typo for protection.
|
|
47
|
+
*
|
|
48
|
+
* `effective` answers "is this tree protected from pointer writes?", not "did
|
|
49
|
+
* the exclusion predicate fire for it". An entry that names an already-skipped
|
|
50
|
+
* built-in root (`.git`, `node_modules`) or sits beneath another exclusion is
|
|
51
|
+
* still effective, because the operator's intent holds; warning about those
|
|
52
|
+
* would be a false alarm about exclusions that do work.
|
|
53
|
+
*
|
|
54
|
+
* Nothing here deletes or rewrites an existing pointer. Excluding a directory
|
|
55
|
+
* only stops it being reported and written; a `CLAUDE.md` already inside an
|
|
56
|
+
* excluded tree is left exactly as it is.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveInstructionPointerExcludes(repoRoot: string, overrides?: Partial<InstructionsScanDependencies>): Promise<InstructionPointerExclusions>;
|
|
10
59
|
export declare function scanInstructionFiles(repoRoot: string, options?: InstructionsScanOptions, overrides?: Partial<InstructionsScanDependencies>): Promise<InstructionEntry[]>;
|
|
11
60
|
export declare function buildInstructionsSummary(entries: InstructionEntry[], actions: InstructionActionRecord[]): InstructionsSummary;
|
|
12
|
-
export declare function buildInstructionsPayload({ mode, entries, actions, }: BuildInstructionsPayloadArgs): InstructionsJsonPayload;
|
|
61
|
+
export declare function buildInstructionsPayload({ mode, entries, actions, excludedPaths, effectiveExcludedPaths, exclusionWarnings, }: BuildInstructionsPayloadArgs): InstructionsJsonPayload;
|
|
13
62
|
export declare function formatInstructionsReport(payload: InstructionsJsonPayload, repoRoot?: string): string;
|
|
14
63
|
export {};
|
|
15
64
|
//# sourceMappingURL=instructions.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.utils.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instructions.utils.d.ts","sourceRoot":"","sources":["../../../src/commands/instructions/instructions.utils.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,4BAA4B,EAC5B,uBAAuB,EACvB,4BAA4B,EAE5B,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AACtD,eAAO,MAAM,iCAAiC,EAAE,uBACrC,CAAC;AAcZ,UAAU,4BAA4B;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAiCD,wBAAgB,8BAA8B,CAC5C,QAAQ,CAAC,EAAE,uBAAuB,GACjC,uBAAuB,CAEzB;AA2ED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,GAAE,SAAS,MAAM,EAAO,GACpC,MAAM,EAAE,CAyBV;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,iCAAiC,CACrD,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,4BAA4B,CAAC,CAuEvC;AAgID,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,EACrC,SAAS,GAAE,OAAO,CAAC,4BAA4B,CAAM,GACpD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkO7B;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,EAAE,uBAAuB,EAAE,GACjC,mBAAmB,CAoBrB;AAgBD,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,aAAa,EACb,sBAAsB,EACtB,iBAAiB,GAClB,EAAE,4BAA4B,GAAG,uBAAuB,CAgCxD;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAmCR"}
|