@next-friday/create-app 2.1.3 → 2.1.5
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/package.json +6 -2
- package/templates/base/.agents/hooks/agent-shell-gate.sh +13 -2
- package/templates/base/.agents/rules/codebase-hygiene.md +13 -0
- package/templates/base/.agents/rules/descriptive-naming.md +12 -0
- package/templates/base/.agents/rules/single-author-style.md +1 -1
- package/templates/base/.claude/rules/codebase-hygiene.md +1 -0
- package/templates/base/.claude/rules/descriptive-naming.md +1 -0
- package/templates/base/.claude/settings.json +3 -0
- package/templates/base/.cursor/BUGBOT.md +2 -0
- package/templates/base/.cursor/hooks/agent-constitution-gate.sh +1 -1
- package/templates/base/.cursor/rules/codebase-hygiene.mdc +18 -0
- package/templates/base/.cursor/rules/descriptive-naming.mdc +17 -0
- package/templates/base/.cursor/rules/single-author-style.mdc +1 -1
- package/templates/base/scripts/check-agent-gates.ts +8 -0
- package/templates/nestjs/.agents/rules.json +6 -0
- package/templates/nextjs/.agents/rules.json +6 -0
- package/templates/nodejs/.agents/rules.json +6 -0
- package/templates/payload/.agents/rules.json +6 -0
- package/templates/turborepo/.agents/rules.json +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next-friday/create-app",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "Create a Next Friday project from a template.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"create",
|
|
@@ -73,15 +73,19 @@
|
|
|
73
73
|
"dev": "tsdown --watch",
|
|
74
74
|
"format": "prettier --write --cache .",
|
|
75
75
|
"format:check": "prettier --check --cache . && editorconfig-checker",
|
|
76
|
+
"gates:check": "node scripts/check-agent-gates.ts",
|
|
76
77
|
"knip": "knip",
|
|
77
78
|
"lint": "eslint . --fix --cache --max-warnings=0 --no-inline-config",
|
|
78
79
|
"lint:check": "eslint . --cache --max-warnings=0 --no-inline-config",
|
|
80
|
+
"rules:check": "node scripts/sync-agent-rules.ts --check",
|
|
81
|
+
"rules:sync": "node scripts/sync-agent-rules.ts",
|
|
79
82
|
"sort-package-json": "sort-package-json package.json",
|
|
80
83
|
"sort-package-json:check": "sort-package-json --check package.json",
|
|
84
|
+
"suppressions:check": "bash .agents/hooks/agent-suppression-gate.sh --repo",
|
|
81
85
|
"test": "vitest run",
|
|
82
86
|
"test:coverage": "vitest run --coverage",
|
|
83
87
|
"test:watch": "vitest",
|
|
84
88
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
85
|
-
"verify": "pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm typecheck && pnpm test:coverage && pnpm knip && pnpm build && pnpm check:publint"
|
|
89
|
+
"verify": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm typecheck && pnpm test:coverage && pnpm knip && pnpm build && pnpm check:publint"
|
|
86
90
|
}
|
|
87
91
|
}
|
|
@@ -20,7 +20,7 @@ command=$(jq -r '.command // .tool_input.command // empty' <<< "$input")
|
|
|
20
20
|
|
|
21
21
|
separator=$'\x1f'
|
|
22
22
|
redirect=$'\x1e'
|
|
23
|
-
protected_names='(\.husky|\.agents|\.cursor|\.claude/rules|\.claude/settings(\.local)?\.json|\.git/hooks|\.git/config
|
|
23
|
+
protected_names='(\.husky|\.agents|\.cursor|\.claude/rules|\.claude/settings(\.local)?\.json|\.git/hooks|\.git/config(\.worktree)?|\.lintstagedrc\.json|\.gitleaks\.toml|\.commitlintrc\.json|\.prettierrc\.json|prettier\.config\.ts|eslint\.config\.ts|scripts/(sync-agent-rules|check-agent-gates)\.ts)'
|
|
24
24
|
protected="(^|[/=])$protected_names(/|$)"
|
|
25
25
|
policy="Hooks and agent policy files are company policy; stop and ask the user."
|
|
26
26
|
in_protected=0
|
|
@@ -117,6 +117,15 @@ lex() {
|
|
|
117
117
|
flush
|
|
118
118
|
words+=("$separator")
|
|
119
119
|
;;
|
|
120
|
+
'{' | '}')
|
|
121
|
+
if ((has_word)); then
|
|
122
|
+
word+=$char
|
|
123
|
+
has_word=1
|
|
124
|
+
else
|
|
125
|
+
flush
|
|
126
|
+
words+=("$separator")
|
|
127
|
+
fi
|
|
128
|
+
;;
|
|
120
129
|
'>')
|
|
121
130
|
flush
|
|
122
131
|
while [[ ${text:index+1:1} == [\>\|\&] ]]; do
|
|
@@ -271,7 +280,9 @@ check_command() {
|
|
|
271
280
|
continue
|
|
272
281
|
fi
|
|
273
282
|
case ${word##*/} in
|
|
274
|
-
env | command | exec | nohup | time | nice | sudo | builtin
|
|
283
|
+
env | command | exec | nohup | time | nice | sudo | builtin | if | then | else | elif | fi | while | until | for | do | done | case | esac | select | in | '!' | '{' | '}')
|
|
284
|
+
args=("${args[@]:1}")
|
|
285
|
+
;;
|
|
275
286
|
*) break ;;
|
|
276
287
|
esac
|
|
277
288
|
done
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Codebase Hygiene
|
|
2
|
+
|
|
3
|
+
Keep the codebase clean. Modify existing code instead of accumulating new code. Git owns history, not source code.
|
|
4
|
+
|
|
5
|
+
- **No duplication.** Do not add code that repeats an existing declaration or behavior.
|
|
6
|
+
- **No dead code.** Do not keep code the current behavior does not run.
|
|
7
|
+
- **No unnecessary versioning.** Do not store version history in source. Do not add a version constant or a versioned copy of a prompt, instruction, or behavior.
|
|
8
|
+
- **No log accumulation.** Do not add a log that repeats one already recorded, and do not commit log output.
|
|
9
|
+
- **Single source of truth.** One fact has one owning declaration.
|
|
10
|
+
- **Minimal changes.** Change only what the current behavior requires.
|
|
11
|
+
- **Remove before adding.** Change or delete the existing code before adding new code. When a declaration already exists, overwrite it. Do not keep the previous text as an example.
|
|
12
|
+
|
|
13
|
+
_Completion criterion_: The diff changes or deletes current code when that meets the requirement. New code exists only when no current code can be changed to do the job. History stays in git.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Descriptive Naming
|
|
2
|
+
|
|
3
|
+
A path or identifier names what it holds. A reader knows what a file, directory, module, or route contains without opening it.
|
|
4
|
+
|
|
5
|
+
- **Name the responsibility.** Each file and directory name states the feature, domain concept, or role it holds.
|
|
6
|
+
- **No organization names.** Do not put an organization, brand, customer, or tenant name in a path or identifier. User-visible text that names the organization reads it from one configured source, not from a literal.
|
|
7
|
+
- **Distinguishable siblings.** Qualify a generic word such as `settings`, `config`, `utils`, `helpers`, `common`, or `detail` with its domain noun. Files that sit together each name the role they play.
|
|
8
|
+
- **Do not copy a name that breaks this rule.** Sibling style does not override it. Give new code a descriptive name and report the existing name to the user.
|
|
9
|
+
|
|
10
|
+
Folder names and file suffixes that the framework or toolchain requires follow that tool's convention.
|
|
11
|
+
|
|
12
|
+
_Completion criterion_: Every path and identifier the diff adds names its responsibility, contains no organization name, and is distinguishable from its siblings.
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Treat each application, package, or component as one author's work. Match representative siblings for layout, naming, exports, helpers, composition, errors, and abstraction. Use the language's standard idiom when no sibling exists. Name the convention when a conflict affects the design.
|
|
4
4
|
|
|
5
|
-
Keep execution flow collocated. Extract a helper when multiple callers share it. One term per concept; parallel symbols share grammatical shape. Comments follow `code-comments.md`.
|
|
5
|
+
Keep execution flow collocated. Extract a helper when multiple callers share it. One term per concept; parallel symbols share grammatical shape. Comments follow `code-comments.md`. Names follow `descriptive-naming.md`, which matching siblings does not override.
|
|
6
6
|
|
|
7
7
|
Keep edits in the requested component, its call sites, and the workspace metadata it needs. Cross-project convention changes are in scope only when the task names them.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@../../.agents/rules/codebase-hygiene.md
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@../../.agents/rules/descriptive-naming.md
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
"Edit(./scripts/sync-agent-rules.ts)",
|
|
19
19
|
"Edit(./scripts/check-agent-gates.ts)",
|
|
20
20
|
"Edit(./.husky/**)",
|
|
21
|
+
"Edit(./.git/hooks/**)",
|
|
22
|
+
"Edit(./.git/config)",
|
|
23
|
+
"Edit(./.git/config.worktree)",
|
|
21
24
|
"Edit(./.lintstagedrc.json)",
|
|
22
25
|
"Edit(./.gitleaks.toml)",
|
|
23
26
|
"Bash(gh repo delete *)",
|
|
@@ -5,9 +5,11 @@ Review pull requests against the project's agent guide and rules:
|
|
|
5
5
|
- [Agent guide](../AGENTS.md)
|
|
6
6
|
- [Owned Checks](../.agents/rules/automation-owned-checks.md)
|
|
7
7
|
- [Required Comments](../.agents/rules/code-comments.md)
|
|
8
|
+
- [Codebase Hygiene](../.agents/rules/codebase-hygiene.md)
|
|
8
9
|
- [Current State](../.agents/rules/current-state-authority.md)
|
|
9
10
|
- [Demand-Driven Configuration](../.agents/rules/demand-driven-configuration.md)
|
|
10
11
|
- [Dependencies](../.agents/rules/dependency-security.md)
|
|
12
|
+
- [Descriptive Naming](../.agents/rules/descriptive-naming.md)
|
|
11
13
|
- [Test Admission](../.agents/rules/deterministic-testing.md)
|
|
12
14
|
- [Diagnostics](../.agents/rules/diagnostics-and-error-handling.md)
|
|
13
15
|
- [Git Workflow](../.agents/rules/git-workflow.md)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -uo pipefail
|
|
3
3
|
|
|
4
|
-
protected='^(\.agents/rules/|\.agents/rules\.json$|\.agents/hooks/|\.claude/rules/|\.claude/settings(\.local)?\.json$|\.cursor/rules/|\.cursor/hooks/|\.cursor/hooks\.json$|scripts/sync-agent-rules\.ts$|scripts/check-agent-gates\.ts$|\.commitlintrc\.json$|\.prettierrc\.json$|prettier\.config\.ts$|eslint\.config\.ts$|\.husky/|\.lintstagedrc\.json$|\.gitleaks\.toml
|
|
4
|
+
protected='^(\.agents/rules/|\.agents/rules\.json$|\.agents/hooks/|\.claude/rules/|\.claude/settings(\.local)?\.json$|\.cursor/rules/|\.cursor/hooks/|\.cursor/hooks\.json$|scripts/sync-agent-rules\.ts$|scripts/check-agent-gates\.ts$|\.commitlintrc\.json$|\.prettierrc\.json$|prettier\.config\.ts$|eslint\.config\.ts$|\.husky/|\.lintstagedrc\.json$|\.gitleaks\.toml$|\.git/hooks/|\.git/config(\.worktree)?$)'
|
|
5
5
|
|
|
6
6
|
allow() {
|
|
7
7
|
printf '%s\n' '{"permission":"allow"}'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Codebase Hygiene
|
|
7
|
+
|
|
8
|
+
Keep the codebase clean. Modify existing code instead of accumulating new code. Git owns history, not source code.
|
|
9
|
+
|
|
10
|
+
- **No duplication.** Do not add code that repeats an existing declaration or behavior.
|
|
11
|
+
- **No dead code.** Do not keep code the current behavior does not run.
|
|
12
|
+
- **No unnecessary versioning.** Do not store version history in source. Do not add a version constant or a versioned copy of a prompt, instruction, or behavior.
|
|
13
|
+
- **No log accumulation.** Do not add a log that repeats one already recorded, and do not commit log output.
|
|
14
|
+
- **Single source of truth.** One fact has one owning declaration.
|
|
15
|
+
- **Minimal changes.** Change only what the current behavior requires.
|
|
16
|
+
- **Remove before adding.** Change or delete the existing code before adding new code. When a declaration already exists, overwrite it. Do not keep the previous text as an example.
|
|
17
|
+
|
|
18
|
+
_Completion criterion_: The diff changes or deletes current code when that meets the requirement. New code exists only when no current code can be changed to do the job. History stays in git.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Descriptive Naming
|
|
7
|
+
|
|
8
|
+
A path or identifier names what it holds. A reader knows what a file, directory, module, or route contains without opening it.
|
|
9
|
+
|
|
10
|
+
- **Name the responsibility.** Each file and directory name states the feature, domain concept, or role it holds.
|
|
11
|
+
- **No organization names.** Do not put an organization, brand, customer, or tenant name in a path or identifier. User-visible text that names the organization reads it from one configured source, not from a literal.
|
|
12
|
+
- **Distinguishable siblings.** Qualify a generic word such as `settings`, `config`, `utils`, `helpers`, `common`, or `detail` with its domain noun. Files that sit together each name the role they play.
|
|
13
|
+
- **Do not copy a name that breaks this rule.** Sibling style does not override it. Give new code a descriptive name and report the existing name to the user.
|
|
14
|
+
|
|
15
|
+
Folder names and file suffixes that the framework or toolchain requires follow that tool's convention.
|
|
16
|
+
|
|
17
|
+
_Completion criterion_: Every path and identifier the diff adds names its responsibility, contains no organization name, and is distinguishable from its siblings.
|
|
@@ -7,6 +7,6 @@ alwaysApply: true
|
|
|
7
7
|
|
|
8
8
|
Treat each application, package, or component as one author's work. Match representative siblings for layout, naming, exports, helpers, composition, errors, and abstraction. Use the language's standard idiom when no sibling exists. Name the convention when a conflict affects the design.
|
|
9
9
|
|
|
10
|
-
Keep execution flow collocated. Extract a helper when multiple callers share it. One term per concept; parallel symbols share grammatical shape. Comments follow `code-comments.md`.
|
|
10
|
+
Keep execution flow collocated. Extract a helper when multiple callers share it. One term per concept; parallel symbols share grammatical shape. Comments follow `code-comments.md`. Names follow `descriptive-naming.md`, which matching siblings does not override.
|
|
11
11
|
|
|
12
12
|
Keep edits in the requested component, its call sites, and the workspace metadata it needs. Cross-project convention changes are in scope only when the task names them.
|
|
@@ -75,6 +75,11 @@ const blockedCommands = [
|
|
|
75
75
|
'echo "$(true&# )\ngit commit -n -m x)"',
|
|
76
76
|
'echo "$(true|# )\ngit commit -n -m x)"',
|
|
77
77
|
'echo "$( (true)# )\ngit commit -n -m x)"',
|
|
78
|
+
"{ git commit --no-verify -m x; }",
|
|
79
|
+
"if true; then git commit -n -m x; fi",
|
|
80
|
+
"while true; do git commit -n -m x; done",
|
|
81
|
+
"if git commit -n -m x; then true; fi",
|
|
82
|
+
"printf x > .git/config.worktree",
|
|
78
83
|
];
|
|
79
84
|
|
|
80
85
|
const allowedCommands = [
|
|
@@ -115,6 +120,9 @@ const protectedPaths = [
|
|
|
115
120
|
".husky/pre-commit",
|
|
116
121
|
".lintstagedrc.json",
|
|
117
122
|
".gitleaks.toml",
|
|
123
|
+
".git/hooks/pre-commit",
|
|
124
|
+
".git/config",
|
|
125
|
+
".git/config.worktree",
|
|
118
126
|
".claude/settings.local.json",
|
|
119
127
|
"src/../.husky/pre-commit",
|
|
120
128
|
];
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"code-comments": {
|
|
6
6
|
"description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
|
|
7
7
|
},
|
|
8
|
+
"codebase-hygiene": {
|
|
9
|
+
"description": "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
10
|
+
},
|
|
8
11
|
"current-state-authority": {
|
|
9
12
|
"description": "Current state: implement from user requirements and the working tree"
|
|
10
13
|
},
|
|
@@ -15,6 +18,9 @@
|
|
|
15
18
|
"description": "Dependencies: add a package only when code or a contract uses it",
|
|
16
19
|
"globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
|
|
17
20
|
},
|
|
21
|
+
"descriptive-naming": {
|
|
22
|
+
"description": "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
23
|
+
},
|
|
18
24
|
"deterministic-testing": {
|
|
19
25
|
"description": "Test admission: add a case only when it catches a defect current tests miss",
|
|
20
26
|
"globs": ["**/*.test.ts"]
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"code-comments": {
|
|
6
6
|
"description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
|
|
7
7
|
},
|
|
8
|
+
"codebase-hygiene": {
|
|
9
|
+
"description": "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
10
|
+
},
|
|
8
11
|
"current-state-authority": {
|
|
9
12
|
"description": "Current state: implement from user requirements and the working tree"
|
|
10
13
|
},
|
|
@@ -15,6 +18,9 @@
|
|
|
15
18
|
"description": "Dependencies: add a package only when code or a contract uses it",
|
|
16
19
|
"globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
|
|
17
20
|
},
|
|
21
|
+
"descriptive-naming": {
|
|
22
|
+
"description": "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
23
|
+
},
|
|
18
24
|
"deterministic-testing": {
|
|
19
25
|
"description": "Test admission: add a case only when it catches a defect current tests miss",
|
|
20
26
|
"globs": ["**/*.test.ts", "**/*.test.tsx"]
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"code-comments": {
|
|
6
6
|
"description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
|
|
7
7
|
},
|
|
8
|
+
"codebase-hygiene": {
|
|
9
|
+
"description": "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
10
|
+
},
|
|
8
11
|
"current-state-authority": {
|
|
9
12
|
"description": "Current state: implement from user requirements and the working tree"
|
|
10
13
|
},
|
|
@@ -15,6 +18,9 @@
|
|
|
15
18
|
"description": "Dependencies: add a package only when code or a contract uses it",
|
|
16
19
|
"globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
|
|
17
20
|
},
|
|
21
|
+
"descriptive-naming": {
|
|
22
|
+
"description": "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
23
|
+
},
|
|
18
24
|
"deterministic-testing": {
|
|
19
25
|
"description": "Test admission: add a case only when it catches a defect current tests miss",
|
|
20
26
|
"globs": ["**/*.test.ts"]
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"code-comments": {
|
|
6
6
|
"description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
|
|
7
7
|
},
|
|
8
|
+
"codebase-hygiene": {
|
|
9
|
+
"description": "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
10
|
+
},
|
|
8
11
|
"current-state-authority": {
|
|
9
12
|
"description": "Current state: implement from user requirements and the working tree"
|
|
10
13
|
},
|
|
@@ -15,6 +18,9 @@
|
|
|
15
18
|
"description": "Dependencies: add a package only when code or a contract uses it",
|
|
16
19
|
"globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
|
|
17
20
|
},
|
|
21
|
+
"descriptive-naming": {
|
|
22
|
+
"description": "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
23
|
+
},
|
|
18
24
|
"deterministic-testing": {
|
|
19
25
|
"description": "Test admission: add a case only when it catches a defect current tests miss",
|
|
20
26
|
"globs": ["**/*.test.ts", "**/*.test.tsx"]
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"code-comments": {
|
|
6
6
|
"description": "Required comments: comment only where a tool or rule needs it, or for a reason the code cannot show"
|
|
7
7
|
},
|
|
8
|
+
"codebase-hygiene": {
|
|
9
|
+
"description": "Codebase hygiene: modify existing code instead of accumulating new code"
|
|
10
|
+
},
|
|
8
11
|
"current-state-authority": {
|
|
9
12
|
"description": "Current state: implement from user requirements and the working tree"
|
|
10
13
|
},
|
|
@@ -15,6 +18,9 @@
|
|
|
15
18
|
"description": "Dependencies: add a package only when code or a contract uses it",
|
|
16
19
|
"globs": ["package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml"]
|
|
17
20
|
},
|
|
21
|
+
"descriptive-naming": {
|
|
22
|
+
"description": "Descriptive naming: paths and identifiers name what they hold, without organization names"
|
|
23
|
+
},
|
|
18
24
|
"deterministic-testing": {
|
|
19
25
|
"description": "Test admission: add a case only when it catches a defect current tests miss",
|
|
20
26
|
"globs": ["**/*.test.ts", "**/*.test.tsx"]
|