@cubis/foundry 0.3.39 → 0.3.41

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.
Files changed (33) hide show
  1. package/README.md +64 -0
  2. package/bin/cubis.js +382 -25
  3. package/mcp/README.md +72 -8
  4. package/mcp/config.json +3 -0
  5. package/mcp/dist/index.js +315 -68
  6. package/mcp/src/config/index.test.ts +1 -0
  7. package/mcp/src/config/schema.ts +5 -0
  8. package/mcp/src/index.ts +40 -9
  9. package/mcp/src/server.ts +66 -10
  10. package/mcp/src/telemetry/tokenBudget.ts +114 -0
  11. package/mcp/src/tools/index.ts +7 -0
  12. package/mcp/src/tools/skillBrowseCategory.ts +22 -5
  13. package/mcp/src/tools/skillBudgetReport.ts +128 -0
  14. package/mcp/src/tools/skillGet.ts +18 -0
  15. package/mcp/src/tools/skillListCategories.ts +19 -6
  16. package/mcp/src/tools/skillSearch.ts +22 -5
  17. package/mcp/src/tools/skillTools.test.ts +61 -9
  18. package/mcp/src/vault/manifest.test.ts +19 -1
  19. package/mcp/src/vault/manifest.ts +12 -1
  20. package/mcp/src/vault/scanner.test.ts +1 -0
  21. package/mcp/src/vault/scanner.ts +1 -0
  22. package/mcp/src/vault/types.ts +6 -0
  23. package/package.json +1 -1
  24. package/workflows/skills/code-documenter/references/images/create-key.png +0 -0
  25. package/workflows/skills/code-documenter/references/images/dashboard-annotated.png +0 -0
  26. package/workflows/skills/documentation-templates/docs/api.md +16 -0
  27. package/workflows/skills/documentation-templates/docs/architecture.md +23 -0
  28. package/workflows/workflows/agent-environment-setup/platforms/antigravity/rules/GEMINI.md +35 -1
  29. package/workflows/workflows/agent-environment-setup/platforms/codex/rules/AGENTS.md +38 -3
  30. package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/AGENTS.md +35 -1
  31. package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/copilot-instructions.md +35 -1
  32. package/workflows/workflows/agent-environment-setup/platforms/cursor/rules/.cursorrules +28 -0
  33. package/workflows/workflows/agent-environment-setup/platforms/windsurf/rules/.windsurfrules +28 -0
@@ -8,6 +8,11 @@
8
8
  import { z } from "zod";
9
9
  import type { VaultManifest } from "../vault/types.js";
10
10
  import { enrichWithDescriptions } from "../vault/manifest.js";
11
+ import {
12
+ buildSkillToolMetrics,
13
+ estimateTokensFromBytes,
14
+ estimateTokensFromText,
15
+ } from "../telemetry/tokenBudget.js";
11
16
 
12
17
  export const skillSearchName = "skill_search";
13
18
 
@@ -27,6 +32,7 @@ export async function handleSkillSearch(
27
32
  args: z.infer<typeof skillSearchSchema>,
28
33
  manifest: VaultManifest,
29
34
  summaryMaxLength: number,
35
+ charsPerToken: number,
30
36
  ) {
31
37
  const { query } = args;
32
38
  const lower = query.toLowerCase();
@@ -56,17 +62,28 @@ export async function handleSkillSearch(
56
62
  category: s.category,
57
63
  description: s.description ?? "(no description)",
58
64
  }));
65
+ const payload = { query, results, count: results.length };
66
+ const text = JSON.stringify(payload, null, 2);
67
+ const selectedSkillsEstimatedTokens = matches.reduce(
68
+ (sum, skill) => sum + estimateTokensFromBytes(skill.fileBytes, charsPerToken),
69
+ 0,
70
+ );
71
+ const metrics = buildSkillToolMetrics({
72
+ charsPerToken,
73
+ fullCatalogEstimatedTokens: manifest.fullCatalogEstimatedTokens,
74
+ responseEstimatedTokens: estimateTokensFromText(text, charsPerToken),
75
+ selectedSkillsEstimatedTokens,
76
+ });
59
77
 
