Skip to content

Commit fa2fbf1

Browse files
dfa1claude
andcommitted
docs: merge AGENTS.md into CLAUDE.md
Single source of truth for agent/AI guidance. CLAUDE.md absorbs all unique content from AGENTS.md (debug, logging, sonar, package map, CommandArguments tables, arch notes) while retaining CLAUDE.md-specific content (domain primitives, DI interfaces, jqwik section). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 477a25e commit fa2fbf1

2 files changed

Lines changed: 137 additions & 190 deletions

File tree

AGENTS.md

Lines changed: 0 additions & 183 deletions
This file was deleted.

CLAUDE.md

Lines changed: 137 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,149 @@
1-
# hosh project guidance
1+
# hosh — Claude guidance
2+
3+
Human Oriented SHell: experimental Java shell, typed records, virtual-thread pipelines. Multi-module Maven project (JDK 25).
4+
5+
Website: <https://hosh-shell.github.io>
6+
7+
## Build
8+
9+
```bash
10+
./mvnw clean verify # full build (unit + integration + fitness + acceptance)
11+
./mvnw -Pskip-slow-tests clean verify # ~2× faster, skip slow tests
12+
./mvnw test-compile org.pitest:pitest-maven:mutationCoverage # mutation testing
13+
./mvnw clean verify sonar:sonar -Psonar -Dsonar.token=MYTOKEN # sonar analysis
14+
```
15+
16+
Run: `java -jar main/target/hosh.jar`
17+
18+
Debug:
19+
20+
```bash
21+
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 -jar main/target/hosh.jar
22+
```
23+
24+
## Logging
25+
26+
Hosh uses `java.util.logging`, disabled by default.
27+
28+
```bash
29+
HOSH_LOG_LEVEL=FINE java -jar main/target/hosh.jar
30+
```
31+
32+
Log events written to `$HOME/.hosh.log`.
33+
34+
## Module map
35+
36+
| Module | Purpose |
37+
|---|---|
38+
| `spi/` | Core abstractions: `Command`, `Channel`, `Record`, `ExitStatus`, `Value` subtypes |
39+
| `spi-test-support/` | Test helpers for SPI |
40+
| `test-support/` | JUnit 5 utilities |
41+
| `runtime/` | Shell engine: `Interpreter`, `Supervisor`, ANTLR4 `Compiler`/`Parser` |
42+
| `modules/system/` | echo, sleep, withTimeout, benchmark, … |
43+
| `modules/filesystem/` | ls, cd, walk, cp, mv, rm, find, … |
44+
| `modules/text/` | grep, sort, count, split, join, trim, regex, … |
45+
| `modules/network/` | http, resolve, … |
46+
| `modules/terminal/` | clear, … |
47+
| `modules/history/` | history |
48+
| `main/` | Entry point `Hosh.java`, produces uberjar |
49+
50+
Root package: `hosh`. Key sub-packages: `hosh.spi`, `hosh.runtime`, `hosh.runtime.prompt`, `hosh.runtime.completion`, `hosh.modules.*`.
51+
52+
## Key classes
53+
54+
| Concern | Class | Location |
55+
|---|---|---|
56+
| Entry point | `Hosh` | `main/` |
57+
| Parsing | `Compiler`, `Parser` | `runtime/` |
58+
| ANTLR4 grammar | `Hosh.g4` | `runtime/src/main/antlr4/` |
59+
| Pipeline execution | `Supervisor` | `runtime/` |
60+
| Inter-stage data | `PipelineChannel` | `runtime/` |
61+
| Core record type | `Record`, `Records` | `spi/` |
62+
| Typed values | `Value`, `Keys` | `spi/` |
63+
| Command interface | `Command` | `spi/` |
64+
| Command arguments | `CommandArguments`, `CommandArgument` | `spi/` |
65+
| Channels | `InputChannel`, `OutputChannel` | `spi/` |
66+
| Module registration | `Module` | `spi/` |
67+
68+
## Architecture constraints
69+
70+
- Commands communicate via typed `Record`s — never raw strings across subsystem boundaries.
71+
- Pipeline stages run concurrently on virtual threads (`Executors.newVirtualThreadPerTaskExecutor()`).
72+
- Inter-stage data flows through `PipelineChannel` backed by `LinkedTransferQueue`.
73+
- Strict error handling by default — equivalent to `set -euo pipefail` in bash.
74+
- Modules depend only on `spi/` — never on `runtime/` internals (enforced by `module-info.java`).
75+
- Uses Java Platform Module System (`module-info.java` in every module).
76+
- To add a command: create class implementing `Command`, register in the module's `Module` impl.
77+
- Dependency injection happens in `Interpreter` via awareness interfaces (`StateAware`, `StateMutatorAware`, `LineReaderAware`, `TerminalAware`, `HistoryAware`, `VersionAware`).
78+
79+
## CommandArguments
80+
81+
Always use `CommandArguments` — never raw `List<String>`.
82+
83+
```java
84+
@Override
85+
public ExitStatus run(CommandArguments args, InputChannel in, OutputChannel out, OutputChannel err, State state) {
86+
if (args.size() != 1) {
87+
err.send(Records.singleton(Keys.ERROR, Values.ofText("usage: mycommand <arg>")));
88+
return ExitStatus.error();
89+
}
90+
String value = args.get(0).asString();
91+
// ...
92+
}
93+
```
94+
95+
### CommandArguments methods
96+
97+
| Method | Description |
98+
|---|---|
99+
| `CommandArguments.of(String... values)` | Factory for tests and internal use |
100+
| `isEmpty()` | True if no arguments |
101+
| `size()` | Number of arguments |
102+
| `get(int index)` | Argument at index; programming error if out of bounds |
103+
| `stream()` | Stream over arguments |
104+
105+
### CommandArgument accessors
106+
107+
| Method | Return type | Description |
108+
|---|---|---|
109+
| `asString()` | `String` | Raw string value |
110+
| `asKey()` | `Key` | Converts via `Keys.of(value)` |
111+
| `asLong()` | `OptionalLong` | Parses as `long`; empty if invalid |
112+
| `asInt()` | `OptionalInt` | Parses as `int`; empty if invalid |
113+
| `asDuration()` | `Optional<Duration>` | Parses ISO-8601 duration; empty if invalid |
114+
| `asPath(State state)` | `Path` | Resolves relative to `state.getCwd()`; absolute, normalized |
115+
116+
## Code style
117+
118+
- Tabs, not spaces (Java and XML). Checkstyle will fail otherwise.
119+
- Checkstyle enforced for all files under `src/main` and `src/test` (`checkstyle.xml` at root).
120+
- Java 25. No Kotlin, no Gradle.
121+
- Zero SonarQube bugs/smells policy.
122+
- No `sun.misc.Unsafe` or internal JDK APIs.
123+
- Prefer explicit over clever. Fail fast on unhandled cases.
124+
- Domain primitives: use `Key`, `Value`, `ExitStatus`, `VariableName`, `CommandName` — never pass raw `String`/primitives across subsystem boundaries.
2125

