@yeison.restrepo.r/code-conductor 1.23.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.
- package/LICENSE +185 -0
- package/README.md +314 -0
- package/bin/code-conductor.mjs +133 -0
- package/global/CLAUDE.md +93 -0
- package/global/commands/cc-checkpoint.md +50 -0
- package/global/commands/cc-compact.md +49 -0
- package/global/commands/cc-lang.md +32 -0
- package/global/commands/cc-stack.md +69 -0
- package/global/hooks/graphify-ast-refresh.py +81 -0
- package/global/hooks/verbosity-remind.sh +372 -0
- package/global/memory/personal.md +24 -0
- package/global/memory/verbosity.md +7 -0
- package/global/settings.json +24 -0
- package/lib/installer/config.mjs +51 -0
- package/lib/installer/deploy.mjs +76 -0
- package/lib/installer/env.mjs +35 -0
- package/lib/installer/settings.mjs +77 -0
- package/package.json +34 -0
- package/project-template/.claude/commands/cc-debug.md +42 -0
- package/project-template/.claude/commands/cc-docs.md +49 -0
- package/project-template/.claude/commands/cc-implement.md +164 -0
- package/project-template/.claude/commands/cc-init.md +84 -0
- package/project-template/.claude/commands/cc-plan.md +114 -0
- package/project-template/.claude/commands/cc-refactor.md +42 -0
- package/project-template/.claude/commands/cc-resume.md +142 -0
- package/project-template/.claude/commands/cc-review.md +77 -0
- package/project-template/.claude/commands/cc-spec.md +138 -0
- package/project-template/.claude/commands/cc-test.md +56 -0
- package/project-template/.claude/hooks/context-guard.ps1 +55 -0
- package/project-template/.claude/hooks/context-guard.sh +43 -0
- package/project-template/.claude/hooks/post-compact.ps1 +41 -0
- package/project-template/.claude/hooks/post-compact.sh +36 -0
- package/project-template/.claude/hooks/pre-tool-use.sh +81 -0
- package/project-template/.claude/hooks/verbosity-remind.sh +168 -0
- package/project-template/.claude/memory/context-threshold.txt +1 -0
- package/project-template/.claude/memory/project.md +48 -0
- package/project-template/.claude/settings.json +52 -0
- package/project-template/CLAUDE.md +104 -0
- package/skills/agent-delegation.md +44 -0
- package/skills/code-simplifier.md +124 -0
- package/skills/critical-review.md +75 -0
- package/skills/memory-first.md +50 -0
- package/skills/verbosity.md +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship made available under
|
|
36
|
+
the License, as indicated by a copyright notice that is included in
|
|
37
|
+
or attached to the work (an example is provided in the Appendix below).
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
|
+
form, that is based on (or derived from) the Work and for which the
|
|
41
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
43
|
+
of this License, Derivative Works shall not include works that remain
|
|
44
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
45
|
+
the Work and derivative works thereof.
|
|
46
|
+
|
|
47
|
+
"Contribution" shall mean, as submitted to the Licensor for inclusion
|
|
48
|
+
in the Work by the copyright owner or by an individual or Legal Entity
|
|
49
|
+
authorized to submit on behalf of the copyright owner. For the purposes
|
|
50
|
+
of this definition, "submitted" means any form of electronic, verbal,
|
|
51
|
+
or written communication sent to the Licensor or its representatives,
|
|
52
|
+
including but not limited to communication on electronic mailing lists,
|
|
53
|
+
source code control systems, and issue tracking systems that are managed
|
|
54
|
+
by, or on behalf of, the Licensor for the purpose of discussing and
|
|
55
|
+
improving the Work, but excluding communication that is conspicuously
|
|
56
|
+
marked or otherwise designated in writing by the copyright owner as
|
|
57
|
+
"Not a Contribution."
|
|
58
|
+
|
|
59
|
+
"Contributor" shall mean Licensor and any Legal Entity on behalf of
|
|
60
|
+
whom a Contribution has been received by the Licensor and subsequently
|
|
61
|
+
incorporated within the Work.
|
|
62
|
+
|
|
63
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
64
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
65
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
66
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
67
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
68
|
+
Work and such Derivative Works in Source or Object form.
|
|
69
|
+
|
|
70
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
71
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
72
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
73
|
+
(except as stated in this section) patent license to make, have made,
|
|
74
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
75
|
+
where such license applies only to those patent claims licensable
|
|
76
|
+
by such Contributor that are necessarily infringed by their
|
|
77
|
+
Contribution(s) alone or by combination of their Contributions
|
|
78
|
+
with the Work to which such Contributions were submitted. If You
|
|
79
|
+
institute patent litigation against any entity (including a cross-claim
|
|
80
|
+
or counterclaim in a lawsuit) alleging that the Work or any
|
|
81
|
+
Contribution incorporated within the Work constitutes direct or
|
|
82
|
+
contributory patent infringement, then any patent licenses granted
|
|
83
|
+
to You under this License for that Work shall terminate as of the
|
|
84
|
+
date such litigation is filed.
|
|
85
|
+
|
|
86
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
87
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
88
|
+
modifications, and in Source or Object form, provided that You
|
|
89
|
+
meet the following conditions:
|
|
90
|
+
|
|
91
|
+
(a) You must give any other recipients of the Work or Derivative
|
|
92
|
+
Works a copy of this License; and
|
|
93
|
+
|
|
94
|
+
(b) You must cause any modified files to carry prominent notices
|
|
95
|
+
stating that You changed the files; and
|
|
96
|
+
|
|
97
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
98
|
+
that You distribute, all copyright, patent, trademark, and
|
|
99
|
+
attribution notices from the Source form of the Work,
|
|
100
|
+
excluding those notices that do not pertain to any part of
|
|
101
|
+
the Derivative Works; and
|
|
102
|
+
|
|
103
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
104
|
+
distribution, You must include a readable copy of the
|
|
105
|
+
attribution notices contained within such NOTICE file, in
|
|
106
|
+
at least one of the following places: within a NOTICE text
|
|
107
|
+
file distributed as part of the Derivative Works; within
|
|
108
|
+
the Source form or documentation, if provided along with the
|
|
109
|
+
Derivative Works; or, within a display generated by the
|
|
110
|
+
Derivative Works, if and wherever such third-party notices
|
|
111
|
+
normally appear. The contents of the NOTICE file are for
|
|
112
|
+
informational purposes only and do not modify the License.
|
|
113
|
+
You may add Your own attribution notices within Derivative
|
|
114
|
+
Works that You distribute, alongside or as an additional
|
|
115
|
+
addendum to the NOTICE text from the Work, provided that
|
|
116
|
+
such additional attribution notices cannot be construed
|
|
117
|
+
as modifying the License.
|
|
118
|
+
|
|
119
|
+
You may add Your own license statement for Your modifications and
|
|
120
|
+
may provide additional grant of rights to use, copy, modify, merge,
|
|
121
|
+
publish, distribute, sublicense, and/or sell copies of the
|
|
122
|
+
Derivative Works, and to permit persons to whom the Derivative Works
|
|
123
|
+
are furnished to do so.
|
|
124
|
+
|
|
125
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
126
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
127
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
128
|
+
this License, without any additional terms or conditions.
|
|
129
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
130
|
+
the terms of any separate license agreement you may have executed
|
|
131
|
+
with Licensor regarding such Contributions.
|
|
132
|
+
|
|
133
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
134
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
135
|
+
except as required for reasonable and customary use in describing the
|
|
136
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
137
|
+
|
|
138
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
139
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
140
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
141
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
142
|
+
implied, including, without limitation, any conditions of title,
|
|
143
|
+
merchantability, or fitness for a particular purpose. You are
|
|
144
|
+
solely responsible for determining the appropriateness of using
|
|
145
|
+
or redistributing the Work and assume any risks associated with
|
|
146
|
+
Your exercise of permissions under this License.
|
|
147
|
+
|
|
148
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
149
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
150
|
+
unless required by applicable law (such as deliberate and grossly
|
|
151
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
152
|
+
liable to You for damages, including any direct, indirect, special,
|
|
153
|
+
incidental, or exemplary damages of any character arising as a
|
|
154
|
+
result of this License or out of the use or inability to use the
|
|
155
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
156
|
+
work stoppage, computer failure or malfunction, or all other
|
|
157
|
+
commercial damages or losses), even if such Contributor has been
|
|
158
|
+
advised of the possibility of such damages.
|
|
159
|
+
|
|
160
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
161
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
162
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
163
|
+
or other liability obligations and/or rights consistent with this
|
|
164
|
+
License. However, in accepting such obligations, You may act only
|
|
165
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
166
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
167
|
+
defend, and hold each Contributor harmless for any liability
|
|
168
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
169
|
+
of your accepting any warranty or additional liability.
|
|
170
|
+
|
|
171
|
+
END OF TERMS AND CONDITIONS
|
|
172
|
+
|
|
173
|
+
Copyright 2026 Yeison Restrepo
|
|
174
|
+
|
|
175
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
176
|
+
you may not use this file except in compliance with the License.
|
|
177
|
+
You may obtain a copy of the License at
|
|
178
|
+
|
|
179
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
180
|
+
|
|
181
|
+
Unless required by applicable law or agreed to in writing, software
|
|
182
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
183
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
184
|
+
implied. See the License for the specific language governing
|
|
185
|
+
permissions and limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# code-conductor
|
|
2
|
+
|
|
3
|
+
A spec-first, token-efficient Claude Code configuration that turns AI-assisted coding into a disciplined, repeatable engineering workflow.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
AI coding assistants are only as good as the structure you put around them. Without it, sessions drift: the agent overwrites files it shouldn't, skips the spec, reads entire codebases line by line, and produces code that solves the wrong problem efficiently. The result is fast output with slow outcomes — more rewrites, more context lost, more tokens burned. code-conductor is the structure.
|
|
10
|
+
|
|
11
|
+
| Without code-conductor | With code-conductor |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Free-form prompt → agent guesses, overwrites, drifts | `/cc-spec` → approved spec → `/cc-plan` → confirmed steps → implement |
|
|
14
|
+
| Full files read on every turn | grep/find before read — targeted tool calls only |
|
|
15
|
+
| Conventions reset every session | Stack profile + memory loaded at session start |
|
|
16
|
+
| Frontend code with no UX consideration | UI/UX skill activated automatically for frontend stacks |
|
|
17
|
+
| Manual CLAUDE.md with `<command>` placeholders | **Stack auto-detection** — `code-conductor --project` reads your `package.json`, `go.mod`, `Cargo.toml`, etc. and auto-fills CLAUDE.md Development Commands so the agent never guesses your build/test/lint commands |
|
|
18
|
+
| Verbose markdown handoffs eat context | **SNAP v1**: minified single-line JSON handoff format, schema-validated by `scripts/snap-validate.mjs`, ≥15% smaller than the markdown snapshot it replaces |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx @yeison.restrepo.r/code-conductor # one-shot global setup
|
|
26
|
+
# or
|
|
27
|
+
npm install -g @yeison.restrepo.r/code-conductor && code-conductor
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Add to a project
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
code-conductor --project # also scaffold ./.claude in the current repo
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Flags
|
|
37
|
+
|
|
38
|
+
By default, the installer installs only the global core files. Use flags to extend this behavior.
|
|
39
|
+
|
|
40
|
+
| Flag | Description |
|
|
41
|
+
|------|-------------|
|
|
42
|
+
| `--project` / `-Project` | Also install the project template into the current directory |
|
|
43
|
+
| `--no-deps` / `-NoDeps` | Skip dependency installation (Node tooling, Playwright MCP, plugins); copy agent files only |
|
|
44
|
+
| `--verbosity MIN\|INFO\|VERBOSE` / `-Verbosity` | Set the default response verbosity (default: `MIN`). `MIN` = one sentence per response. `INFO` = bullet list. `VERBOSE` = full explanation. Re-run the installer to change it. |
|
|
45
|
+
|
|
46
|
+
### Update
|
|
47
|
+
|
|
48
|
+
Re-run the same install command. User-configured files are never overwritten; agent-managed files are always updated.
|
|
49
|
+
|
|
50
|
+
> **Note:** Do not clone this repository into a parent directory named `graphify-out` or `node_modules`. Guard 4 checks path components and will block agent `Read` calls on source files if the repository root is nested inside such a directory. Use relative paths if this layout is unavoidable.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## How It Works
|
|
55
|
+
|
|
56
|
+
code-conductor operates at three layers:
|
|
57
|
+
|
|
58
|
+
**Global core** (`~/.claude/`) — applies to every project on your machine. Enforces the spec-first workflow, token efficiency rules, safety checks, code simplicity rules, and memory conventions. Installed once; always active.
|
|
59
|
+
|
|
60
|
+
**Project template** (`.claude/`) — lives in your repo and is shared with your team via git. Adds project-specific slash commands, hooks that guard file writes, and a shared memory file for decisions, conventions, and technical debt.
|
|
61
|
+
|
|
62
|
+
**Dynamic stack discovery + skills** — `/cc-stack` runs the bundled `detect-stack.mjs` scanner and writes your detected build/test/lint/format commands plus a concise, generated ruleset straight into your project `CLAUDE.md`. Skills extend the agent's behavior for cross-cutting concerns like code simplicity and UI/UX.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Available Commands
|
|
67
|
+
|
|
68
|
+
All commands are tagged `(Conductor)` in the Claude Code command palette so they're easy to spot alongside commands from other sources.
|
|
69
|
+
|
|
70
|
+
### Global (all projects)
|
|
71
|
+
|
|
72
|
+
| Command | Description |
|
|
73
|
+
|---------|-------------|
|
|
74
|
+
| `/cc-checkpoint` | Read the current session, extract decisions, conventions, and debt, then write them to `project.md` and `personal.md` with a timestamp. Run before `/compact`, after completing a feature, and after key architectural decisions. |
|
|
75
|
+
| `/cc-stack` | Run the dynamic detector to identify your framework and write the detected commands and a generated ruleset into your project `CLAUDE.md`. |
|
|
76
|
+
| `/cc-lang [code]` | Switch response language for this session. Code identifiers, filenames, and commit messages remain English regardless. |
|
|
77
|
+
|
|
78
|
+
### Project (requires `--project` install)
|
|
79
|
+
|
|
80
|
+
| Command | Description |
|
|
81
|
+
|---------|-------------|
|
|
82
|
+
| `/cc-resume` | Restore full session context in one command: reads project identity, memory, latest spec and plan, git state, and loads the stack profile. Scans the active plan for `[>]` (interrupted) and `[!]` (failed) task markers and surfaces them in the session report. Run at the start of every session after initialization. |
|
|
83
|
+
| `/cc-init` | Initialize or re-sync the project environment: detect stack, checkpoint memory, refresh the project graph, and verify hook integrity. Run at the start of every session. |
|
|
84
|
+
| `/cc-spec [name]` | Search the codebase first, ask only for missing context, generate a full feature spec, and wait for your approval before any plan is made. |
|
|
85
|
+
| `/cc-plan` | Require an approved spec, map the codebase, and generate an ordered implementation plan with exact file paths, a test list, a commit order, and identified risks. Every generated task line carries a unique `[T-NNN]` ID (min 3 digits, unlimited suffix depth) using plain ASCII checkboxes — enforced at generation time. |
|
|
86
|
+
| `/cc-compact` | Phase-boundary command. Serializes the current phase's essential state (decisions, pending steps, files touched, constraints) into a single-line SNAP JSON snapshot at `.claude/memory/session-snapshot.json` — and, when Node `>= 22.5` is available, a git-hash-keyed row in the local `.conductor/cache.db` — then prompts you to run `/compact` to clear conversation history. Run at the end of every phase to prevent context overflow. |
|
|
87
|
+
| `/cc-implement` | Execute implementation tasks from an approved plan using a surgical 5-step ritual: Grep-locate pending tasks → single-line Read verify → pre-flip `[ ]` to `[>]` → execute → post-flip to `[X]` or `[!]`. Never reads or rewrites the full plan file. Includes dependency evaluation, drift detection, and a Step 6 hook that records each task's final state to a local SQLite cache (see below). |
|
|
88
|
+
|
|
89
|
+
Each of `/cc-spec`, `/cc-plan`, and `/cc-implement` opens its phase with a **resume read** (`scripts/resume-read.mjs`): it restores any context stored for the current git commit, so work survives branch switches and rollbacks (see [Local State Cache & Session Persistence](#local-state-cache--session-persistence--v1220)).
|
|
90
|
+
| `/cc-review [file\|dir]` | Review code in three layers - Critical / Important / Suggestion - then deliver a verdict and offer to auto-fix. |
|
|
91
|
+
| `/cc-debug [problem]` | Generate hypotheses ordered by probability, confirm before investigating, use Playwright MCP for visual bugs, and report the root cause with a targeted fix. |
|
|
92
|
+
| `/cc-refactor [file\|module]` | Diagnose complexity, plan ordered changes, apply one step at a time, and verify tests pass after each step. |
|
|
93
|
+
| `/cc-test [scope]` | Analyze coverage gaps, write tests in AAA pattern, add Playwright E2E where applicable, run after confirmation, and report results. |
|
|
94
|
+
| `/cc-docs [scope]` | Audit existing documentation, write inline docs in the correct format for your stack (JSDoc / docstrings / JavaDoc / GoDoc), and preview before writing. |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Skills
|
|
99
|
+
|
|
100
|
+
Skills extend agent behavior for cross-cutting concerns that apply regardless of stack.
|
|
101
|
+
|
|
102
|
+
### code-simplifier — always active
|
|
103
|
+
|
|
104
|
+
Applied to every piece of code written or reviewed in every session. Enforces:
|
|
105
|
+
|
|
106
|
+
- No speculative abstractions — solve today's problem only
|
|
107
|
+
- Functions ≤30 lines, doing one thing
|
|
108
|
+
- Flat over nested — guard clauses and early returns
|
|
109
|
+
- Descriptive names — no `Base`, `Abstract`, `Manager`, `Handler`
|
|
110
|
+
- Comments explain why, never what
|
|
111
|
+
|
|
112
|
+
### ui-ux-pro-max — frontend projects
|
|
113
|
+
|
|
114
|
+
Activated automatically when `/cc-stack` detects a frontend stack (React, Angular, Next.js, and similar). Installed from [nextlevelbuilder/ui-ux-pro-max-skill](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill) — the installer downloads it directly from GitHub. Enforces visual hierarchy, spacing grids, semantic color tokens, component states, WCAG AA accessibility, and framework-specific UI conventions.
|
|
115
|
+
|
|
116
|
+
### critical-review — always active during implementation
|
|
117
|
+
|
|
118
|
+
Applied to every implementation task via a 4-phase adversarial protocol:
|
|
119
|
+
|
|
120
|
+
1. **Pre-Flight** — Happy Path, Failure Points, and Boundary Conditions identified before any code is written
|
|
121
|
+
2. **Adversarial Review** — RESILIENCE (silent failures), EFFICIENCY (code smells), FRICTION (happy-path friction)
|
|
122
|
+
3. **Self-Correction** — each weakness refactored and re-verified in isolation
|
|
123
|
+
4. **`[VALIDATION]`** — required closing section on every implementation: edge cases covered, best-outcome justification, residual risks
|
|
124
|
+
|
|
125
|
+
### verbosity — always active
|
|
126
|
+
|
|
127
|
+
Controls how much Claude writes per turn. The level is set at install time via `--verbosity` and stored in `~/.claude/memory/verbosity.md`. Default: `MIN`.
|
|
128
|
+
|
|
129
|
+
| Level | Behavior |
|
|
130
|
+
|-------|----------|
|
|
131
|
+
| `MIN` | One declarative sentence. `[CHANGES]` tag with file list only. |
|
|
132
|
+
| `INFO` | Bullet list of what changed and why. Max 5 bullets. `[CHANGES]` + `[REASON]`. |
|
|
133
|
+
| `VERBOSE` | Full explanation, prose allowed. All response tags. |
|
|
134
|
+
|
|
135
|
+
### memory-first — always active
|
|
136
|
+
|
|
137
|
+
Before reading any file, Claude walks a priority lookup chain and stops at the first step that answers the question:
|
|
138
|
+
|
|
139
|
+
1. **Project memory**: `.claude/memory/project.md`
|
|
140
|
+
2. **Graphify graph** — structural/relational queries (`what calls X`, `what depends on Y`)
|
|
141
|
+
3. **Grep / Glob** — pattern searches
|
|
142
|
+
4. **Targeted read** — last resort, always with `offset` + `limit`, max 150 lines
|
|
143
|
+
|
|
144
|
+
### agent-delegation — always active
|
|
145
|
+
|
|
146
|
+
Keeps the main context clean. Sub-agents handle exploration and parallel work; they return a ≤200-word summary to the main context. Raw file contents and intermediate data never enter the main context.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Hooks
|
|
151
|
+
|
|
152
|
+
Hooks run automatically at specific points in a Claude Code session. They require no manual setup.
|
|
153
|
+
|
|
154
|
+
### graphify-ast-refresh *(global)*
|
|
155
|
+
|
|
156
|
+
Fires on every `UserPromptSubmit`. Checks whether `graphify-out/.graphify_ast_done` is fresh (default: 60 min, override with `GRAPHIFY_STALE_MINUTES`). If stale or missing, spawns a non-blocking background Python process that runs file detection and AST extraction — no LLM calls, no tokens. The main session inherits a ready graph without paying the generation cost.
|
|
157
|
+
|
|
158
|
+
Works on Windows, Linux, and macOS. Exits in under 5ms when the graph is current.
|
|
159
|
+
|
|
160
|
+
### pre-tool-use
|
|
161
|
+
|
|
162
|
+
Fires before every tool call. Three guards:
|
|
163
|
+
|
|
164
|
+
**Large-file Read guard** — if Claude tries to read a file with more than 150 lines without specifying an `offset` and `limit`, the call is blocked and Claude is redirected to the orchestrator lookup chain (memory → graph → grep → targeted read). Prevents reading entire codebases when a targeted search would do.
|
|
165
|
+
|
|
166
|
+
**Duplicate file guard** — if Claude tries to write or create a file that already exists, it prints a warning showing the file path, line count, and last-modified timestamp, then presents three options: overwrite, edit in place, or cancel. Prevents silently replacing files you've already configured.
|
|
167
|
+
|
|
168
|
+
**Bash scan guard (Guard 3)** — intercepts every Bash tool call and pattern-matches the command string against 12 mass content-dump patterns before execution: deep `find` without `maxdepth 1`, `find -exec` with readers/shells, `xargs` with readers, `cat`/pager/grep with unquoted globs, command substitution with readers, shell loops, `mapfile`/`readarray`, `eval`/`source`/dot operator, alias remapping to readers, and obfuscation sequences. Commands over 8192 characters and unclosed quotes are blocked fail-closed. Operators can whitelist specific directory prefixes or exact tokens via `BASH_SCAN_ALLOWLIST` in the hook file.
|
|
169
|
+
|
|
170
|
+
### context-guard *(global + project)* — v1.15.0
|
|
171
|
+
|
|
172
|
+
Fires on every `UserPromptSubmit`. Atomically increments a turn counter in `.claude/memory/turn-count.txt`. At 80% of the configured threshold it emits ⚠ CONTEXT WARNING; at or above the threshold it emits 🚨 CONTEXT CRITICAL. The threshold is read from `.claude/memory/context-threshold.txt` (default: 25). After `/compact`, the `post-compact` hook resets the counter to 0.
|
|
173
|
+
|
|
174
|
+
Available on both Unix (`context-guard.sh`) and Windows (`context-guard.ps1`). Set `CC_GUARD_DEBUG=1` to print debug info to stderr. Set `CC_PROJECT_ROOT` to override the project root used for the memory directory.
|
|
175
|
+
|
|
176
|
+
### post-compact
|
|
177
|
+
|
|
178
|
+
Fires after `/compact`. Resets the turn counter to 0, reads `project.md`, shows the timestamp of the last `/cc-checkpoint`, and reminds you to run `/cc-checkpoint` if context from this session hasn't been saved yet. Prevents losing decisions and conventions when the context window is compressed.
|
|
179
|
+
|
|
180
|
+
### verbosity-remind *(global + project)* — v1.11.0
|
|
181
|
+
|
|
182
|
+
Fires on every `UserPromptSubmit`. Re-injects the active MIN/INFO/VERBOSE verbosity constraint before every Claude response, preventing level drift as the context window fills (BUG-014).
|
|
183
|
+
|
|
184
|
+
The global hook defers to a project-level hook if one exists (upward traversal from `$PWD`). The active level is read from the nearest `.claude/memory/verbosity.md` ancestor file. Set `CC_VERBOSITY_SKIP=1` to disable in CI/CD environments.
|
|
185
|
+
|
|
186
|
+
> **Note — `$HOME` unset environments:** When `$HOME` is unset (e.g., some CI containers, `sudo -H` shells, minimal Docker images), `verbosity-remind.sh` exits immediately with code 0 and emits no output. Claude falls back to MIN verbosity by default. Set `HOME=/root` (or the appropriate home directory) in the container environment to restore full hook behavior. The hook never raises an error when `$HOME` is absent — it degrades gracefully to ensure the user's session is never blocked.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Local State Cache & Session Persistence — v1.22.0
|
|
191
|
+
|
|
192
|
+
`/cc-implement`'s Step 6 hook records each task's final state to a local SQLite cache at `.conductor/cache.db`, written by the bundled `scripts/conductor-db.mjs` engine — a zero-dependency ES module wrapping Node's built-in `node:sqlite`.
|
|
193
|
+
|
|
194
|
+
- **Schema (v2, ARCH-008):** `task_state(plan_file, task_id, state, updated_at)` keyed by `(plan_file, task_id)` — `plan_file` normalized to a repo-relative POSIX path so the same plan de-duplicates across working directories — plus `sessions`, `snapshots` (one verbatim SNAP blob per git commit, newest wins), and `raw_history`. Upserts on every write.
|
|
195
|
+
- **Runtime-gated:** `node:sqlite` needs Node `>= 22.5`, so every caller probes the Node version and self-disables below it. `engines.node` stays `>=20`; the cache is an optimization, never a requirement.
|
|
196
|
+
- **Non-authoritative + fail-safe:** the plan markdown and the `.claude/memory/session-snapshot.json` handoff remain the sources of truth. Every failure path — absent `node:sqlite`, a corrupt or non-regular file at the db path, `SQLITE_BUSY`, a newer schema, CLI misuse — degrades to a single `CONDUCTOR_DB:` stderr line and exit 0. A corrupt db is renamed aside (never `rm -r`) and recreated.
|
|
197
|
+
- **Gitignored:** `.conductor/` is local-only and never committed.
|
|
198
|
+
|
|
199
|
+
### Phase-entry resume — v1.22.0
|
|
200
|
+
|
|
201
|
+
`/cc-spec`, `/cc-plan`, and `/cc-implement` open each phase by running `scripts/resume-read.mjs`, which resolves the current git commit hash and restores any context stored for it — surviving branch switches and rollbacks. A valid DB snapshot for the commit wins; otherwise it falls back to the `.claude/memory/session-snapshot.json` handoff written by `/cc-compact`. A hit prints a `RESUME_HIT` block the command adopts as its starting context; a clean miss proceeds fresh; a readable-but-corrupt handoff halts the phase (exit `4`) with a `SNAP_INVALID` notice so you can inspect it. This completes the **ARCH-008** milestone: relational schema (v1.20.0) → checkpoint/compact writers (v1.21.0) → phase-entry readers (v1.22.0).
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Memory Architecture
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
~/.claude/
|
|
209
|
+
memory/
|
|
210
|
+
personal.md ← local only, never committed
|
|
211
|
+
dev preferences, shortcuts
|
|
212
|
+
verbosity.md ← agent-managed, set by installer
|
|
213
|
+
active verbosity level (MIN/INFO/VERBOSE)
|
|
214
|
+
|
|
215
|
+
project-root/
|
|
216
|
+
.claude/
|
|
217
|
+
memory/
|
|
218
|
+
project.md ← in git, shared with team
|
|
219
|
+
decisions, conventions, debt, workarounds
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`/cc-checkpoint` writes to both. Run it before `/compact`, after completing a feature, and after any key architectural decision.
|
|
223
|
+
|
|
224
|
+
`/cc-stack` records the detected stack in your project `CLAUDE.md` (the `- Stack:` line and the `## Active Stack Profiles` block); on later sessions it asks whether anything changed before re-detecting.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Language Support
|
|
229
|
+
|
|
230
|
+
| Priority | Source | How to set |
|
|
231
|
+
|----------|--------|------------|
|
|
232
|
+
| 1 (highest) | Session | `/lang [code]` |
|
|
233
|
+
| 2 | Project | `language:` in project `CLAUDE.md` |
|
|
234
|
+
| 3 | Personal | `response_language:` in `personal.md` |
|
|
235
|
+
| 4 (default) | Global | English |
|
|
236
|
+
|
|
237
|
+
**Supported codes:** `en` `es` `pt` `fr` `de` `it` `zh` `ja` `ko`
|
|
238
|
+
|
|
239
|
+
Code identifiers, file names, and commit messages are always English.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## File Structure
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
code-conductor/
|
|
247
|
+
├── README.md
|
|
248
|
+
├── VERSION
|
|
249
|
+
├── .gitignore
|
|
250
|
+
├── bin/code-conductor.mjs npm CLI entry (npx code-conductor)
|
|
251
|
+
├── lib/installer/ CLI modules (env, deploy, settings, config)
|
|
252
|
+
├── global/
|
|
253
|
+
│ ├── CLAUDE.md Global agent behavior (all projects)
|
|
254
|
+
│ ├── settings.json
|
|
255
|
+
│ ├── commands/
|
|
256
|
+
│ │ ├── cc-checkpoint.md /cc-checkpoint
|
|
257
|
+
│ │ ├── cc-stack.md /cc-stack
|
|
258
|
+
│ │ └── cc-lang.md /cc-lang
|
|
259
|
+
│ ├── hooks/
|
|
260
|
+
│ │ └── graphify-ast-refresh.py Background AST refresh on UserPromptSubmit
|
|
261
|
+
│ └── memory/
|
|
262
|
+
│ └── personal.md Template (never committed)
|
|
263
|
+
├── project-template/
|
|
264
|
+
│ ├── CLAUDE.md
|
|
265
|
+
│ └── .claude/
|
|
266
|
+
│ ├── settings.json Hooks wiring (pre-tool-use, post-compact)
|
|
267
|
+
│ ├── commands/
|
|
268
|
+
│ │ ├── cc-init.md /cc-init — session initialization
|
|
269
|
+
│ │ ├── cc-resume.md /cc-resume — session context restore
|
|
270
|
+
│ │ ├── cc-spec.md /cc-spec
|
|
271
|
+
│ │ ├── cc-plan.md /cc-plan
|
|
272
|
+
│ │ ├── cc-implement.md /cc-implement
|
|
273
|
+
│ │ ├── cc-review.md /cc-review
|
|
274
|
+
│ │ ├── cc-compact.md /cc-compact — phase boundary compaction
|
|
275
|
+
│ │ ├── cc-debug.md /cc-debug
|
|
276
|
+
│ │ ├── cc-refactor.md /cc-refactor
|
|
277
|
+
│ │ ├── cc-test.md /cc-test
|
|
278
|
+
│ │ └── cc-docs.md /cc-docs
|
|
279
|
+
│ ├── hooks/
|
|
280
|
+
│ │ ├── pre-tool-use.sh Large-file read guard + duplicate file guard + bash scan guard
|
|
281
|
+
│ │ ├── context-guard.sh Turn-counter warning (.sh + .ps1)
|
|
282
|
+
│ │ └── post-compact.sh Checkpoint reminder + cache sweep after `/compact` (.sh + .ps1)
|
|
283
|
+
│ └── memory/
|
|
284
|
+
│ └── project.md Shared team memory (in git)
|
|
285
|
+
├── scripts/
|
|
286
|
+
│ ├── conductor-db.mjs Zero-dep node:sqlite engine (.conductor/cache.db)
|
|
287
|
+
│ ├── resume-read.mjs Phase-entry resume reader (DB snapshot → handoff fallback)
|
|
288
|
+
│ ├── snap-build.mjs SNAP v1/v2 handoff serializer
|
|
289
|
+
│ ├── snap-validate.mjs SNAP schema validator
|
|
290
|
+
│ ├── session-id.mjs Stable session-id resolver
|
|
291
|
+
│ └── detect-stack.mjs Stack auto-detection scanner
|
|
292
|
+
└── skills/
|
|
293
|
+
├── code-simplifier.md Always active — complexity and simplicity rules
|
|
294
|
+
├── critical-review.md Always active — 4-phase adversarial review protocol
|
|
295
|
+
├── verbosity.md Always active — MIN/INFO/VERBOSE response rules
|
|
296
|
+
├── memory-first.md Always active — memory → graph → grep → read chain
|
|
297
|
+
└── agent-delegation.md Always active — sub-agent spawn rules
|
|
298
|
+
# ui-ux-pro-max installed from github.com/nextlevelbuilder/ui-ux-pro-max-skill
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## .gitignore Note
|
|
304
|
+
|
|
305
|
+
When installed with `--project`, the installer appends `.claude/memory/personal.md` to your project's `.gitignore`. This keeps personal preferences local and out of the shared repo.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Uninstall Notes
|
|
310
|
+
|
|
311
|
+
> **`git revert` in non-repository environments (CI/CD, Docker, bare installs):**
|
|
312
|
+
> Uninstall steps that use `git checkout <tag>` or `git revert <sha>` require a git working tree. In CI/CD pipelines, Docker containers, or directories that are not git repositories, these commands will fail with `fatal: not a git repository`. This is expected and non-fatal.
|
|
313
|
+
>
|
|
314
|
+
> **In non-repo environments:** manually delete or restore `skills/verbosity.md` and remove the `verbosity-remind` entry from `~/.claude/settings.json`. Hook removal (`rm ~/.claude/hooks/verbosity-remind.sh`) and `settings.json` cleanup work identically in all environments — no git is required.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { resolveAssetRoot, resolveHome, nodeMajorAtLeast } from '../lib/installer/env.mjs';
|
|
6
|
+
import { assertAssets, deployGlobal, deployProject, chmodHooks } from '../lib/installer/deploy.mjs';
|
|
7
|
+
import { verbosityHookCommand, mergeVerbosityHook } from '../lib/installer/settings.mjs';
|
|
8
|
+
import { writeVerbosity, seedMemoryFile, writeVersionFile } from '../lib/installer/config.mjs';
|
|
9
|
+
|
|
10
|
+
const USAGE = `Usage: code-conductor [--project] [--verbosity MIN|INFO|VERBOSE] [--version] [--help]`;
|
|
11
|
+
|
|
12
|
+
// Hand-rolled parser (four flags only). Deliberately NOT node:util's parseArgs —
|
|
13
|
+
// the CLI honors the zero-runtime-dependency rule and node:util adds no value for
|
|
14
|
+
// this tiny surface, so nothing is imported for argument handling.
|
|
15
|
+
// Conflict policy: flags are LAST-WINS. `--verbosity MIN --verbosity VERBOSE`
|
|
16
|
+
// yields VERBOSE (each match overwrites opts.verbosity); a repeated `--project`
|
|
17
|
+
// is idempotent. No "conflicting flags" error is raised — last-wins is the least
|
|
18
|
+
// surprising CLI convention and keeps the parser branchless.
|
|
19
|
+
function parseArgs(argv) {
|
|
20
|
+
const opts = { project: false, verbosity: undefined, verbosityGiven: false, version: false, help: false, unknown: [] };
|
|
21
|
+
for (let i = 0; i < argv.length; i++) {
|
|
22
|
+
const a = argv[i];
|
|
23
|
+
if (a === '--project') opts.project = true;
|
|
24
|
+
else if (a === '--verbosity' || a.startsWith('--verbosity=')) {
|
|
25
|
+
opts.verbosityGiven = true;
|
|
26
|
+
if (a.startsWith('--verbosity=')) {
|
|
27
|
+
// Inline form: --verbosity=INFO. Empty (`--verbosity=`) leaves value ''.
|
|
28
|
+
// Surrounding whitespace (e.g. a quoted `--verbosity= VERBOSE `) is NOT
|
|
29
|
+
// stripped here — normalizeVerbosity() trims before matching, so whitespace
|
|
30
|
+
// is tolerated and a whitespace-only/`=`-only value normalizes to null → MIN+warn.
|
|
31
|
+
opts.verbosity = a.slice('--verbosity='.length);
|
|
32
|
+
} else {
|
|
33
|
+
// Space-separated form: consume the next token only if it is a real value,
|
|
34
|
+
// not another flag or the end of argv (`--verbosity` passed last). A missing
|
|
35
|
+
// value stays undefined and falls back to MIN + warning in writeVerbosity.
|
|
36
|
+
const next = argv[i + 1];
|
|
37
|
+
if (next !== undefined && !next.startsWith('--')) { opts.verbosity = next; i++; }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (a === '--version' || a === '-v') opts.version = true;
|
|
41
|
+
else if (a === '--help' || a === '-h') opts.help = true;
|
|
42
|
+
// Unrecognized flags / stray positionals are collected, not fatal: the install
|
|
43
|
+
// still proceeds (exit 0) but run() emits one stderr warning so typos surface.
|
|
44
|
+
else opts.unknown.push(a);
|
|
45
|
+
}
|
|
46
|
+
return opts;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function pkgVersion(assetRoot) {
|
|
50
|
+
return JSON.parse(readFileSync(join(assetRoot, 'package.json'), 'utf8')).version;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// log(stream, msg) is injected so tests capture output without spawning a process.
|
|
54
|
+
export function run(argv, env = process.env, { cwd = process.cwd(), log } = {}) {
|
|
55
|
+
const emit = log || ((stream, msg) => process[stream].write(`${msg}\n`));
|
|
56
|
+
|
|
57
|
+
// Hard runtime floor: refuse to run on Node < 20 with a clear message rather than
|
|
58
|
+
// failing obscurely inside cpSync/ESM later. env.node lets tests inject a version.
|
|
59
|
+
if (!nodeMajorAtLeast(20, env.node)) {
|
|
60
|
+
emit('stderr', `code-conductor: Node >=20 required, found ${env.node || process.versions.node}`);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const assetRoot = resolveAssetRoot();
|
|
65
|
+
const opts = parseArgs(argv);
|
|
66
|
+
|
|
67
|
+
if (opts.unknown.length) emit('stderr', `code-conductor: ignoring unrecognized argument(s): ${opts.unknown.join(' ')}`);
|
|
68
|
+
|
|
69
|
+
// --help and --version are explicit informational OUTPUT (not diagnostics), so they
|
|
70
|
+
// go to STDOUT and exit 0 — this lets `code-conductor --version` be captured in a
|
|
71
|
+
// shell substitution. Only warnings/errors ever go to stderr.
|
|
72
|
+
if (opts.help) { emit('stdout', USAGE); return 0; }
|
|
73
|
+
if (opts.version) { emit('stdout', pkgVersion(assetRoot)); return 0; }
|
|
74
|
+
|
|
75
|
+
const home = resolveHome(env);
|
|
76
|
+
if (!home) { emit('stderr', 'code-conductor: cannot resolve home directory (HOME/USERPROFILE unset)'); return 1; }
|
|
77
|
+
|
|
78
|
+
// `writing` gates the two exit classes the constraints mandate:
|
|
79
|
+
// false → pre-flight/environment failure (missing asset, EROFS/EACCES before
|
|
80
|
+
// the first copy) → exit 1;
|
|
81
|
+
// true → any error once a copy has begun is a mid-copy PARTIAL_WRITE → exit 2,
|
|
82
|
+
// recoverable by an idempotent re-run.
|
|
83
|
+
// The flag is a SINGLE gate spanning BOTH deployment tracks: global runs first and
|
|
84
|
+
// flips it, so by the time --project's deployProject runs, writing is already true.
|
|
85
|
+
// A mid-copy failure in either track is therefore treated identically (exit 2),
|
|
86
|
+
// except the two tagged precondition errors (MISSING_ASSET, PROJECT_TARGET_NOT_DIR)
|
|
87
|
+
// and the environment codes (EROFS/EACCES/EPERM), which are exit 1 regardless.
|
|
88
|
+
let writing = false;
|
|
89
|
+
try {
|
|
90
|
+
assertAssets(assetRoot, ['global', 'skills', 'project-template']); // pre-flight
|
|
91
|
+
writing = true; // copy phase begins
|
|
92
|
+
const claudeDir = deployGlobal(assetRoot, home);
|
|
93
|
+
chmodHooks(claudeDir);
|
|
94
|
+
seedMemoryFile(home, 'personal.md', assetRoot);
|
|
95
|
+
const v = writeVerbosity(home, assetRoot, opts.verbosity, opts.verbosityGiven);
|
|
96
|
+
if (v.warn) emit('stderr', v.warn);
|
|
97
|
+
mergeVerbosityHook(join(claudeDir, 'settings.json'), verbosityHookCommand(home));
|
|
98
|
+
writeVersionFile(home, pkgVersion(assetRoot));
|
|
99
|
+
if (opts.project) deployProject(assetRoot, cwd);
|
|
100
|
+
return 0;
|
|
101
|
+
} catch (err) {
|
|
102
|
+
// Pre-flight failures (nothing written yet) → exit 1.
|
|
103
|
+
if (!writing) {
|
|
104
|
+
if (err.code === 'MISSING_ASSET') emit('stderr', `code-conductor: ${err.message}`);
|
|
105
|
+
else if (err.code === 'EROFS') emit('stderr', `code-conductor: cannot write to ${err.path} (read-only file system) — remount writable or adjust permissions`);
|
|
106
|
+
else emit('stderr', `code-conductor: cannot start install: ${err.message}`);
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
// Precondition conflict (--project target is a non-directory) → exit 1, not 2:
|
|
110
|
+
// nothing was partially written for the project, the path is simply unusable.
|
|
111
|
+
if (err.code === 'PROJECT_TARGET_NOT_DIR') { emit('stderr', `code-conductor: ${err.message}`); return 1; }
|
|
112
|
+
// Environment errors that surface on the very first write are still exit 1.
|
|
113
|
+
if (err.code === 'EROFS') { emit('stderr', `code-conductor: cannot write to ${err.path} (read-only file system) — remount writable or adjust permissions`); return 1; }
|
|
114
|
+
if (err.code === 'EACCES' || err.code === 'EPERM') { emit('stderr', `code-conductor: permission denied writing ${err.path} — fix with chmod/chown`); return 1; }
|
|
115
|
+
// Any other error mid-copy is a partial write → exit 2 (idempotent re-run repairs it).
|
|
116
|
+
emit('stderr', `code-conductor: PARTIAL_WRITE at ${err.path || 'unknown path'}: ${err.message} — re-run to complete the partial install`);
|
|
117
|
+
return 2;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Compare as file URLs so a Windows path (C:\...\bin\code-conductor.mjs) matches
|
|
122
|
+
// import.meta.url; naive `file://` + backslash string concat never would. Node's ESM
|
|
123
|
+
// loader sets import.meta.url to the module's REALPATH, so argv[1] must be realpath-
|
|
124
|
+
// resolved too — otherwise a symlinked launch path (npx cache, a global prefix, or
|
|
125
|
+
// macOS /tmp -> /private/var) never matches and the CLI exits 0 doing nothing.
|
|
126
|
+
function invokedDirectly() {
|
|
127
|
+
const argv1 = process.argv[1];
|
|
128
|
+
if (!argv1) return false;
|
|
129
|
+
let resolved;
|
|
130
|
+
try { resolved = realpathSync(argv1); } catch { resolved = argv1; }
|
|
131
|
+
return import.meta.url === pathToFileURL(resolved).href;
|
|
132
|
+
}
|
|
133
|
+
if (invokedDirectly()) process.exit(run(process.argv.slice(2)));
|