60
78
  return {
61
79
  content: [
62
80
  {
63
81
  type: "text" as const,
64
- text: JSON.stringify(
65
- { query, results, count: results.length },
66
- null,
67
- 2,
68
- ),
82
+ text,
69
83
  },
70
84
  ],
85
+ structuredContent: {
86
+ metrics,
87
+ },
71
88
  };
72
89
  }
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { mkdtempSync, writeFileSync } from "node:fs";
2
+ import { mkdtempSync, statSync, writeFileSync } from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import type { VaultManifest } from "../vault/types.js";
6
6
  import { handleSkillBrowseCategory } from "./skillBrowseCategory.js";
7
+ import { handleSkillBudgetReport } from "./skillBudgetReport.js";
7
8
  import { handleSkillGet } from "./skillGet.js";
8
9
  import { handleSkillListCategories } from "./skillListCategories.js";
9
10
  import { handleSkillSearch } from "./skillSearch.js";
@@ -12,6 +13,10 @@ function payload(result: { content: Array<{ text: string }> }): Record<string, u
12
13
  return JSON.parse(result.content[0].text) as Record<string, unknown>;
13
14
  }
14
15
 
16
+ function metrics(result: { structuredContent?: Record<string, unknown> }): Record<string, unknown> {
17
+ return (result.structuredContent?.metrics || {}) as Record<string, unknown>;
18
+ }
19
+
15
20
  function createSkillFile(id: string, description: string, body = "# Content"): string {
16
21
  const dir = mkdtempSync(path.join(os.tmpdir(), `mcp-skill-${id}-`));
17
22
  const file = path.join(dir, "SKILL.md");
@@ -32,27 +37,47 @@ function createManifest(): VaultManifest {
32
37
  "fastapi-expert",
33
38
  "FastAPI async backend patterns",
34
39
  );
40
+ const reactBytes = statSync(reactFile).size;
41
+ const fastapiBytes = statSync(fastapiFile).size;
42
+ const fullCatalogBytes = reactBytes + fastapiBytes;
35
43
 
36
44
  return {
37
45
  categories: ["backend", "frontend"],
38
46
  skills: [
39
- { id: "react-expert", category: "frontend", path: reactFile },
40
- { id: "fastapi-expert", category: "backend", path: fastapiFile },
47
+ {
48
+ id: "react-expert",
49
+ category: "frontend",
50
+ path: reactFile,
51
+ fileBytes: reactBytes,
52
+ },
53
+ {
54
+ id: "fastapi-expert",
55
+ category: "backend",
56
+ path: fastapiFile,
57
+ fileBytes: fastapiBytes,
58
+ },
41
59
  ],
60
+ fullCatalogBytes,
61
+ fullCatalogEstimatedTokens: Math.ceil(fullCatalogBytes / 4),
42
62
  };
43
63
  }
44
64
 
