@stackbilt/cli 0.1.6 → 0.1.8

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.
@@ -107,17 +107,22 @@ async function setupCommand(options, args) {
107
107
  console.log(JSON.stringify(result, null, 2));
108
108
  return index_2.EXIT_CODE.SUCCESS;
109
109
  }
110
- console.log(' Charter setup complete.');
111
- console.log(` Config path: ${result.configPath}`);
112
- console.log(` .charter initialized: ${result.initialized ? 'yes' : 'already present'}`);
110
+ console.log(' Governance guardrails are now active for this repo.');
111
+ console.log(` Baseline path: ${result.configPath}`);
112
+ console.log(` Baseline created: ${result.initialized ? 'yes' : 'already present'}`);
113
113
  if (result.workflow.mode === 'github') {
114
- console.log(` GitHub workflow: ${result.workflow.created ? 'created' : 'already present'} (${result.workflow.path})`);
114
+ console.log(` CI policy gate: ${result.workflow.created ? 'enabled' : 'already present'} (${result.workflow.path})`);
115
115
  }
116
116
  console.log('');
117
- console.log(' Next steps:');
118
- console.log(' 1. Run: charter validate --format text');
119
- console.log(' 2. Run: charter drift --format text');
120
- console.log(' 3. Tune .charter/config.json and patterns/*.json');
117
+ console.log(' What this gives you immediately:');
118
+ console.log(' - Merge-time checks for risky changes without governance links');
119
+ console.log(' - Drift detection against your blessed stack');
120
+ console.log(' - Audit-ready governance evidence from repo history');
121
+ console.log('');
122
+ console.log(' Run now:');
123
+ console.log(' 1. charter validate --format text');
124
+ console.log(' 2. charter drift --format text');
125
+ console.log(' 3. charter audit --format text');
121
126
  return index_2.EXIT_CODE.SUCCESS;
122
127
  }
123
128
  function writeFileIfMissing(targetPath, content, force) {
@@ -137,4 +142,4 @@ function getFlag(args, flag) {
137
142
  }
138
143
  return undefined;
139
144
  }
