rhachet-roles-ehmpathy 1.15.14 → 1.15.16
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/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/rule.forbid.as-cast.md +65 -0
- package/dist/domain.roles/mechanic/briefs/practices/code.prod/pitofsuccess.typedefs/rule.require.shapefit.md +41 -0
- package/dist/domain.roles/mechanic/briefs/{criteria.practices/prefer.emojis.chill_nature.md → practices/lang.tones/rule.prefer.chill-nature-emojis.md} +0 -1
- package/dist/domain.roles/mechanic/inits/init.claude.permissions.jsonc +16 -5
- package/dist/domain.roles/mechanic/skills/claude.tools/mvsafe.sh +103 -0
- package/dist/domain.roles/mechanic/skills/claude.tools/rmsafe.sh +97 -0
- package/package.json +1 -1
- package/dist/domain.roles/mechanic/briefs/architecture/ubiqlang.md +0 -37
- package/dist/domain.roles/mechanic/briefs/patterns/lang.tones/prefer.chill-nature.md +0 -0
- package/dist/domain.roles/mechanic/briefs/patterns/lang.tones/prefer.lowercase.md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle → .archive}/_mech.compressed.md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle → .archive}/_mech.compressed.prompt.md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.declarative/.readme.md → .archive/code.prod.declarative.readme.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{architecture/directional-dependencies.md → .archive/patterns.directional-dependencies.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{style.compressed.md → .archive/style.compressed.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{style.compressed.prompt.md → .archive/style.compressed.prompt.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/require.dependency.pinned_versions.md → practices/code.prod/consistent.artifacts/rule.require.pinned-versions.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.typescript.utils/best-practice/ref.package.as-command.[tips].md → practices/code.prod/consistent.contracts/ref.package.as-command.[ref].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{architecture/bounded-contexts.md → practices/code.prod/evolvable.architecture/rule.require.bounded-contexts.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{architecture/domain-driven-design.md → practices/code.prod/evolvable.architecture/rule.require.domain-driven-design.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.objects/best-practice/ref.package.domain-objects.[readme].md → practices/code.prod/evolvable.domain.objects/ref.package.domain-objects.[ref].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.objects/bad-practices/blocker.has.attributes.nullable.md → practices/code.prod/evolvable.domain.objects/rule.forbid.nullable-without-reason.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.objects/bad-practices/blocker.has.attributes.undefined.md → practices/code.prod/evolvable.domain.objects/rule.forbid.undefined-attributes.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.objects/bad-practices/blocker.refs.immuatble.md → practices/code.prod/evolvable.domain.objects/rule.require.immutable-refs.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.operations/best-practice/require.sync.names.md → practices/code.prod/evolvable.domain.operations/rule.require.sync-filename-opname.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.contract.inputs.nameargs/bad-practice/forbid.positional-args.md → practices/code.prod/evolvable.procedures/rule.forbid.positional-args.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.domain.operations/bad-practices/forbid.ordered-args.md → practices/code.prod/evolvable.procedures/rule.forbid.positional-args.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.arrowonly.md → practices/code.prod/evolvable.procedures/rule.require.arrow-only.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.clear-contracts.md → practices/code.prod/evolvable.procedures/rule.require.clear-contracts.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{engineer/dependency-injection.md → practices/code.prod/evolvable.procedures/rule.require.dependency-injection.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{engineer/dependency-injection.stub.md → practices/code.prod/evolvable.procedures/rule.require.dependency-injection.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.args.input-context.md → practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.args.input-inline.md → practices/code.prod/evolvable.procedures/rule.require.input-context-pattern.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.contract.inputs.nameargs/best-practice/require.namedargs.md → practices/code.prod/evolvable.procedures/rule.require.named-args.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.single-responsibility.md → practices/code.prod/evolvable.procedures/rule.require.single-responsibility.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.repo.structure/bad-practices/forbid.barrel.exports.ts.md → practices/code.prod/evolvable.repo.structure/rule.forbid.barrel-exports.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.repo.structure/bad-practices/forbid.index.ts.md → practices/code.prod/evolvable.repo.structure/rule.forbid.index-ts.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.repo.structure/best-practice/dot-test-and-dot-temp.md → practices/code.prod/evolvable.repo.structure/rule.prefer.dot-dirs.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.repo.structure/best-practice/directional-dependencies.md → practices/code.prod/evolvable.repo.structure/rule.require.directional-deps.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.errors.failfast/bad-practices/forbid.failhide.md → practices/code.prod/pitofsuccess.errors/rule.forbid.error-hiding.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.errors.failfast/bad-practices/forbid.hide_errors.md → practices/code.prod/pitofsuccess.errors/rule.forbid.error-hiding.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.errors.failfast/best-practice/prefer.HelpfulError.wrap.md → practices/code.prod/pitofsuccess.errors/rule.prefer.helpful-error-wrap.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.errors.failfast/best-practice/require.fail_fast.[demo].shell.md → practices/code.prod/pitofsuccess.errors/rule.require.fail-fast.[demo].shell.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.errors.failfast/best-practice/require.fail_fast.md → practices/code.prod/pitofsuccess.errors/rule.require.fail-fast.[seed].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.failfast.md → practices/code.prod/pitofsuccess.errors/rule.require.fail-fast.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/require.idempotency.md → practices/code.prod/pitofsuccess.procedures/rule.require.idempotency.[seed].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.idempotency.md → practices/code.prod/pitofsuccess.procedures/rule.require.idempotent-procedures.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.immutability.md → practices/code.prod/pitofsuccess.procedures/rule.require.immutable-vars.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/pit-of-success.via.minimize-surface-area.md → practices/code.prod/pitofsuccess.procedures/rule.require.pitofsuccess.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{lessons/code.prod.typescript.types/bivariance_vs_contravariance.[lesson].md → practices/code.prod/pitofsuccess.typedefs/define.bivariance-for-generics.[lesson].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.what-why.v2.md → practices/code.prod/readable.comments/rule.require.what-why-headers.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.what-why.md → practices/code.prod/readable.comments/rule.require.what-why-headers.v1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.narrative/bad-practices/avoid.ifs.md → practices/code.prod/readable.narrative/rule.avoid.unnecessary-ifs.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.narrative/bad-practices/forbid.else.md → practices/code.prod/readable.narrative/rule.forbid.else-branches.[demo].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.narrative/bad-practices/forbid.else.v2.md → practices/code.prod/readable.narrative/rule.forbid.else-branches.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.narrative/best-practice/early-returns.named-checks.[demo].md → practices/code.prod/readable.narrative/rule.prefer.early-returns.[demo].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.transformers_over_conditionals.[lesson].md → practices/code.prod/readable.narrative/rule.prefer.transformers-over-conditionals.[lesson].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/flow.narratives.md → practices/code.prod/readable.narrative/rule.require.narrative-flow.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.prod.declarative/best-practice/declastruct.[demo].md → practices/code.prod/readable.persistence/rule.prefer.declastruct.[demo].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/ref.test-fns.[readme].md → practices/code.test/consistent.contracts/ref.package.test-fns.[ref].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/howto.write.bdd.[lesson].md → practices/code.test/frames.behavior/howto.write-bdd.[lesson].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{codestyle/mech.tests.given-when-then.md → practices/code.test/frames.behavior/rule.require.given-when-then.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/prefer.datadriven.md → practices/code.test/frames.caselist/rule.prefer.data-driven.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice → practices/code.test/lessons.howto}/howto.diagnose.[lesson].md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice → practices/code.test/lessons.howto}/howto.run.[lesson].md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice → practices/code.test/lessons.howto}/howto.use.[lesson].md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/howto.write.[lesson].md → practices/code.test/lessons.howto/howto.write.[lesson].md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/howto.write.[lesson].on_scope.for_integ.md → practices/code.test/lessons.howto/howto.write.[lesson].md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/howto.write.[lesson].on_scope.for_units.md → practices/code.test/lessons.howto/howto.write.[lesson].md.pt3.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.howto/best-practice/whento.snapshots.[lesson].md → practices/code.test/lessons.howto/rule.require.snapshots.[lesson].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/code.test.acceptance/best-practice/blackbox.md → practices/code.test/scope.acceptance/rule.require.blackbox.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns → practices}/lang.terms/.readme.md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/lang.terms/domain=practices.terms=forbid_prefer_desire_require.md → practices/lang.terms/define.directives.terms=forbid_avoid_prefer_require.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{terms/plan.exec_vs_apply.md → practices/lang.terms/define.exec-vs-apply.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/lang.terms/domain=software.terms=prodcode_vs_testcode.md → practices/lang.terms/define.prodcode-testcode.terms=prodcode_vs_testcode.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/never.term.script.md → practices/lang.terms/rule.forbid.term-script.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{terms/badpractice/script.md → practices/lang.terms/rule.forbid.term-script.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/lang.terms/bad-practices/forbid.term=existing.md → practices/lang.terms/rule.forbid.term=existing.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/lang.terms/best-practice/require.order.noun_adj.md → practices/lang.terms/rule.require.order.noun_adj.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{style.names.treestruct.md → practices/lang.terms/rule.require.treestruct.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{style.names.ubiqlang.md → practices/lang.terms/rule.require.ubiqlang.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns → practices}/lang.tones/.readme.md +0 -0
- /package/dist/domain.roles/mechanic/briefs/{style.words.lowercase.md → practices/lang.tones/rule.prefer.lowercase.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/flow.debug.diagnostics/bad-practices/forbid.trust_vscode.md → practices/work.flow/diagnose/rule.forbid.trust-vscode-diagnostics.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{patterns/flow.refact.questions/best-practice/require.testchange.review.md → practices/work.flow/refactor/rule.require.review-test-changes.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/prefer.jq.over_alt.[demo].md → practices/work.flow/tools/rule.prefer.jq.[demo].md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/prefer.terraform.[criteria].md → practices/work.flow/tools/rule.prefer.terraform.md.pt1.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/prefer.terraform.[seed].md → practices/work.flow/tools/rule.prefer.terraform.md.pt2.md} +0 -0
- /package/dist/domain.roles/mechanic/briefs/{criteria.practices/require.knowledge.externalized.md → practices/work.flow/tools/rule.require.externalized-knowledge.md} +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
.tactic = types:forbid-as-cast
|
|
2
|
+
|
|
3
|
+
.what = using `as X` casts is forbidden — it signals a rule.require.shapefit violation
|
|
4
|
+
|
|
5
|
+
.scope:
|
|
6
|
+
- applies to all typescript code in the codebase
|
|
7
|
+
- enforced during code review and lint rules
|
|
8
|
+
|
|
9
|
+
.why:
|
|
10
|
+
- `as` casts bypass typescript's type system
|
|
11
|
+
- they hide legitimate type errors that indicate design flaws
|
|
12
|
+
- they create runtime hazards when the cast is incorrect
|
|
13
|
+
- they make refactoring dangerous by silencing compiler warnings
|
|
14
|
+
|
|
15
|
+
.exception:
|
|
16
|
+
- allowed only at boundaries with external org code that lacks proper typedefs
|
|
17
|
+
- must document via inline comment why this hazard is necessary
|
|
18
|
+
- must include a note about what would need to change to remove the cast
|
|
19
|
+
|
|
20
|
+
.how:
|
|
21
|
+
- when tempted to use `as`, ask: "why doesn't this type fit naturally?"
|
|
22
|
+
- investigate and fix the root cause instead of casting
|
|
23
|
+
- if the source types are wrong, create proper type definitions
|
|
24
|
+
- if runtime validation is needed, use proper type guards
|
|
25
|
+
- if the compiler is wrong about a type, file a typescript issue or use a narrower cast
|
|
26
|
+
|
|
27
|
+
.enforcement:
|
|
28
|
+
- `as` casts in prod code without documented exception = BLOCKER
|
|
29
|
+
- exception comments must explain:
|
|
30
|
+
- why the external code lacks proper types
|
|
31
|
+
- what the correct type should be
|
|
32
|
+
- what would need to change to remove the cast
|
|
33
|
+
|
|
34
|
+
.examples:
|
|
35
|
+
|
|
36
|
+
.positive:
|
|
37
|
+
```ts
|
|
38
|
+
// refactoring to avoid cast
|
|
39
|
+
const result = processInput(input); // types align naturally
|
|
40
|
+
|
|
41
|
+
// using type guard instead of cast
|
|
42
|
+
if (isValidResponse(response)) {
|
|
43
|
+
// response is properly narrowed here
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// documented external boundary (allowed exception)
|
|
47
|
+
// NOTE: third-party-sdk lacks proper types for this response
|
|
48
|
+
// TODO: contribute types upstream or create local declaration file
|
|
49
|
+
const data = response.data as ThirdPartyResponse;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
.negative:
|
|
53
|
+
```ts
|
|
54
|
+
// ⛔ undocumented cast
|
|
55
|
+
const user = data as User;
|
|
56
|
+
|
|
57
|
+
// ⛔ cast to silence error
|
|
58
|
+
const result = badFunction() as ExpectedType;
|
|
59
|
+
|
|
60
|
+
// ⛔ any-cast escape hatch
|
|
61
|
+
const x = (y as any) as SomeType;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
.links:
|
|
65
|
+
- see also: `rule.require.shapefit`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.tactic = types:shapefit
|
|
2
|
+
|
|
3
|
+
.what = types must be well-defined and naturally fit; mismatches signal legitimate defects to resolve
|
|
4
|
+
|
|
5
|
+
.scope:
|
|
6
|
+
- applies to all type definitions, function signatures, and data transformations
|
|
7
|
+
- enforced at compile time via typescript's type system
|
|
8
|
+
|
|
9
|
+
.why:
|
|
10
|
+
- types that don't fit indicate a design flaw or incomplete understanding of the domain
|
|
11
|
+
- forcing types to fit via casts hides bugs and creates runtime hazards
|
|
12
|
+
- well-shaped types enable the compiler to catch errors before runtime
|
|
13
|
+
- creates a pit-of-success where correct code is easier to write than incorrect code
|
|
14
|
+
|
|
15
|
+
.how:
|
|
16
|
+
- if a type doesn't fit, investigate the root cause:
|
|
17
|
+
- is the source data incorrectly shaped?
|
|
18
|
+
- is the target type overly restrictive?
|
|
19
|
+
- is there a missing transformation step?
|
|
20
|
+
- resolve the mismatch by fixing the actual problem, not by casting
|
|
21
|
+
- use discriminated unions and type guards for legitimate polymorphism
|
|
22
|
+
- rely on typescript's inference rather than explicit annotations where possible
|
|
23
|
+
|
|
24
|
+
.enforcement:
|
|
25
|
+
- type errors are blockers, not warnings to suppress
|
|
26
|
+
- `as` casts are forbidden except at documented external boundaries (see rule.forbid.as-cast)
|
|
27
|
+
- `any` types are forbidden except for truly dynamic scenarios with proper runtime validation
|
|
28
|
+
|
|
29
|
+
.examples:
|
|
30
|
+
|
|
31
|
+
.positive:
|
|
32
|
+
- refactoring a function signature to accept the actual input type
|
|
33
|
+
- adding a missing property to a domain object
|
|
34
|
+
- using `satisfies` to check conformance without casting
|
|
35
|
+
- creating proper type guards for narrowing
|
|
36
|
+
|
|
37
|
+
.negative:
|
|
38
|
+
- `const x = y as SomeType` to silence compiler
|
|
39
|
+
- `// @ts-ignore` to skip type checking
|
|
40
|
+
- using `any` to bypass type constraints
|
|
41
|
+
- loosening types to accommodate bad data
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"deny": [
|
|
12
12
|
// git write operations - require explicit user request for audit trail
|
|
13
13
|
"Bash(git commit:*)",
|
|
14
|
-
"Bash(git add
|
|
14
|
+
"Bash(git add .)",
|
|
15
|
+
"Bash(git add -A:*)",
|
|
16
|
+
"Bash(git add --all:*)",
|
|
15
17
|
"Bash(git stash:*)",
|
|
16
18
|
"Bash(git checkout:*)",
|
|
17
19
|
"Bash(git branch -d:*)",
|
|
@@ -24,6 +26,10 @@
|
|
|
24
26
|
"Bash(git reflog delete:*)",
|
|
25
27
|
"Bash(git config:*)",
|
|
26
28
|
|
|
29
|
+
// git mv/rm - use mvsafe.sh and rmsafe.sh instead (repo-constrained)
|
|
30
|
+
"Bash(git mv:*)",
|
|
31
|
+
"Bash(git rm:*)",
|
|
32
|
+
|
|
27
33
|
// "anywrite" commands - CRITICAL SECURITY RISK
|
|
28
34
|
//
|
|
29
35
|
// unlike Claude's native Edit/Write tools which are scoped to the repo,
|
|
@@ -141,10 +147,6 @@
|
|
|
141
147
|
"Bash(mkdir:*)",
|
|
142
148
|
"Bash(pwd)",
|
|
143
149
|
|
|
144
|
-
// git mv/rm are safe - constrained to repo, all changes revertable
|
|
145
|
-
"Bash(git mv:*)",
|
|
146
|
-
"Bash(git rm:*)",
|
|
147
|
-
|
|
148
150
|
// git read-only - all have no write variants
|
|
149
151
|
"Bash(git log:*)",
|
|
150
152
|
"Bash(git status:*)",
|
|
@@ -162,6 +164,12 @@
|
|
|
162
164
|
// cpsafe - safe file copy within git repo (source must be git-tracked)
|
|
163
165
|
"Bash(.agent/repo=ehmpathy/role=mechanic/skills/.skills/claude.tools/cpsafe.sh:*)",
|
|
164
166
|
|
|
167
|
+
// mvsafe - safe file move within git repo
|
|
168
|
+
"Bash(.agent/repo=ehmpathy/role=mechanic/skills/.skills/claude.tools/mvsafe.sh:*)",
|
|
169
|
+
|
|
170
|
+
// rmsafe - safe file removal within git repo
|
|
171
|
+
"Bash(.agent/repo=ehmpathy/role=mechanic/skills/.skills/claude.tools/rmsafe.sh:*)",
|
|
172
|
+
|
|
165
173
|
// npm read operations
|
|
166
174
|
"Bash(npm view:*)",
|
|
167
175
|
"Bash(npm list:*)",
|
|
@@ -209,6 +217,9 @@
|
|
|
209
217
|
"Bash(RESNAP=true THOROUGH=true npm run test:integration:*)",
|
|
210
218
|
"Bash(RESNAP=true THOROUGH=true npm run test:acceptance:*)",
|
|
211
219
|
|
|
220
|
+
// test list operation
|
|
221
|
+
"Bash(npx jest --listTests:*)",
|
|
222
|
+
|
|
212
223
|
// fix operations
|
|
213
224
|
"Bash(npm run fix:*)",
|
|
214
225
|
"Bash(npm run fix:format:*)",
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
######################################################################
|
|
3
|
+
# .what = safe file move within git repo
|
|
4
|
+
#
|
|
5
|
+
# .why = enables file moving without:
|
|
6
|
+
# - touching files outside the repo
|
|
7
|
+
# - accidental path traversal attacks
|
|
8
|
+
#
|
|
9
|
+
# this is a controlled alternative to raw mv, which is
|
|
10
|
+
# denied in permissions due to security risks.
|
|
11
|
+
#
|
|
12
|
+
# usage:
|
|
13
|
+
# mvsafe.sh --src "path/to/source" --dest "path/to/dest"
|
|
14
|
+
#
|
|
15
|
+
# guarantee:
|
|
16
|
+
# - source must be within repo
|
|
17
|
+
# - dest must be within repo
|
|
18
|
+
# - creates parent directories if needed
|
|
19
|
+
# - fail-fast on errors
|
|
20
|
+
######################################################################
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
# parse named arguments
|
|
24
|
+
SRC=""
|
|
25
|
+
DEST=""
|
|
26
|
+
|
|
27
|
+
while [[ $# -gt 0 ]]; do
|
|
28
|
+
case $1 in
|
|
29
|
+
--src)
|
|
30
|
+
SRC="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--dest)
|
|
34
|
+
DEST="$2"
|
|
35
|
+
shift 2
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
echo "unknown argument: $1"
|
|
39
|
+
echo "usage: mvsafe.sh --src 'source' --dest 'destination'"
|
|
40
|
+
exit 1
|
|
41
|
+
;;
|
|
42
|
+
esac
|
|
43
|
+
done
|
|
44
|
+
|
|
45
|
+
# validate required args
|
|
46
|
+
if [[ -z "$SRC" ]]; then
|
|
47
|
+
echo "error: --src is required"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [[ -z "$DEST" ]]; then
|
|
52
|
+
echo "error: --dest is required"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# ensure we're in a git repo
|
|
57
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
58
|
+
echo "error: not in a git repository"
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# get repo root
|
|
63
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
64
|
+
|
|
65
|
+
# resolve absolute paths
|
|
66
|
+
SRC_ABS=$(realpath -m "$SRC")
|
|
67
|
+
DEST_ABS=$(realpath -m "$DEST")
|
|
68
|
+
|
|
69
|
+
# validate source is within repo
|
|
70
|
+
if [[ "$SRC_ABS" != "$REPO_ROOT"* ]]; then
|
|
71
|
+
echo "error: source must be within the git repository"
|
|
72
|
+
echo " repo root: $REPO_ROOT"
|
|
73
|
+
echo " source: $SRC_ABS"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# validate dest is within repo
|
|
78
|
+
if [[ "$DEST_ABS" != "$REPO_ROOT"* ]]; then
|
|
79
|
+
echo "error: destination must be within the git repository"
|
|
80
|
+
echo " repo root: $REPO_ROOT"
|
|
81
|
+
echo " dest: $DEST_ABS"
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# validate source exists
|
|
86
|
+
if [[ ! -e "$SRC_ABS" ]]; then
|
|
87
|
+
echo "error: source does not exist: $SRC"
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# create parent directories if needed
|
|
92
|
+
DEST_DIR=$(dirname "$DEST_ABS")
|
|
93
|
+
if [[ ! -d "$DEST_DIR" ]]; then
|
|
94
|
+
echo "creating directory: $DEST_DIR"
|
|
95
|
+
mkdir -p "$DEST_DIR"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# perform the move
|
|
99
|
+
mv "$SRC_ABS" "$DEST_ABS"
|
|
100
|
+
|
|
101
|
+
SRC_REL="${SRC_ABS#$REPO_ROOT/}"
|
|
102
|
+
DEST_REL="${DEST_ABS#$REPO_ROOT/}"
|
|
103
|
+
echo "moved: $SRC_REL -> $DEST_REL"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
######################################################################
|
|
3
|
+
# .what = safe file removal within git repo
|
|
4
|
+
#
|
|
5
|
+
# .why = enables file deletion without:
|
|
6
|
+
# - touching files outside the repo
|
|
7
|
+
# - accidental path traversal attacks
|
|
8
|
+
#
|
|
9
|
+
# this is a controlled alternative to raw rm, which is
|
|
10
|
+
# denied in permissions due to security risks.
|
|
11
|
+
#
|
|
12
|
+
# usage:
|
|
13
|
+
# rmsafe.sh --path "path/to/file"
|
|
14
|
+
# rmsafe.sh --path "path/to/dir" --recursive
|
|
15
|
+
#
|
|
16
|
+
# guarantee:
|
|
17
|
+
# - path must be within repo
|
|
18
|
+
# - requires --recursive for directories
|
|
19
|
+
# - fail-fast on errors
|
|
20
|
+
######################################################################
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
# parse named arguments
|
|
24
|
+
TARGET=""
|
|
25
|
+
RECURSIVE=false
|
|
26
|
+
|
|
27
|
+
while [[ $# -gt 0 ]]; do
|
|
28
|
+
case $1 in
|
|
29
|
+
--path)
|
|
30
|
+
TARGET="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--recursive|-r)
|
|
34
|
+
RECURSIVE=true
|
|
35
|
+
shift
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
echo "unknown argument: $1"
|
|
39
|
+
echo "usage: rmsafe.sh --path 'target' [--recursive]"
|
|
40
|
+
exit 1
|
|
41
|
+
;;
|
|
42
|
+
esac
|
|
43
|
+
done
|
|
44
|
+
|
|
45
|
+
# validate required args
|
|
46
|
+
if [[ -z "$TARGET" ]]; then
|
|
47
|
+
echo "error: --path is required"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# ensure we're in a git repo
|
|
52
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
53
|
+
echo "error: not in a git repository"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# get repo root
|
|
58
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
59
|
+
|
|
60
|
+
# resolve absolute path
|
|
61
|
+
TARGET_ABS=$(realpath -m "$TARGET")
|
|
62
|
+
|
|
63
|
+
# validate target is within repo
|
|
64
|
+
if [[ "$TARGET_ABS" != "$REPO_ROOT"* ]]; then
|
|
65
|
+
echo "error: path must be within the git repository"
|
|
66
|
+
echo " repo root: $REPO_ROOT"
|
|
67
|
+
echo " path: $TARGET_ABS"
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# prevent deleting repo root itself
|
|
72
|
+
if [[ "$TARGET_ABS" == "$REPO_ROOT" ]]; then
|
|
73
|
+
echo "error: cannot delete the repository root"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# validate target exists
|
|
78
|
+
if [[ ! -e "$TARGET_ABS" ]]; then
|
|
79
|
+
echo "error: path does not exist: $TARGET"
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# check if directory and require --recursive
|
|
84
|
+
if [[ -d "$TARGET_ABS" ]] && [[ "$RECURSIVE" != true ]]; then
|
|
85
|
+
echo "error: target is a directory, use --recursive to delete"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# perform the removal
|
|
90
|
+
if [[ "$RECURSIVE" == true ]]; then
|
|
91
|
+
rm -rf "$TARGET_ABS"
|
|
92
|
+
else
|
|
93
|
+
rm "$TARGET_ABS"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
TARGET_REL="${TARGET_ABS#$REPO_ROOT/}"
|
|
97
|
+
echo "removed: $TARGET_REL"
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "rhachet-roles-ehmpathy",
|
|
3
3
|
"author": "ehmpathy",
|
|
4
4
|
"description": "empathetic software construction roles and skills, via rhachet",
|
|
5
|
-
"version": "1.15.
|
|
5
|
+
"version": "1.15.16",
|
|
6
6
|
"repository": "ehmpathy/rhachet-roles-ehmpathy",
|
|
7
7
|
"homepage": "https://github.com/ehmpathy/rhachet-roles-ehmpathy",
|
|
8
8
|
"keywords": [
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
.tactic = name:ubiqlang
|
|
2
|
-
|
|
3
|
-
.what = enforce a rigorous, domain-driven naming system rooted in ubiquitous language
|
|
4
|
-
.where:
|
|
5
|
-
- ubiquitous language = the shared, unambiguous vocabulary used by both domain experts and developers
|
|
6
|
-
- this tactic applies to all names: types, variables, functions, slugs, and folders
|
|
7
|
-
|
|
8
|
-
.why:
|
|
9
|
-
- eliminates ambiguity and cognitive friction
|
|
10
|
-
- ensures that everyone speaks the same language — in code, UI, tests, and docs
|
|
11
|
-
- prevents synonym drift (e.g., "client" vs "customer") and overload traps (e.g., "update" meaning 3 things)
|
|
12
|
-
|
|
13
|
-
.how:
|
|
14
|
-
- eliminate synonyms
|
|
15
|
-
- choose one canonical word per concept (e.g., always use `customer`, never `client`, `user`, or `account`)
|
|
16
|
-
- eliminate overloads
|
|
17
|
-
- each term must refer to one concept only (e.g., avoid using `update` for both "save data" and "fetch latest")
|
|
18
|
-
- use consistent noun-verb stacking that mirrors domain intent (e.g., `customerPhoneUpdate`, not `editPhoneNumber`)
|
|
19
|
-
- whenever a new term is introduced:
|
|
20
|
-
- define its interface, expected shape, and role
|
|
21
|
-
- document its meaning clearly and visibly (ideally in context or hover docs)
|
|
22
|
-
- ensure its usage is verified across type definitions, business rules, and communication flows
|
|
23
|
-
|
|
24
|
-
.examples:
|
|
25
|
-
.positive:
|
|
26
|
-
- `customer` instead of `client`, `user`, or `buyer`
|
|
27
|
-
- `jobQuote` as the single term for estimates/proposals
|
|
28
|
-
- `leadCapture` as the canonical action for inbound lead collection
|
|
29
|
-
- `customerPhoneUpdate` for updating a phone number
|
|
30
|
-
- `invoiceDraft` and `invoiceFinal` for two distinct invoice states
|
|
31
|
-
|
|
32
|
-
.negative:
|
|
33
|
-
- `client`, `user`, `account`, `buyer` all referring to the same actor
|
|
34
|
-
- `editCustomerPhone`, `changePhone`, `updateNumber` used interchangeably
|
|
35
|
-
- `job` used for both a requested service and a completed one
|
|
36
|
-
- `update()` overloaded to mean save, patch, sync, or refresh
|
|
37
|
-
- `quote`, `estimate`, `proposal`, and `bid` all floating without clear hierarchy
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/domain.roles/mechanic/briefs/{codestyle → .archive}/_mech.compressed.prompt.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/domain.roles/mechanic/briefs/{style.compressed.md → .archive/style.compressed.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|