@cairnkeep/cli 2.25.0 → 2.26.0

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 (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/docs/README.md +2 -0
  3. package/docs/harness-compatibility.md +5 -2
  4. package/docs/learning/CURRICULUM-MAP.md +3 -3
  5. package/docs/learning/FEATURE-GUIDE.md +7 -1
  6. package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
  7. package/docs/learning/lessons/L01-safe-trial.md +3 -3
  8. package/docs/learning/lessons/L02-installation.md +2 -2
  9. package/docs/learning/lessons/L03-first-project.md +1 -1
  10. package/docs/learning/lessons/L19-validated-skill-improvement.md +1 -1
  11. package/docs/learning/lessons/L20-mcp-tool-profiles.md +1 -1
  12. package/docs/learning/lessons/L21-context-packs.md +1 -1
  13. package/docs/learning/lessons/L22-native-windows.md +2 -2
  14. package/docs/learning/lessons/L23-guided-setup.md +1 -1
  15. package/docs/learning/lessons/L24-okf-exchange.md +1 -1
  16. package/docs/learning/lessons/L25-playbooks.md +1 -1
  17. package/docs/learning/lessons/L26-context-intelligence.md +1 -1
  18. package/docs/learning/lessons/L27-ecosystem-evidence.md +1 -1
  19. package/docs/learning/lessons/L28-security-assurance.md +5 -1
  20. package/docs/learning/lessons/L29-team-continuity.md +33 -1
  21. package/docs/learning/tracks/operator.md +2 -0
  22. package/docs/learning/video-scripts/V28-security-assurance.md +4 -0
  23. package/docs/learning/video-scripts/V29-team-continuity.md +19 -1
  24. package/docs/operating.md +6 -0
  25. package/docs/privacy-and-data-flow.md +21 -1
  26. package/docs/provider-data-flow-review.md +48 -0
  27. package/docs/security-assurance.md +11 -0
  28. package/docs/storage.md +14 -0
  29. package/docs/team-onboarding.md +226 -0
  30. package/docs/team-pilot.md +2 -0
  31. package/docs/team.md +11 -0
  32. package/examples/eval/bundled-fake.json +1 -1
  33. package/mcp-memory-server/dist/capability-config.js +12 -1
  34. package/mcp-memory-server/dist/team-cli.js +15 -5
  35. package/mcp-memory-server/dist/team-client.js +71 -0
  36. package/mcp-memory-server/dist/team-mcp.js +8 -1
  37. package/mcp-memory-server/dist/team-store.js +8 -2
  38. package/mcp-memory-server/package.json +2 -2
  39. package/package.json +1 -1
  40. package/scripts/cairn-cli.mjs +6 -1
  41. package/scripts/completion.sh +11 -3
  42. package/scripts/lib/team-retention.mjs +1 -1
  43. package/scripts/team-connect.mjs +366 -0
  44. package/scripts/test-ci-sharding.sh +1 -1
  45. package/scripts/test-codeql-cohort.mjs +35 -0
  46. package/scripts/test-completion.sh +4 -1
  47. package/scripts/test-package-install.sh +1 -0
  48. package/scripts/test-phase18-capability-lifecycle.sh +2 -2
  49. package/scripts/test-security-baseline.sh +1 -0
  50. package/scripts/test-team-docs.sh +11 -2
  51. package/scripts/test-team-installed.mjs +51 -0
  52. package/scripts/test-team-pilot.mjs +43 -1
  53. package/scripts/verify-security-baseline.mjs +20 -0
  54. package/scripts/windows-platform.mjs +1 -1
@@ -33,6 +33,25 @@ function walk(value, visit, path = "workflow") {
33
33
  }
34
34
  }
35
35
 