140
- //# sourceMappingURL=setup.js.map
145
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1,3 @@
1
+ import type { CLIOptions } from '../index';
2
+ export declare function quickstartCommand(options: CLIOptions): Promise<number>;
3
+ export declare function whyCommand(options: CLIOptions): Promise<number>;
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.quickstartCommand = quickstartCommand;
4
+ exports.whyCommand = whyCommand;
5
+ const node_child_process_1 = require("node:child_process");
6
+ const fs = require("node:fs");
7
+ const path = require("node:path");
8
+ const index_1 = require("../index");
9
+ const git_1 = require("@stackbilt/git");
10
+ async function quickstartCommand(options) {
11
+ const snapshot = getSnapshot(options.configPath);
12
+ if (options.format === 'json') {
13
+ console.log(JSON.stringify(snapshot, null, 2));
14
+ return index_1.EXIT_CODE.SUCCESS;
15
+ }
16
+ console.log('');
17
+ console.log(' Charter Quickstart');
18
+ console.log(' Turns governance from abstract policy into merge-time guardrails.');
19
+ console.log('');
20
+ console.log(' Repo snapshot:');
21
+ console.log(` - Git repo: ${snapshot.inGitRepo ? 'yes' : 'no'}`);
22
+ console.log(` - Governance baseline (.charter): ${snapshot.hasBaseline ? 'installed' : 'missing'}`);
23
+ console.log(` - Recent commits scanned: ${snapshot.commitsScanned}`);
24
+ console.log(` - Governance-linked commit coverage: ${snapshot.coveragePercent}%`);
25
+ console.log(` - High-risk commits without governance links: ${snapshot.highRiskUnlinked}`);
26
+ console.log('');
27
+ console.log(' Why teams use Charter:');
28
+ console.log(' - Catch risky, unreviewed changes before merge');
29
+ console.log(' - Create an auditable trail from code changes to governance decisions');
30
+ console.log(' - Keep policy checks consistent across local dev and CI');
31
+ console.log('');
32
+ console.log(` Next action: ${snapshot.nextAction}`);
33
+ console.log('');
34
+ return index_1.EXIT_CODE.SUCCESS;
35
+ }
36
+ async function whyCommand(options) {
37
+ if (options.format === 'json') {
38
+ console.log(JSON.stringify({
39
+ problem: 'Teams lose context on risky changes and approvals become inconsistent.',
40
+ charterSolves: [
41
+ 'Enforces governance trailers for significant changes',
42
+ 'Scans for stack drift against blessed patterns',
43
+ 'Produces repeatable audit evidence for PRs and reviews',
44
+ ],
45
+ value: [
46
+ 'Lower probability of breaking changes landing without architectural context',
47
+ 'Faster reviews because reviewers see linked decisions in commit metadata',
48
+ 'Clear governance posture for leadership and compliance reporting',
49
+ ],
50
+ start: 'charter setup --ci github',
51
+ }, null, 2));
52
+ return index_1.EXIT_CODE.SUCCESS;
53
+ }
54
+ console.log('');
55
+ console.log(' Why Charter');
56
+ console.log('');
57
+ console.log(' Problem it solves:');
58
+ console.log(' Governance intent lives in docs, but risky changes merge without clear decision links.');
59
+ console.log('');
60
+ console.log(' What Charter does:');
61
+ console.log(' - Enforces commit-level governance links for significant changes');
62
+ console.log(' - Detects drift from your blessed architecture patterns');
63
+ console.log(' - Generates audit output leadership and reviewers can actually use');
64
+ console.log('');
65
+ console.log(' Expected payoff:');
66
+ console.log(' - Fewer high-impact surprises in production');
67
+ console.log(' - Faster review cycles with clearer architectural accountability');
68
+ console.log(' - Consistent governance behavior across repos');
69
+ console.log('');
70
+ console.log(' Start here: charter setup --ci github');
71
+ console.log('');
72
+ return index_1.EXIT_CODE.SUCCESS;
73
+ }
74
+ function getSnapshot(configPath) {
75
+ const inGitRepo = isGitRepo();
76
+ const hasBaseline = fs.existsSync(path.join(configPath, 'config.json'));
77
+ if (!inGitRepo) {
78
+ return {
79
+ inGitRepo,
80
+ hasBaseline,
81
+ commitsScanned: 0,
82
+ coveragePercent: 0,
83
+ highRiskUnlinked: 0,
84
+ nextAction: 'Run this inside a git repository, then run: charter setup --ci github',
85
+ };
86
+ }
87
+ const commits = hasCommits() ? getRecentCommits(20) : [];
88
+ const parsed = (0, git_1.parseAllTrailers)(commits);
89
+ const linked = new Set();
90
+ for (const t of parsed.governedBy)
91
+ linked.add(t.commitSha);
92
+ for (const t of parsed.resolvesRequest)
93
+ linked.add(t.commitSha);
94
+ let highRiskUnlinked = 0;
95
+ for (const commit of commits) {
96
+ if (!linked.has(commit.sha) && (0, git_1.assessCommitRisk)(commit.files_changed, commit.message) === 'HIGH') {
97
+ highRiskUnlinked++;
98
+ }
99
+ }
100
+ const coveragePercent = commits.length > 0 ? Math.round((linked.size / commits.length) * 100) : 0;
101
+ const nextAction = !hasBaseline
102
+ ? 'Run: charter setup --ci github'
103
+ : highRiskUnlinked > 0
104
+ ? 'Run: charter validate --format text and add Governed-By trailers to high-risk commits'
105
+ : 'Run: charter audit --format text for a shareable governance posture report';
106
+ return {
107
+ inGitRepo,
108
+ hasBaseline,
109
+ commitsScanned: commits.length,
110
+ coveragePercent,
111
+ highRiskUnlinked,
112
+ nextAction,
113
+ };
114
+ }
115
+ function isGitRepo() {
116
+ try {
117
+ (0, node_child_process_1.execFileSync)('git', ['rev-parse', '--is-inside-work-tree'], { stdio: 'ignore' });
118
+ return true;
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ function getRecentCommits(count) {
125
+ try {
126
+ const log = (0, node_child_process_1.execFileSync)('git', ['log', `-${count}`, '--format=%H|%s', '--name-only'], {
127
+ encoding: 'utf-8',
128
+ maxBuffer: 10 * 1024 * 1024,
129
+ stdio: ['ignore', 'pipe', 'ignore'],
130
+ });
131
+ const commits = [];
132
+ let current = null;
133
+ for (const line of log.split('\n')) {
134
+ if (line.includes('|') && line.length > 40) {
135
+ if (current)
136
+ commits.push(current);
137
+ const [sha, ...message] = line.split('|');
138
+ current = {
139
+ sha,
140
+ author: '',
141
+ timestamp: '',
142
+ message: message.join('|'),
143
+ files_changed: [],
144
+ };
145
+ }
146
+ else if (line.trim() && current) {
147
+ current.files_changed.push(line.trim());
148
+ }
149
+ }
150
+ if (current)
151
+ commits.push(current);
152
+ return commits;
153
+ }
154
+ catch {
155
+ return [];
156
+ }
157
+ }
158
+ function hasCommits() {
159
+ try {
160
+ (0, node_child_process_1.execFileSync)('git', ['rev-parse', '--verify', 'HEAD'], {
161
+ stdio: 'ignore',
162
+ });
163
+ return true;
164
+ }
165
+ catch {
166
+ return false;
167
+ }
168
+ }
package/dist/index.js CHANGED
@@ -15,18 +15,21 @@ const validate_1 = require("./commands/validate");
15
15
  const audit_1 = require("./commands/audit");
16
16
  const drift_1 = require("./commands/drift");
17
17
  const classify_1 = require("./commands/classify");
18
+ const why_1 = require("./commands/why");
18
19
  const package_json_1 = require("../package.json");
19
20
  const CLI_VERSION = package_json_1.version;
20
21
  const HELP = `
21
22
  charter - repo-level governance toolkit
22
23
 
23
24
  Usage:
25
+ charter Show immediate governance value + risk snapshot
24
26
  charter setup [--ci github] Bootstrap .charter/ and optional CI workflow
25
27
  charter init Scaffold .charter/ config directory
26
28
  charter validate Validate git commits for governance trailers
27
29
  charter audit Generate governance audit report
28
30
  charter drift [--path <dir>] Scan files for pattern drift
29
31
  charter classify <subject> Classify a change (SURFACE/LOCAL/CROSS_CUTTING)
32
+ charter why Explain why teams adopt Charter and expected ROI
30
33
  charter doctor Check CLI + config health
31
34
  charter --help Show this help
32
35
  charter --version Show version
@@ -52,7 +55,7 @@ class CLIError extends Error {
52
55
  }
53
56
  exports.CLIError = CLIError;
54
57
  async function run(args) {
55
- if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
58
+ if (args.includes('--help') || args.includes('-h')) {
56
59
  console.log(HELP);
57
60
  return exports.EXIT_CODE.SUCCESS;
58
61
  }
@@ -60,18 +63,21 @@ async function run(args) {
60
63
  console.log(`charter v${CLI_VERSION}`);
61
64
  return exports.EXIT_CODE.SUCCESS;
62
65
  }
63
- const command = args[0];
64
- const restArgs = args.slice(1);
65
- const format = getFlag(restArgs, '--format') || 'text';
66
+ const format = getFlag(args, '--format') || 'text';
66
67
  if (format !== 'text' && format !== 'json') {
67
68
  throw new CLIError(`Invalid --format value: ${format}. Use text or json.`);
68
69
  }
69
70
  const options = {
70
- configPath: getFlag(restArgs, '--config') || '.charter',
71
+ configPath: getFlag(args, '--config') || '.charter',
71
72
  format,
72
- ciMode: restArgs.includes('--ci'),
73
- yes: restArgs.includes('--yes'),
73
+ ciMode: args.includes('--ci'),
74
+ yes: args.includes('--yes'),
74
75
  };
76
+ if (args.length === 0 || args[0].startsWith('-')) {
77
+ return (0, why_1.quickstartCommand)(options);
78
+ }
79
+ const command = args[0];
80
+ const restArgs = args.slice(1);
75
81
  switch (command) {
76
82
  case 'setup':
77
83
  return (0, setup_1.setupCommand)(options, restArgs);
@@ -85,6 +91,8 @@ async function run(args) {
85
91
  return (0, drift_1.driftCommand)(options, restArgs);
86
92
  case 'classify':
87
93
  return (0, classify_1.classifyCommand)(options, restArgs);
94
+ case 'why':
95
+ return (0, why_1.whyCommand)(options);
88
96
  case 'doctor':
89
97
  return (0, doctor_1.doctorCommand)(options);
90
98
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackbilt/cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Charter CLI — repo-level governance checks",
5
5
  "bin": {
6
6
  "charter": "./dist/bin.js"