mindforge-cc 11.4.0 → 11.5.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 (92) hide show
  1. package/.agent/CLAUDE.md +13 -0
  2. package/.agent/hooks/lib/hook-flags.js +78 -0
  3. package/.agent/hooks/lib/pretooluse-visible-output.js +46 -0
  4. package/.agent/hooks/mindforge-block-no-verify.js +552 -0
  5. package/.agent/hooks/mindforge-config-protection.js +144 -0
  6. package/.agent/hooks/run-with-flags.js +207 -0
  7. package/.agent/mindforge/checkpoint.md +76 -0
  8. package/.agent/mindforge/harness-audit.md +59 -0
  9. package/.agent/mindforge/instinct.md +46 -0
  10. package/.agent/mindforge/orch-add-feature.md +43 -0
  11. package/.agent/mindforge/orch-build-mvp.md +48 -0
  12. package/.agent/mindforge/orch-change-feature.md +45 -0
  13. package/.agent/mindforge/orch-fix-defect.md +43 -0
  14. package/.agent/mindforge/orch-refine-code.md +43 -0
  15. package/.claude/CLAUDE.md +13 -0
  16. package/.claude/commands/mindforge/checkpoint.md +76 -0
  17. package/.claude/commands/mindforge/execute-phase.md +47 -6
  18. package/.claude/commands/mindforge/harness-audit.md +59 -0
  19. package/.claude/commands/mindforge/instinct.md +46 -0
  20. package/.claude/commands/mindforge/orch-add-feature.md +43 -0
  21. package/.claude/commands/mindforge/orch-build-mvp.md +48 -0
  22. package/.claude/commands/mindforge/orch-change-feature.md +45 -0
  23. package/.claude/commands/mindforge/orch-fix-defect.md +43 -0
  24. package/.claude/commands/mindforge/orch-refine-code.md +43 -0
  25. package/.claude/commands/mindforge/plan-write.md +11 -0
  26. package/.claude/commands/mindforge/product-spec.md +76 -0
  27. package/.mindforge/config.json +2 -2
  28. package/.mindforge/engine/instincts/instinct-schema.md +17 -9
  29. package/.mindforge/imported-agents.jsonl +10 -0
  30. package/.mindforge/manifests/install-components.json +36 -0
  31. package/.mindforge/manifests/install-modules.json +193 -0
  32. package/.mindforge/manifests/install-profiles.json +57 -0
  33. package/.mindforge/memory/sync-manifest.json +1 -1
  34. package/.mindforge/personas/gan-evaluator.md +226 -0
  35. package/.mindforge/personas/gan-generator.md +151 -0
  36. package/.mindforge/personas/gan-planner.md +118 -0
  37. package/.mindforge/personas/harness-optimizer.md +55 -0
  38. package/.mindforge/personas/loop-operator.md +58 -0
  39. package/.mindforge/schemas/hooks.schema.json +199 -0
  40. package/.mindforge/schemas/install-modules.schema.json +44 -0
  41. package/.mindforge/schemas/install-state.schema.json +95 -0
  42. package/.mindforge/schemas/plugin.schema.json +75 -0
  43. package/.mindforge/schemas/provenance.schema.json +31 -0
  44. package/.mindforge/skills/agent-architecture-audit/SKILL.md +272 -0
  45. package/.mindforge/skills/continuous-learning/SKILL.md +16 -0
  46. package/.mindforge/skills/orch-pipeline/SKILL.md +284 -0
  47. package/.mindforge/skills/writing-plans/SKILL.md +76 -0
  48. package/CHANGELOG.md +75 -0
  49. package/MINDFORGE.md +3 -3
  50. package/RELEASENOTES.md +86 -0
  51. package/SECURITY.md +16 -0
  52. package/bin/autonomous/auto-runner.js +46 -5
  53. package/bin/autonomous/handoff-schema.js +114 -0
  54. package/bin/autonomous/session-guardian.sh +138 -0
  55. package/bin/autonomous/supervisor.js +98 -0
  56. package/bin/change-classifier.js +19 -5
  57. package/bin/governance/approve.js +61 -28
  58. package/bin/governance/config-manager.js +3 -1
  59. package/bin/governance/rbac-manager.js +14 -6
  60. package/bin/harness-audit.js +520 -0
  61. package/bin/hooks/instinct-capture-hook.js +16 -1
  62. package/bin/hooks/lib/detect-project.js +72 -0
  63. package/bin/installer/harness-adapter-compliance.js +321 -0
  64. package/bin/installer/install-manifests.js +200 -0
  65. package/bin/installer/install-state.js +243 -0
  66. package/bin/installer-core.js +1 -1
  67. package/bin/learning/instinct-cli.js +359 -0
  68. package/bin/learning/lib/ssrf-guard.js +252 -0
  69. package/bin/memory/eis-client.js +31 -10
  70. package/bin/models/llm-errors.js +79 -0
  71. package/bin/models/model-client.js +39 -4
  72. package/bin/models/ollama-provider.js +115 -0
  73. package/bin/models/openai-provider.js +40 -9
  74. package/bin/models/profiles-loader.js +147 -0
  75. package/bin/models/provider-registry.js +59 -0
  76. package/bin/revops/market-evaluator.js +23 -2
  77. package/bin/revops/router-steering-v2.js +17 -2
  78. package/bin/security/trust-boundaries.js +15 -3
  79. package/bin/utils/readiness-gate.js +169 -0
  80. package/bin/worktree/engine.js +497 -0
  81. package/package.json +8 -2
  82. package/subagents/categories/04-quality-security/.claude-plugin/plugin.json +10 -0
  83. package/subagents/categories/04-quality-security/go-build-resolver.md +105 -0
  84. package/subagents/categories/04-quality-security/go-reviewer.md +87 -0
  85. package/subagents/categories/04-quality-security/python-reviewer.md +109 -0
  86. package/subagents/categories/04-quality-security/react-build-resolver.md +215 -0
  87. package/subagents/categories/04-quality-security/react-reviewer.md +167 -0
  88. package/subagents/categories/04-quality-security/rust-build-resolver.md +159 -0
  89. package/subagents/categories/04-quality-security/rust-reviewer.md +105 -0
  90. package/subagents/categories/04-quality-security/silent-failure-hunter.md +67 -0
  91. package/subagents/categories/04-quality-security/type-design-analyzer.md +58 -0
  92. package/subagents/categories/04-quality-security/typescript-reviewer.md +126 -0
@@ -12,14 +12,9 @@ const os = require('os');
12
12
  const crypto = require('crypto');
13
13
  const { execFileSync } = require('child_process');
14
14
 
15
- const REASON = process.argv[2] || 'Manual approval for sensitive changes.';
16
15
  const ROOT = path.resolve(__dirname, '../../');
17
16
  const APPROVALS_DIR = path.join(ROOT, '.planning/approvals');
18
17
 
19
- if (!fs.existsSync(APPROVALS_DIR)) {
20
- fs.mkdirSync(APPROVALS_DIR, { recursive: true });
21
- }
22
-
23
18
  /**
24
19
  * Attempts to retrieve the GPG signing key configured in git.
25
20
  * Returns null if no key is configured or git is unavailable.
@@ -34,35 +29,65 @@ function getGPGSigningKey() {
34
29
  }
35
30
 
36
31
  /**
37
- * Verifies the identity of the approver using GPG if available.
38
- * Falls back to git identity only (with warning) if no GPG key is configured.
32
+ * Verifies the identity of the approver using GPG.
33
+ *
34
+ * FAIL-CLOSED (Wave 6): a Tier 3 approval is a security gate. If no GPG signing
35
+ * key is configured, identity cannot be cryptographically attributed — git
36
+ * identity comes from spoofable env (USER / git config), so it is NOT a
37
+ * verification. We therefore REFUSE to mint an approval unless the operator
38
+ * explicitly opts into the weaker git-identity mode via
39
+ * MINDFORGE_ALLOW_UNVERIFIED_APPROVAL=1 (audited as unverified). Previously this
40
+ * returned {verified:false} but the record was written anyway and no consumer
41
+ * checked the flag — a cosmetic gate.
42
+ *
39
43
  * @param {string} approver - The approver identity string
44
+ * @returns {{verified:boolean, method:string, identity:string, keyId?:string}}
45
+ * @throws if no GPG key AND the unverified-approval opt-in is not set.
40
46
  */
41
47
  function verifyApproverIdentity(approver) {
42
48
  const gpgKey = getGPGSigningKey();
43
49
 
44
50
  if (!gpgKey) {
45
- console.warn('[GOVERNANCE] No GPG signing key configured — approval accepted with git identity only');
46
- return { verified: false, method: 'git_identity', identity: approver };
51
+ const allowUnverified = process.env.MINDFORGE_ALLOW_UNVERIFIED_APPROVAL === '1';
52
+ if (!allowUnverified) {
53
+ throw new Error(
54
+ 'No GPG signing key configured (git config user.signingkey is empty). ' +
55
+ 'A Tier 3 approval requires a verifiable identity. Either configure GPG signing, ' +
56
+ 'or explicitly accept an UNVERIFIED approval by setting ' +
57
+ 'MINDFORGE_ALLOW_UNVERIFIED_APPROVAL=1 (the record will be marked verified:false).'
58
+ );
59
+ }
60
+ console.warn('[GOVERNANCE] No GPG key — minting an UNVERIFIED approval (MINDFORGE_ALLOW_UNVERIFIED_APPROVAL=1). ' +
61
+ 'git identity is spoofable; this approval is NOT cryptographically attributed.');
62
+ return { verified: false, method: 'git_identity_unverified', identity: approver };
47
63
  }
48
64
 
49
65
  return { verified: true, method: 'gpg_key', identity: approver, keyId: gpgKey };
50
66
  }
51
67
 