3126
## Testing
4127

5-
### Property-Based Testing (PBT)
128+
- All features covered by unit tests. Always check the happy path at minimum.
129+
- JUnit 5 + Mockito (BDDMockito) + AssertJ.
130+
- Every test has `// Given` / `// When` / `// Then` sections.
131+
- Class under test is always named `sut`.
132+
- Use `BDDMockito` exclusively: `given(mock.method()).willReturn(value)`. Never the reverse form. Only static-import `given` and `then` — not `willReturn`/`willThrow`.
133+
- Prefer `@ParameterizedTest` over copy-pasting tests. Use `@ValueSource` when possible; `@ArgumentsSource` when more structure needed (test case must have a name).
134+
- Acceptance tests run the built jar end-to-end with hosh scripts.
135+
- Mutation testing via PIT (`pitest-maven`).
6136

7-
This project uses [jqwik](https://jqwik.net/) for property-based tests.
137+
## Property-Based Testing (jqwik)
8138

9-
**Known issue:** jqwik 1.9.3 targets JUnit Platform 1.x but the project uses JUnit 6 (Platform 6.x). `@Property` tests compile and are structurally correct but the jqwik engine does not execute them at runtime. Track https://github.com/jqwik-team/jqwik/issues for jqwik 2.x release targeting JUnit 6.
139+
**Known issue:** jqwik 1.9.3 targets JUnit Platform 1.x; project uses JUnit 6 (Platform 6.x). `@Property` tests compile and are structurally correct but the jqwik engine does not execute them at runtime. Track https://github.com/jqwik-team/jqwik/issues for jqwik 2.x.
10140

11-
**Writing property tests:** use `@Property` + `@ForAll` for parameters, `@Provide` for custom arbitraries, `Assume.that(...)` for preconditions. Follow the existing patterns in `ValuesTest.java` (spi module).
141+
Write property tests: `@Property` + `@ForAll` for parameters, `@Provide` for custom arbitraries, `Assume.that(...)` for preconditions. See `ValuesTest.java` (spi module) for patterns.
12142

13-
**Key properties to test:**
143+
Key properties:
14144
- Comparator contract: reflexivity, antisymmetry, transitivity
15145
- Merge commutativity: `a.merge(b) == b.merge(a)`
16146
- Sort idempotence: `sort(sort(xs)) == sort(xs)`
17147
- Partition: `take(n, xs) + drop(n, xs) == xs`
18148

19-
**Architecture rule:** `UnitTestsFitnessTest` allows `@Property` and `@Provide` annotations alongside the standard JUnit annotations (`@Test`, `@BeforeEach`, `@AfterEach`, `@ParameterizedTest`).
149+
`UnitTestsFitnessTest` allows `@Property` and `@Provide` alongside standard JUnit annotations.

0 commit comments

Comments
 (0)