45
65
  describe("skill tools", () => {
46
66
  it("lists categories with skill counts", () => {
47
67
  const manifest = createManifest();
48
- const result = handleSkillListCategories(manifest);
68
+ const result = handleSkillListCategories(manifest, 4);
49
69
  const data = payload(result);
70
+ const toolMetrics = metrics(result);
50
71
 
51
72
  expect(data.totalSkills).toBe(2);
52
73
  expect(data.categories).toEqual([
53
74
  { category: "backend", skillCount: 1 },
54
75
  { category: "frontend", skillCount: 1 },
55
76
  ]);
77
+ expect(toolMetrics.estimatorVersion).toBeDefined();
78
+ expect(toolMetrics.fullCatalogEstimatedTokens).toBe(
79
+ manifest.fullCatalogEstimatedTokens,
80
+ );
56
81
  });
57
82
 
58
83
  it("browses a category with enriched descriptions", async () => {
@@ -61,8 +86,10 @@ describe("skill tools", () => {
61
86
  { category: "frontend" },
62
87
  manifest,
63
88
  200,
89
+ 4,
64
90
  );
65
91
  const data = payload(result);
92
+ const toolMetrics = metrics(result);
66
93
 
67
94
  expect(data.category).toBe("frontend");
68
95
  expect(data.count).toBe(1);
@@ -72,12 +99,13 @@ describe("skill tools", () => {
72
99
  description: "React performance and architecture guidance",
73
100
  },
74
101
  ]);
102
+ expect(toolMetrics.selectedSkillsEstimatedTokens).toBeGreaterThan(0);
75
103
  });
76
104
 
77
105
  it("throws when browsing an unknown category", async () => {
78
106
  const manifest = createManifest();
79
107
  await expect(
80
- handleSkillBrowseCategory({ category: "mobile" }, manifest, 200),
108
+ handleSkillBrowseCategory({ category: "mobile" }, manifest, 200, 4),
81
109
  ).rejects.toThrow('Category not found: "mobile"');
82
110
  });
83
111
 
@@ -85,7 +113,7 @@ describe("skill tools", () => {
85
113
  const manifest = createManifest();
86
114
 
87
115
  const byId = payload(
88
- await handleSkillSearch({ query: "react" }, manifest, 200),
116
+ await handleSkillSearch({ query: "react" }, manifest, 200, 4),
89
117
  );
90
118
  expect(byId.count).toBe(1);
91
119
  expect(byId.results).toEqual([
@@ -97,7 +125,7 @@ describe("skill tools", () => {
97
125
  ]);
98
126
 
99
127
  const byDescription = payload(
100
- await handleSkillSearch({ query: "async backend" }, manifest, 200),
128
+ await handleSkillSearch({ query: "async backend" }, manifest, 200, 4),
101
129
  );
102
130
  expect(byDescription.count).toBe(1);
103
131
  expect(byDescription.results).toEqual([
@@ -111,16 +139,40 @@ describe("skill tools", () => {
111
139
 
112
140
  it("returns full skill content for skill_get", async () => {
113
141
  const manifest = createManifest();
114
- const result = await handleSkillGet({ id: "react-expert" }, manifest);
142
+ const result = await handleSkillGet({ id: "react-expert" }, manifest, 4);
143
+ const toolMetrics = metrics(result);
115
144
 
116
145
  expect(result.content[0].text).toContain("# Content");
117
146
  expect(result.content[0].text).toContain("description: React performance");
147
+ expect(toolMetrics.loadedSkillEstimatedTokens).toBeGreaterThan(0);
118
148
  });
119
149
 
120
150
  it("throws when skill_get cannot find the requested skill", async () => {
121
151
  const manifest = createManifest();
122
- await expect(handleSkillGet({ id: "missing" }, manifest)).rejects.toThrow(
152
+ await expect(handleSkillGet({ id: "missing" }, manifest, 4)).rejects.toThrow(
123
153
  'Skill not found: "missing"',
124
154
  );
125
155
  });
156
+
157
+ it("returns consolidated budget rollup for selected and loaded skills", () => {
158
+ const manifest = createManifest();
159
+ const result = handleSkillBudgetReport(
160
+ {
161
+ selectedSkillIds: ["react-expert", "missing-skill"],
162
+ loadedSkillIds: ["react-expert"],
163
+ },
164
+ manifest,
165
+ 4,
166
+ );
167
+ const data = payload(result);
168
+
169
+ expect(data.skillLog).toBeDefined();
170
+ expect(data.contextBudget).toMatchObject({
171
+ fullCatalogEstimatedTokens: manifest.fullCatalogEstimatedTokens,
172
+ estimated: true,
173
+ });
174
+ expect(
175
+ (data.skillLog as Record<string, unknown>).unknownSelectedSkillIds,
176
+ ).toContain("missing-skill");
177
+ });
126
178
  });
@@ -3,6 +3,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import {
6
+ buildManifest,
6
7
  enrichWithDescriptions,
7
8
  extractDescription,
8
9
  parseDescriptionFromFrontmatter,
@@ -109,11 +110,12 @@ describe("manifest enrichment", () => {
109
110
 
110
111
  const enriched = await enrichWithDescriptions(
111
112
  [
112
- { id: "alpha", category: "general", path: fileA },
113
+ { id: "alpha", category: "general", path: fileA, fileBytes: 64 },
113
114
  {
114
115
  id: "beta",
115
116
  category: "general",
116
117
  path: fileB,
118
+ fileBytes: 64,
117
119
  description: "Already populated",
118
120
  },
119
121
  ],
@@ -124,3 +126,19 @@ describe("manifest enrichment", () => {
124
126
  expect(enriched[1].description).toBe("Already populated");
125
127
  });
126
128
  });
129
+
130
+ describe("buildManifest", () => {
131
+ it("computes full catalog byte and token totals", () => {
132
+ const manifest = buildManifest(
133
+ [
134
+ { id: "a", category: "general", path: "/tmp/a.md", fileBytes: 20 },
135
+ { id: "b", category: "frontend", path: "/tmp/b.md", fileBytes: 12 },
136
+ ],
137
+ 4,
138
+ );
139
+
140
+ expect(manifest.categories).toEqual(["frontend", "general"]);
141
+ expect(manifest.fullCatalogBytes).toBe(32);
142
+ expect(manifest.fullCatalogEstimatedTokens).toBe(8);
143
+ });
144
+ });
@@ -8,19 +8,30 @@
8
8
  import { readFile } from "node:fs/promises";
9
9
  import type { SkillPointer, VaultManifest } from "./types.js";
10
10
  import { logger } from "../utils/logger.js";
11
+ import { estimateTokensFromBytes } from "../telemetry/tokenBudget.js";
11
12
 
12
13
  /**
13
14
  * Build a VaultManifest from scanned skill pointers.
14
15
  * Categories are derived from the pointers.
15
16
  */
16
- export function buildManifest(skills: SkillPointer[]): VaultManifest {
17
+ export function buildManifest(
18
+ skills: SkillPointer[],
19
+ charsPerToken: number,
20
+ ): VaultManifest {
17
21
  const categorySet = new Set<string>();
22
+ let fullCatalogBytes = 0;
18
23
  for (const skill of skills) {
19
24
  categorySet.add(skill.category);
25
+ fullCatalogBytes += skill.fileBytes;
20
26
  }
21
27
  return {
22
28
  categories: [...categorySet].sort(),
23
29
  skills,
30
+ fullCatalogBytes,
31
+ fullCatalogEstimatedTokens: estimateTokensFromBytes(
32
+ fullCatalogBytes,
33
+ charsPerToken,
34
+ ),
24
35
  };
25
36
  }
26
37
 
@@ -52,6 +52,7 @@ describe("scanVaultRoots", () => {
52
52
  expect(byId["react-expert"]).toBe("frontend");
53
53
  expect(byId["database-design"]).toBe("data");
54
54
  expect(byId["custom-skill"]).toBe("general");
55
+ expect(skills.every((skill) => skill.fileBytes > 0)).toBe(true);
55
56
  });
56
57
 
57
58
  it("skips missing roots and continues scanning valid roots", async () => {
@@ -46,6 +46,7 @@ export async function scanVaultRoots(
46
46
  id: entry,
47
47
  category: deriveCategory(entry),
48
48
  path: skillFile,
49
+ fileBytes: skillStat.size,
49
50
  });
50
51
  }
51
52
  }
@@ -9,6 +9,8 @@ export interface SkillPointer {
9
9
  category: string;
10
10
  /** Absolute path to the SKILL.md file. */
11
11
  path: string;
12
+ /** Skill file size in bytes. */
13
+ fileBytes: number;
12
14
  /** Short description extracted from frontmatter (truncated). */
13
15
  description?: string;
14
16
  }
@@ -18,4 +20,8 @@ export interface VaultManifest {
18
20
  categories: string[];
19
21
  /** All skill pointers (metadata only – no full content). */
20
22
  skills: SkillPointer[];
23
+ /** Total bytes across all discovered SKILL.md files. */
24
+ fullCatalogBytes: number;
25
+ /** Estimated full-catalog token usage (deterministic estimator). */
26
+ fullCatalogEstimatedTokens: number;
21
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubis/foundry",
3
- "version": "0.3.39",
3
+ "version": "0.3.41",
4
4
  "description": "Cubis Foundry CLI for workflow-first AI agent environments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,16 @@
1
+ # API Reference Template
2
+
3
+ Use this file as the canonical entry point for API endpoint documentation.
4
+
5
+ ## Endpoint Index
6
+
7
+ - `GET /resource`
8
+ - `POST /resource`
9
+ - `PATCH /resource/{id}`
10
+ - `DELETE /resource/{id}`
11
+
12
+ ## Conventions
13
+
14
+ - Include auth requirements per endpoint.
15
+ - Include request/response examples.
16
+ - Include error codes and retry guidance.
@@ -0,0 +1,23 @@
1
+ # Architecture Overview Template
2
+
3
+ Use this file to describe system boundaries and data flow.
4
+
5
+ ## Components
6
+
7
+ - API layer
8
+ - Domain/service layer
9
+ - Persistence layer
10
+ - External integrations
11
+
12
+ ## Runtime Flow
13
+
14
+ 1. Request enters API layer
15
+ 2. Domain logic validates and processes
16
+ 3. Persistence reads/writes state
17
+ 4. Response returns with observability metadata
18
+
19
+ ## Non-Functional Notes
20
+
21
+ - Reliability/SLOs
22
+ - Security model
23
+ - Scaling strategy
@@ -68,6 +68,32 @@ Use the best specialist first:
68
68
 
69
69
  ## 5) Skill Loading Policy
70
70
 
71
+ ## MCP-first Skill Discovery Order (Required)
72
+
73
+ 1. Use `skill_search` first to narrow candidate skills.
74
+ 2. Use `skill_browse_category` second to inspect category-level candidates.
75
+ 3. Use `skill_get` only for final selected skills that must be loaded.
76
+ 4. Keep pointer-first flow; avoid loading full skill text prematurely.
77
+
78
+ ## Skill Log Completion Block (Required)
79
+
80
+ After finishing skill selection/loading, publish:
81
+
82
+ - `selected_skills`: skill IDs selected for the task
83
+ - `loaded_skills`: skill IDs loaded via `skill_get`
84
+ - `skipped_skills`: considered but not loaded
85
+
86
+ ## Context Budget Block (Required, Estimated)
87
+
88
+ Immediately after the Skill Log block, publish estimated budget fields:
89
+
90
+ - `full_catalog_est_tokens`
91
+ - `loaded_est_tokens`
92
+ - `estimated_savings_tokens`
93
+ - `estimated_savings_percent`
94
+
95
+ Mark all context/token values as deterministic estimates (not provider metering).
96
+
71
97
  ### Smart Skill Selection (Adaptive)
72
98
 
73
99
  Use an adaptive load policy to control context size:
@@ -85,6 +111,8 @@ Use an adaptive load policy to control context size:
85
111
  4. If a mapped skill is missing, continue with best fallback and state it.
86
112
  5. Keep user-visible decision logs concise: selected skill(s) and one-line rationale.
87
113
 
114
+ After the skill log is complete, append the Context Budget block in the same response/update.
115
+
88
116
  ## 6) Socratic Gate (Before Complex Work)
89
117
 
90
118
  Before multi-file or architecture-impacting changes, ask targeted questions when requirements are unclear:
@@ -110,7 +138,13 @@ If Antigravity script harness exists, prefer:
110
138
  Use these commands to keep this setup healthy:
111
139
 
112
140
  - Install/update bundle:
113
- `cbx workflows install --platform antigravity --bundle agent-environment-setup --scope global --overwrite`
141
+ `cbx workflows install --platform antigravity --bundle agent-environment-setup --scope global --overwrite --postman --stitch --mcp-runtime docker --mcp-fallback local --mcp-tool-sync`
142
+ - Start MCP Docker runtime:
143
+ `cbx mcp runtime up --scope global --name cbx-mcp --port 3310 --replace`
144
+ - Check MCP Docker runtime:
145
+ `cbx mcp runtime status --scope global --name cbx-mcp`
146
+ - Stop MCP Docker runtime:
147
+ `cbx mcp runtime down --name cbx-mcp`
114
148
  - Rebuild managed routing block:
115
149
  `cbx workflows sync-rules --platform antigravity --scope project`
116
150
  - Diagnose setup issues:
@@ -14,12 +14,13 @@ This file defines mandatory behavior for Codex projects installed via `cbx workf
14
14
  Before executing workflows, agents, or code edits, publish a short `Decision Log` that is visible to the user:
15
15
 
16
16
  1. Rule file(s) read at startup (at minimum `AGENTS.md`, plus any additional rule files loaded).
17
- 2. Workflow decision (`$workflow-*` or direct mode) and why it was chosen.
18
- 3. Agent routing decision (`$agent-*` or direct mode) and why it was chosen.
17
+ 2. Workflow decision ($workflow-* or direct mode) and why it was chosen.
18
+ 3. Agent routing decision ($agent-* or direct mode) and why it was chosen.
19
19
  4. Skill loading decision (skill names loaded) and why they were chosen.
20
20
 
21
21
  If routing changes during the task, publish a `Decision Update` before continuing.
22
22
  Keep this user-visible summary concise and factual; do not expose private chain-of-thought.
23
+ When mentioning wrappers in user-visible logs, use raw $workflow-* and $agent-* tokens (no backticks) so Codex can render icon/blue mention styling.
23
24
 
24
25
  ## 2) Skill-Based Workflow
25
26
 
@@ -63,6 +64,32 @@ Use the best specialist first:
63
64
 
64
65
  ## 5) Skill Loading Policy
65
66
 
67
+ ## MCP-first Skill Discovery Order (Required)
68
+
69
+ 1. Use `skill_search` first to narrow candidate skills.
70
+ 2. Use `skill_browse_category` second to inspect category-level candidates.
71
+ 3. Use `skill_get` only for final selected skills that must be loaded.
72
+ 4. Keep pointer-first flow; avoid loading full skill text prematurely.
73
+
74
+ ## Skill Log Completion Block (Required)
75
+
76
+ After finishing skill selection/loading, publish:
77
+
78
+ - `selected_skills`: skill IDs selected for the task
79
+ - `loaded_skills`: skill IDs loaded via `skill_get`
80
+ - `skipped_skills`: considered but not loaded
81
+
82
+ ## Context Budget Block (Required, Estimated)
83
+
84
+ Immediately after the Skill Log block, publish estimated budget fields:
85
+
86
+ - `full_catalog_est_tokens`
87
+ - `loaded_est_tokens`
88
+ - `estimated_savings_tokens`
89
+ - `estimated_savings_percent`
90
+
91
+ Mark all context/token values as deterministic estimates (not provider metering).
92
+
66
93
  ### Smart Skill Selection (Adaptive)
67
94
 
68
95
  Use an adaptive load policy to control context size:
@@ -80,6 +107,8 @@ Use an adaptive load policy to control context size:
80
107
  4. If a mapped skill is missing, continue with best fallback and state it.
81
108
  5. Keep user-visible decision logs concise: selected skill(s) and one-line rationale.
82
109
 
110
+ After the skill log is complete, append the Context Budget block in the same response/update.
111
+
83
112
  ## 6) Socratic Gate (Before Complex Work)
84
113
 
85
114
  Before multi-file or architecture-impacting changes, ask targeted questions when requirements are unclear:
@@ -100,7 +129,13 @@ Before multi-file or architecture-impacting changes, ask targeted questions when
100
129
  Use these commands to keep this setup healthy:
101
130
 
102
131
  - Install/update bundle:
103
- `cbx workflows install --platform codex --bundle agent-environment-setup --scope global --overwrite`
132
+ `cbx workflows install --platform codex --bundle agent-environment-setup --scope global --overwrite --postman --stitch --mcp-runtime docker --mcp-fallback local --mcp-tool-sync`
133
+ - Start MCP Docker runtime:
134
+ `cbx mcp runtime up --scope global --name cbx-mcp --port 3310 --replace`
135
+ - Check MCP Docker runtime:
136
+ `cbx mcp runtime status --scope global --name cbx-mcp`
137
+ - Stop MCP Docker runtime:
138
+ `cbx mcp runtime down --name cbx-mcp`
104
139
  - Rebuild managed routing block:
105
140
  `cbx workflows sync-rules --platform codex --scope project`
106
141
  - Diagnose setup issues:
@@ -72,6 +72,32 @@ When authoring custom Copilot assets, keep frontmatter schema compatible:
72
72
 
73
73
  ## 6) Skill Loading Policy
74
74
 
75
+ ## MCP-first Skill Discovery Order (Required)
76
+
77
+ 1. Use `skill_search` first to narrow candidate skills.
78
+ 2. Use `skill_browse_category` second to inspect category-level candidates.
79
+ 3. Use `skill_get` only for final selected skills that must be loaded.
80
+ 4. Keep pointer-first flow; avoid loading full skill text prematurely.
81
+
82
+ ## Skill Log Completion Block (Required)
83
+
84
+ After finishing skill selection/loading, publish:
85
+
86
+ - `selected_skills`: skill IDs selected for the task
87
+ - `loaded_skills`: skill IDs loaded via `skill_get`
88
+ - `skipped_skills`: considered but not loaded
89
+
90
+ ## Context Budget Block (Required, Estimated)
91
+
92
+ Immediately after the Skill Log block, publish estimated budget fields:
93
+
94
+ - `full_catalog_est_tokens`
95
+ - `loaded_est_tokens`
96
+ - `estimated_savings_tokens`
97
+ - `estimated_savings_percent`
98
+
99
+ Mark all context/token values as deterministic estimates (not provider metering).
100
+
75
101
  ### Smart Skill Selection (Adaptive)
76
102
 
77
103
  Use an adaptive load policy to control context size:
@@ -89,6 +115,8 @@ Use an adaptive load policy to control context size:
89
115
  4. If a mapped skill is missing, continue with best fallback and state it.
90
116
  5. Keep user-visible decision logs concise: selected skill(s) and one-line rationale.
91
117
 
118
+ After the skill log is complete, append the Context Budget block in the same response/update.
119
+
92
120
  ## 7) Socratic Gate (Before Complex Work)
93
121
 
94
122
  Before multi-file or architecture-impacting changes, ask targeted questions when requirements are unclear:
@@ -109,7 +137,13 @@ Before multi-file or architecture-impacting changes, ask targeted questions when
109
137
  Use these commands to keep this setup healthy:
110
138
 
111
139
  - Install/update bundle:
112
- `cbx workflows install --platform copilot --bundle agent-environment-setup --scope global --overwrite`
140
+ `cbx workflows install --platform copilot --bundle agent-environment-setup --scope global --overwrite --postman --stitch --mcp-runtime docker --mcp-fallback local --mcp-tool-sync`
141
+ - Start MCP Docker runtime:
142
+ `cbx mcp runtime up --scope global --name cbx-mcp --port 3310 --replace`
143
+ - Check MCP Docker runtime:
144
+ `cbx mcp runtime status --scope global --name cbx-mcp`
145
+ - Stop MCP Docker runtime:
146
+ `cbx mcp runtime down --name cbx-mcp`
113
147
  - Rebuild managed routing block:
114
148
  `cbx workflows sync-rules --platform copilot --scope project`
115
149
  - Diagnose setup issues:
@@ -72,6 +72,32 @@ When authoring custom Copilot assets, keep frontmatter schema compatible:
72
72
 
73
73
  ## 6) Skill Loading Policy
74
74
 
75
+ ## MCP-first Skill Discovery Order (Required)
76
+
77
+ 1. Use `skill_search` first to narrow candidate skills.
78
+ 2. Use `skill_browse_category` second to inspect category-level candidates.
79
+ 3. Use `skill_get` only for final selected skills that must be loaded.
80
+ 4. Keep pointer-first flow; avoid loading full skill text prematurely.
81
+
82
+ ## Skill Log Completion Block (Required)
83
+
84
+ After finishing skill selection/loading, publish:
85
+
86
+ - `selected_skills`: skill IDs selected for the task
87
+ - `loaded_skills`: skill IDs loaded via `skill_get`
88
+ - `skipped_skills`: considered but not loaded
89
+
90
+ ## Context Budget Block (Required, Estimated)
91
+
92
+ Immediately after the Skill Log block, publish estimated budget fields:
93
+
94
+ - `full_catalog_est_tokens`
95
+ - `loaded_est_tokens`
96
+ - `estimated_savings_tokens`
97
+ - `estimated_savings_percent`
98
+
99
+ Mark all context/token values as deterministic estimates (not provider metering).
100
+
75
101
  ### Smart Skill Selection (TIER 0)
76
102
 
77
103
  Before starting ANY task, the agent MUST:
@@ -88,6 +114,8 @@ Before starting ANY task, the agent MUST:
88
114
  3. Keep context lean; avoid loading unrelated skill documents.
89
115
  4. If a mapped skill is missing, continue with best fallback and state it.
90
116
 
117
+ After the skill log is complete, append the Context Budget block in the same response/update.
118
+
91
119
  ## 7) Socratic Gate (Before Complex Work)
92
120
 
93
121
  Before multi-file or architecture-impacting changes, ask targeted questions when requirements are unclear:
@@ -108,7 +136,13 @@ Before multi-file or architecture-impacting changes, ask targeted questions when
108
136
  Use these commands to keep this setup healthy:
109
137
 
110
138
  - Install/update bundle:
111
- `cbx workflows install --platform copilot --bundle agent-environment-setup --scope global --overwrite`
139
+ `cbx workflows install --platform copilot --bundle agent-environment-setup --scope global --overwrite --postman --stitch --mcp-runtime docker --mcp-fallback local --mcp-tool-sync`
140
+ - Start MCP Docker runtime:
141
+ `cbx mcp runtime up --scope global --name cbx-mcp --port 3310 --replace`
142
+ - Check MCP Docker runtime:
143
+ `cbx mcp runtime status --scope global --name cbx-mcp`
144
+ - Stop MCP Docker runtime:
145
+ `cbx mcp runtime down --name cbx-mcp`
112
146
  - Rebuild managed routing block:
113
147
  `cbx workflows sync-rules --platform copilot --scope project`
114
148
  - Diagnose setup issues:
@@ -32,11 +32,39 @@ Before starting ANY task, the agent MUST:
32
32
 
33
33
  ## 3) Skill Loading Policy
34
34
 
35
+ ## MCP-first Skill Discovery Order (Required)
36
+
37
+ 1. Use `skill_search` first to narrow candidate skills.
38
+ 2. Use `skill_browse_category` second to inspect category-level candidates.
39
+ 3. Use `skill_get` only for final selected skills that must be loaded.
40
+ 4. Keep pointer-first flow; avoid loading full skill text prematurely.
41
+
42
+ ## Skill Log Completion Block (Required)
43
+
44
+ After finishing skill selection/loading, publish:
45
+
46
+ - `selected_skills`: skill IDs selected for the task
47
+ - `loaded_skills`: skill IDs loaded via `skill_get`
48
+ - `skipped_skills`: considered but not loaded
49
+
50
+ ## Context Budget Block (Required, Estimated)
51
+
52
+ Immediately after the Skill Log block, publish estimated budget fields:
53
+
54
+ - `full_catalog_est_tokens`
55
+ - `loaded_est_tokens`
56
+ - `estimated_savings_tokens`
57
+ - `estimated_savings_percent`
58
+
59
+ Mark all context/token values as deterministic estimates (not provider metering).
60
+
35
61
  1. Load only skills needed for the active request.
36
62
  2. Prefer progressive disclosure: start from `SKILL.md`, then specific sections.
37
63
  3. Keep context lean; avoid loading unrelated skill documents.
38
64
  4. If a mapped skill is missing, continue with best fallback and state it.
39
65
 
66
+ After the skill log is complete, append the Context Budget block in the same response/update.
67
+
40
68
  ## 4) Request Classifier
41
69
 
42
70
  1. Question/explanation requests: answer directly.