52
- async function approve() {
53
- const pkgPath = path.join(ROOT, 'package.json');
54
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
68
+ /**
69
+ * Mint a Tier 3 approval record. Throws (fail-closed) if identity cannot be
70
+ * verified and the unverified-approval opt-in is not set — the record is NOT
71
+ * written in that case.
72
+ * @param {{reason?:string, approvalsDir?:string, root?:string}} [opts]
73
+ * @returns {{filePath:string, record:object}}
74
+ */
75
+ function approve(opts = {}) {
76
+ const reason = opts.reason || 'Manual approval for sensitive changes.';
77
+ const root = opts.root || ROOT;
78
+ const approvalsDir = opts.approvalsDir || APPROVALS_DIR;
79
+
80
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
55
81
 
56
82
  const id = `MF-AUTH-${Date.now().toString(36).toUpperCase()}`;
57
83
  const timestamp = new Date().toISOString();
58
84
  const approver = process.env.USER || 'MindForge User';
59
85
 
60
- // Verify approver identity (GPG if available, git identity fallback)
86
+ // Verify approver identity THROWS fail-closed if unverifiable (before any write).
61
87
  const identityVerification = verifyApproverIdentity(approver);
62
88
 
63
- // Calculate a signature based on current state
64
89
  const signature = crypto.createHash('sha256')
65
- .update(`${id}:${REASON}:${timestamp}:${os.hostname()}`)
90
+ .update(`${id}:${reason}:${timestamp}:${os.hostname()}`)
66
91
  .digest('hex');
67
92
 
68
93
  const record = {
@@ -72,25 +97,33 @@ async function approve() {
72
97
  tier: 3,
73
98
  approved_by: approver,
74
99
  timestamp,
75
- reason: REASON,
100
+ reason,
76
101
  signature: `sha256:${signature}`,
77
102
  identity_verification: identityVerification
78
103
  };
79
104
 
105
+ if (!fs.existsSync(approvalsDir)) fs.mkdirSync(approvalsDir, { recursive: true });
80
106
  const filename = `approval-${id.toLowerCase()}.json`;
81
- const filePath = path.join(APPROVALS_DIR, filename);
82
-
107
+ const filePath = path.join(approvalsDir, filename);
83
108
  fs.writeFileSync(filePath, JSON.stringify(record, null, 2));
84
109
 
85
- console.log('\n✅ Governance approval generated!\n');
86
- console.log(`ID: ${id}`);
87
- console.log(`Reason: ${REASON}`);
88
- console.log(`Verified: ${identityVerification.verified ? 'GPG (' + identityVerification.keyId + ')' : 'git identity only (no GPG key)'}`);
89
- console.log(`File: .planning/approvals/${filename}`);
90
- console.log('\nCommit this file to unblock Tier 3 gates in CI.\n');
110
+ return { filePath, record, filename };
91
111
  }
92
112
 
93
- approve().catch(err => {
94
- console.error(`❌ Approval failed: ${err.message}`);
95
- process.exit(1);
96
- });
113
+ module.exports = { verifyApproverIdentity, getGPGSigningKey, approve };
114
+
115
+ if (require.main === module) {
116
+ try {
117
+ const { filename, record } = approve({ reason: process.argv[2] });
118
+ const iv = record.identity_verification;
119
+ console.log('\n✅ Governance approval generated!\n');
120
+ console.log(`ID: ${record.id}`);
121
+ console.log(`Reason: ${record.reason}`);
122
+ console.log(`Verified: ${iv.verified ? 'GPG (' + iv.keyId + ')' : 'git identity only — UNVERIFIED'}`);
123
+ console.log(`File: .planning/approvals/${filename}`);
124
+ console.log('\nCommit this file to unblock Tier 3 gates in CI.\n');
125
+ } catch (err) {
126
+ console.error(`❌ Approval failed: ${err.message}`);
127
+ process.exit(1);
128
+ }
129
+ }
@@ -21,7 +21,9 @@ class ConfigManager {
21
21
  if (fs.existsSync(this.configPath)) {
22
22
  const raw = fs.readFileSync(this.configPath, 'utf8');
23
23
  this.config = JSON.parse(raw);
24
- console.log(`[ConfigManager] Loaded configuration from ${this.configPath}`);
24
+ // Diagnostic goes to stderr (not stdout) so it never pollutes JSON that a
25
+ // consumer parses from this process's stdout. Matches the warn/error lines below.
26
+ console.error(`[ConfigManager] Loaded configuration from ${this.configPath}`);
25
27
  } else {
26
28
  console.warn(`[ConfigManager] Config file not found at ${this.configPath}. Using defaults.`);
27
29
  this.config = { env: 'default' };
@@ -40,18 +40,26 @@ class RBACManager {
40
40
  }
41
41
 
42
42
  /**
43
- * [HARDEN] Dynamically binds roles based on ZTAI trust tiers if no explicit role exists.
44
- * Ensures high-trust agents automatically get architect-level visibility.
43
+ * [HARDEN] Dynamically binds roles based on ZTAI trust tiers on top of the
44
+ * agent's explicit/default roles. High-trust agents automatically gain
45
+ * architect-level visibility.
46
+ *
47
+ * ztai-manager is a SINGLETON instance (not a constructor), and exposes no
48
+ * getIdentity(); the agent's tier lives in the trust registry, read via
49
+ * getAgent(did). Fails SAFE: an unregistered/unknown DID has no resolvable
50
+ * tier, so it receives only its base roles (no tier-based elevation) rather
51
+ * than throwing. (Wave 6: the previous `new ztai().getIdentity()` threw on
52
+ * every call — "ztai is not a constructor".)
45
53
  */
46
54
  async getRolesByTier(did) {
47
- const manager = new ztai();
48
- const identity = await manager.getIdentity();
49
55
  const explicit = this.getRoles(did);
56
+ const agent = ztai.getAgent(did);
57
+ const tier = agent && typeof agent.tier === 'number' ? agent.tier : 0;
50
58
 
51
- if (identity.tier >= 3) {
59
+ if (tier >= 3) {
52
60
  return [...new Set([...explicit, 'lead-architect'])];
53
61
  }
54
- if (identity.tier >= 2) {
62
+ if (tier >= 2) {
55
63
  return [...new Set([...explicit, 'developer'])];
56
64
  }
57
65
  return explicit;