-
Notifications
You must be signed in to change notification settings - Fork 82
feat: detect VS Code location settings in readiness checks #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,9 @@ import { | |
| hasMcpConfig, | ||
| hasCustomAgents, | ||
| hasCopilotSkills, | ||
| hasApmConfig, | ||
| hasApmLockfile, | ||
| hasApmInWorkflows, | ||
| readAllDependencies, | ||
| checkInstructionConsistency | ||
| } from "./checkers"; | ||
|
|
@@ -302,7 +305,10 @@ export function buildCriteria(): ReadinessCriterion[] { | |
| } | ||
|
|
||
| // Check for area instructions (.github/instructions/*.instructions.md) | ||
| const fileBasedInstructions = await hasFileBasedInstructions(context.repoPath); | ||
| const fileBasedInstructions = await hasFileBasedInstructions( | ||
| context.repoPath, | ||
| context.vscodeLocations?.instructionsLocations | ||
| ); | ||
| const areas = context.analysis.areas ?? []; | ||
|
|
||
| // For monorepos or repos with detected areas, check coverage | ||
|
|
@@ -321,6 +327,15 @@ export function buildCriteria(): ReadinessCriterion[] { | |
| }; | ||
|
Comment on lines
307
to
327
|
||
| } | ||
|
|
||
| // File-based instructions found (e.g. from VS Code location settings) without areas | ||
| if (fileBasedInstructions.length > 0) { | ||
| return { | ||
| status: "pass", | ||
| reason: `Root + ${fileBasedInstructions.length} file-based instruction(s) found.`, | ||
| evidence: [...rootFound, ...fileBasedInstructions] | ||
| }; | ||
| } | ||
|
|
||
| // For monorepos without areas, check per-app instructions (legacy behavior) | ||
| if (context.analysis.isMonorepo && context.apps.length > 1) { | ||
| const appsMissing: string[] = []; | ||
|
|
@@ -405,7 +420,10 @@ export function buildCriteria(): ReadinessCriterion[] { | |
| impact: "medium", | ||
| effort: "medium", | ||
| check: async (context) => { | ||
| const found = await hasCustomAgents(context.repoPath); | ||
| const found = await hasCustomAgents( | ||
| context.repoPath, | ||
| context.vscodeLocations?.agentLocations | ||
| ); | ||
| return { | ||
| status: found.length > 0 ? "pass" : "fail", | ||
| reason: "No custom AI agents configured (e.g. .github/agents/, .copilot/agents/).", | ||
|
|
@@ -425,7 +443,10 @@ export function buildCriteria(): ReadinessCriterion[] { | |
| impact: "medium", | ||
| effort: "medium", | ||
| check: async (context) => { | ||
| const found = await hasCopilotSkills(context.repoPath); | ||
| const found = await hasCopilotSkills( | ||
| context.repoPath, | ||
| context.vscodeLocations?.skillsLocations | ||
| ); | ||
| return { | ||
| status: found.length > 0 ? "pass" : "fail", | ||
| reason: "No Copilot or Claude skills found (e.g. .copilot/skills/, .github/skills/).", | ||
|
|
@@ -434,6 +455,71 @@ export function buildCriteria(): ReadinessCriterion[] { | |
| }; | ||
| } | ||
| }, | ||
| { | ||
| id: "apm-config", | ||
| title: "APM package manifest present", | ||
| pillar: "ai-tooling", | ||
| level: 2, | ||
| scope: "repo", | ||
| impact: "medium", | ||
| effort: "low", | ||
| check: async (context) => { | ||
| const found = await hasApmConfig(context.repoPath); | ||
| return { | ||
| status: found ? "pass" : "fail", | ||
| reason: found | ||
| ? undefined | ||
| : "No apm.yml found. Use APM to install shared agent packages and keep instructions in sync across repos. See: https://github.com/microsoft/apm", | ||
| evidence: ["apm.yml"] | ||
| }; | ||
| } | ||
| }, | ||
| { | ||
| id: "apm-locked-deps", | ||
| title: "APM dependencies locked", | ||
| pillar: "ai-tooling", | ||
| level: 3, | ||
| scope: "repo", | ||
| impact: "medium", | ||
| effort: "low", | ||
| check: async (context) => { | ||
| const hasConfig = await hasApmConfig(context.repoPath); | ||
| if (!hasConfig) { | ||
| return { status: "skip", reason: "No apm.yml found \u2014 skipping lockfile check." }; | ||
| } | ||
| const found = await hasApmLockfile(context.repoPath); | ||
| return { | ||
| status: found ? "pass" : "fail", | ||
| reason: found | ||
| ? undefined | ||
| : "apm.yml found but dependencies are not locked. Run `apm install` to generate apm.lock.yaml.", | ||
| evidence: ["apm.lock.yaml"] | ||
| }; | ||
| } | ||
| }, | ||
| { | ||
| id: "apm-ci-integration", | ||
| title: "APM integrated in CI pipeline", | ||
| pillar: "ai-tooling", | ||
| level: 4, | ||
| scope: "repo", | ||
| impact: "high", | ||
| effort: "medium", | ||
| check: async (context) => { | ||
| const hasConfig = await hasApmConfig(context.repoPath); | ||
| if (!hasConfig) { | ||
| return { status: "skip", reason: "No apm.yml found \u2014 skipping CI check." }; | ||
| } | ||
| const found = await hasApmInWorkflows(context.repoPath); | ||
| return { | ||
| status: found ? "pass" : "fail", | ||
| reason: found | ||
| ? undefined | ||
| : "No APM step found in CI. Add `microsoft/apm-action` to your workflow to audit agent packages on every PR. See: https://github.com/microsoft/apm-action", | ||
| evidence: [".github/workflows/*.{yml,yaml}"] | ||
| }; | ||
| } | ||
| }, | ||
| // ── Area-scoped criteria (only run when areaPath is set) ── | ||
| { | ||
| id: "area-readme", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validateAndNormalize()can incorrectly accept Windows-style absolute paths when running on POSIX. Example: a setting path like\\etc\\agentsis not considered absolute bypath.isAbsolute()on POSIX, but the laterreplace(/\\/g, "/")turns it into/etc/agents(absolute). That would make subsequentpath.join(repoPath, dir)ignorerepoPathand allow filesystem access outside the repo. Consider normalizing separators before the absolute-path check and/or rejecting any normalized path that starts with/or\\, and add a test case for leading-backslash inputs.