36
+ export function validateCodeqlCohort(workflows, dependabot) {
37
+ const references = [];
38
+ for (const workflow of workflows) walk(workflow, (key, value) => {
39
+ if (key === "uses" && typeof value === "string" && value.startsWith("github/codeql-action/")) {
40
+ assert.match(value, /^github\/codeql-action\/[^@\s]+@[a-f0-9]{40}$/, "CodeQL actions must be pinned to a full commit");
41
+ references.push(value);
42
+ }
43
+ });
44
+ assert.ok(references.length > 0, "CodeQL cohort is missing");
45
+ assert.equal(new Set(references.map(value => value.split("@")[1])).size, 1, "CodeQL cohort must use the same commit across workflows");
46
+ for (const action of ["init", "analyze", "upload-sarif"]) {
47
+ assert.ok(references.some(value => value.startsWith(`github/codeql-action/${action}@`)), `CodeQL cohort is missing ${action}`);
48
+ }
49
+ const updates = dependabot?.updates?.filter(update => update["package-ecosystem"] === "github-actions" && update.directory === "/") ?? [];
50
+ assert.equal(updates.length, 1, "CodeQL cohort requires one root GitHub Actions update group");
51
+ const group = updates[0].groups?.["codeql-action"];
52
+ assert.deepEqual(group, { patterns: ["github/codeql-action/*"] }, "CodeQL dependency group must cover the entire cohort without exclusions or update-type restrictions");
53
+ }
54
+
36
55
  function validateWorkflow(name, workflow) {
37
56
  assert.ok(workflow && typeof workflow === "object" && !Array.isArray(workflow), `${name} is not a workflow mapping`);
38
57
  assert.ok(workflow.permissions && typeof workflow.permissions === "object" && !Array.isArray(workflow.permissions), `${name} must have an explicit workflow permission mapping`);
@@ -123,6 +142,7 @@ for (const [index, [fixture, expected]] of maliciousFixtures.entries()) {
123
142
 
124
143
  for (const { name, workflow } of sources) validateWorkflow(name, workflow);
125
144
  validatePublicationPermissions(publish);
145
+ validateCodeqlCohort(sources.map(source => source.workflow), parse(readFileSync(join(root, ".github", "dependabot.yml"), "utf8")));
126
146
 
127
147
  const security = sources.find(({ name }) => name === "security.yml")?.text ?? "";
128
148
  assert.match(security, /github\/codeql-action\/init@[a-f0-9]{40}/);
@@ -779,7 +779,7 @@ export function powershellCompletion() {
779
779
  $pack = 'init','lock','validate','install','import-okf','validate-okf','export-okf','list','show','remove','enable','disable','update','skills','approve-skill','revoke-skill','doctor','--repair','--project','--project-id','--json'
780
780
  $proposals = 'create','list','show','apply','doctor','--session','--scope','--model','--category','--project','--json'
781
781
  $security = 'doctor','--project','--json'
782
- $team = 'init','project','member','credential','create','set','remove','issue','revoke','serve','mcp','list','read','search','history','propose','proposals','proposal-show','review','audit','doctor','backup','restore','memory-delete','--organization','--data','--project','--roles','--class','--expires-at','--output','--input','--confirm','--port','--key','--query','--proposal','--decision','--revision','--project-root'
782
+ $team = 'connect','disconnect','init','project','member','credential','create','set','remove','issue','revoke','serve','mcp','list','read','search','history','propose','proposals','proposal-show','review','audit','doctor','backup','restore','memory-delete','--organization','--data','--project','--roles','--class','--expires-at','--output','--input','--confirm','--port','--key','--query','--proposal','--decision','--revision','--project-root','--connection','--client','--url','--token-file','--harness','--access','--apply','--yes'
783
783
  $evaluation = 'validate','run','ablate','report','prune','delete','protocol','--task-set','--adapter','--output','--repetitions','--seed','--yes','--json','--disable','--experiment','--older-than-days','--dry-run','--trajectory','--codex-jsonl','--capture-authorized'
784
784
  $candidates = if ($commandAst.ToString() -match '^\\s*cairn\\s+setup(?:\\s|$)') { $setup } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+team(?:\\s|$)') { $team } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+playbook(?:\\s|$)') { $playbook } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+pack(?:\\s|$)') { $pack } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+proposals(?:\\s|$)') { $proposals } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+security(?:\\s|$)') { $security } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+eval(?:\\s|$)') { $evaluation } else { $commands }
785
785
  $candidates | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {