duaer-spec 0.1.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.
Files changed (75) hide show
  1. package/.cursor/rules/agents-workflow.mdc +50 -0
  2. package/.cursor/rules/ai-ui-copy.mdc +12 -0
  3. package/.cursor/rules/duaer-spec.mdc +33 -0
  4. package/.cursor/skills/duaer-analyze/SKILL.md +259 -0
  5. package/.cursor/skills/duaer-checklist/SKILL.md +383 -0
  6. package/.cursor/skills/duaer-clarify/SKILL.md +291 -0
  7. package/.cursor/skills/duaer-constitution/SKILL.md +177 -0
  8. package/.cursor/skills/duaer-converge/SKILL.md +277 -0
  9. package/.cursor/skills/duaer-git-commit/SKILL.md +68 -0
  10. package/.cursor/skills/duaer-git-feature/SKILL.md +94 -0
  11. package/.cursor/skills/duaer-git-initialize/SKILL.md +54 -0
  12. package/.cursor/skills/duaer-git-remote/SKILL.md +50 -0
  13. package/.cursor/skills/duaer-git-validate/SKILL.md +54 -0
  14. package/.cursor/skills/duaer-implement/SKILL.md +226 -0
  15. package/.cursor/skills/duaer-plan/SKILL.md +166 -0
  16. package/.cursor/skills/duaer-specify/SKILL.md +345 -0
  17. package/.cursor/skills/duaer-tasks/SKILL.md +214 -0
  18. package/.cursor/skills/duaer-taskstoissues/SKILL.md +109 -0
  19. package/.duaer/extensions/.registry +23 -0
  20. package/.duaer/extensions/git/README.md +119 -0
  21. package/.duaer/extensions/git/commands/duaer.git.commit.md +63 -0
  22. package/.duaer/extensions/git/commands/duaer.git.feature.md +82 -0
  23. package/.duaer/extensions/git/commands/duaer.git.initialize.md +49 -0
  24. package/.duaer/extensions/git/commands/duaer.git.remote.md +45 -0
  25. package/.duaer/extensions/git/commands/duaer.git.validate.md +49 -0
  26. package/.duaer/extensions/git/config-template.yml +79 -0
  27. package/.duaer/extensions/git/extension.yml +142 -0
  28. package/.duaer/extensions/git/git-config.yml +79 -0
  29. package/.duaer/extensions/git/scripts/bash/auto-commit.sh +211 -0
  30. package/.duaer/extensions/git/scripts/bash/create-new-feature-branch.sh +626 -0
  31. package/.duaer/extensions/git/scripts/bash/git-common.sh +56 -0
  32. package/.duaer/extensions/git/scripts/bash/initialize-repo.sh +54 -0
  33. package/.duaer/extensions/git/scripts/powershell/auto-commit.ps1 +230 -0
  34. package/.duaer/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +592 -0
  35. package/.duaer/extensions/git/scripts/powershell/git-common.ps1 +52 -0
  36. package/.duaer/extensions/git/scripts/powershell/initialize-repo.ps1 +69 -0
  37. package/.duaer/extensions/git/scripts/python/auto_commit.py +195 -0
  38. package/.duaer/extensions/git/scripts/python/create_new_feature_branch.py +634 -0
  39. package/.duaer/extensions/git/scripts/python/git_common.py +81 -0
  40. package/.duaer/extensions/git/scripts/python/initialize_repo.py +89 -0
  41. package/.duaer/extensions.yml +167 -0
  42. package/.duaer/init-options.json +9 -0
  43. package/.duaer/integration.json +15 -0
  44. package/.duaer/integrations/cursor-agent.manifest.json +17 -0
  45. package/.duaer/integrations/duaer.manifest.json +19 -0
  46. package/.duaer/memory/.constitution-template.json +4 -0
  47. package/.duaer/memory/constitution.md +37 -0
  48. package/.duaer/memory/project-context.md +24 -0
  49. package/.duaer/memory/testing.md +14 -0
  50. package/.duaer/scripts/bash/check-prerequisites.sh +243 -0
  51. package/.duaer/scripts/bash/common.sh +926 -0
  52. package/.duaer/scripts/bash/create-new-feature.sh +407 -0
  53. package/.duaer/scripts/bash/resolve-template.sh +57 -0
  54. package/.duaer/scripts/bash/setup-plan.sh +85 -0
  55. package/.duaer/scripts/bash/setup-tasks.sh +94 -0
  56. package/.duaer/templates/checklist-template.md +45 -0
  57. package/.duaer/templates/constitution-template.md +50 -0
  58. package/.duaer/templates/plan-template.md +113 -0
  59. package/.duaer/templates/spec-template.md +131 -0
  60. package/.duaer/templates/tasks-template.md +252 -0
  61. package/.duaer/workflows/duaer/workflow.yml +78 -0
  62. package/.duaer/workflows/workflow-registry.json +13 -0
  63. package/ADOPT.md +75 -0
  64. package/AGENTS.md +290 -0
  65. package/CHANGELOG.md +28 -0
  66. package/DUADER.md +57 -0
  67. package/LICENSE +21 -0
  68. package/README.md +74 -0
  69. package/bin/duaer.mjs +298 -0
  70. package/docs/agent/README.md +12 -0
  71. package/docs/agent/change-checklist.md +130 -0
  72. package/docs/agent/e2e-test-plan.md +33 -0
  73. package/docs/agent/workflow.md +127 -0
  74. package/docs/baseline.md +10 -0
  75. package/package.json +49 -0
@@ -0,0 +1,79 @@
1
+ # Git Branching Workflow Extension Configuration
2
+ # Copied to .duaer/extensions/git/git-config.yml on install
3
+
4
+ # Branch numbering strategy: "sequential" (001, 002, ...) or "timestamp" (YYYYMMDD-HHMMSS)
5
+ branch_numbering: sequential
6
+
7
+ # Optional branch name template. Leave empty for the default "{number}-{slug}".
8
+ # Supported tokens: {author}, {app}, {number}, {slug}
9
+ # {slug} must not appear before {number}; final path segment must start with {number}-.
10
+ # Example for monorepos: "{author}/{app}/{number}-{slug}"
11
+ branch_template: ""
12
+
13
+ # Optional shorthand namespace. Leave empty to use branch_template/default behavior.
14
+ # Example: "features/{app}" expands to "features/{app}/{number}-{slug}"
15
+ branch_prefix: "feat"
16
+
17
+ # Commit message used by `git commit` during repository initialization
18
+ init_commit_message: "[Duaer] Initial commit"
19
+
20
+ # Commit message style used by auto-commit hooks (duaer.git.commit):
21
+ # "fixed" - default; use the configured/static messages below.
22
+ # "conventional" - ask the agent to inspect the diff and generate a
23
+ # Conventional Commit message (e.g. "feat: add OAuth spec")
24
+ # instead of using the messages configured below.
25
+ commit_style: fixed
26
+
27
+ # Auto-commit before/after core commands.
28
+ # Set "default" to enable for all commands, then override per-command.
29
+ # Each key can be true/false. Message is customizable per-command.
30
+ auto_commit:
31
+ default: false
32
+ before_clarify:
33
+ enabled: false
34
+ message: "[Duaer] Save progress before clarification"
35
+ before_plan:
36
+ enabled: false
37
+ message: "[Duaer] Save progress before planning"
38
+ before_tasks:
39
+ enabled: false
40
+ message: "[Duaer] Save progress before task generation"
41
+ before_implement:
42
+ enabled: false
43
+ message: "[Duaer] Save progress before implementation"
44
+ before_checklist:
45
+ enabled: false
46
+ message: "[Duaer] Save progress before checklist"
47
+ before_analyze:
48
+ enabled: false
49
+ message: "[Duaer] Save progress before analysis"
50
+ before_taskstoissues:
51
+ enabled: false
52
+ message: "[Duaer] Save progress before issue sync"
53
+ after_constitution:
54
+ enabled: false
55
+ message: "[Duaer] Add project constitution"
56
+ after_specify:
57
+ enabled: false
58
+ message: "[Duaer] Add specification"
59
+ after_clarify:
60
+ enabled: false
61
+ message: "[Duaer] Clarify specification"
62
+ after_plan:
63
+ enabled: false
64
+ message: "[Duaer] Add implementation plan"
65
+ after_tasks:
66
+ enabled: false
67
+ message: "[Duaer] Add tasks"
68
+ after_implement:
69
+ enabled: false
70
+ message: "[Duaer] Implementation progress"
71
+ after_checklist:
72
+ enabled: false
73
+ message: "[Duaer] Add checklist"
74
+ after_analyze:
75
+ enabled: false
76
+ message: "[Duaer] Add analysis report"
77
+ after_taskstoissues:
78
+ enabled: false
79
+ message: "[Duaer] Sync tasks to issues"
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env bash
2
+ # Git extension: auto-commit.sh
3
+ # Automatically commit changes after a Duaer command completes.
4
+ # Checks per-command config keys in git-config.yml before committing.
5
+ #
6
+ # Usage: auto-commit.sh <event_name> [generated_message]
7
+ # auto-commit.sh <event_name> --message-file <path>
8
+ # e.g.: auto-commit.sh after_specify
9
+ # e.g.: auto-commit.sh after_specify --message-file /tmp/commit-msg.txt (commit_style: conventional)
10
+ #
11
+ # --message-file is the preferred way to supply an agent-generated commit
12
+ # message: it reads the message from a file instead of a shell argument,
13
+ # so message content (which may contain quotes, `$(...)`, backticks, etc.)
14
+ # is never interpolated into a shell command line.
15
+
16
+ set -e
17
+
18
+ EVENT_NAME="${1:-}"
19
+ if [ -z "$EVENT_NAME" ]; then
20
+ echo "Usage: $0 <event_name> [generated_message | --message-file <path>]" >&2
21
+ exit 1
22
+ fi
23
+ shift || true
24
+
25
+ # Optional second argument: an agent-generated commit message (used when
26
+ # commit_style: conventional is configured). Prefer --message-file over
27
+ # passing the message directly as a shell argument.
28
+ GENERATED_MESSAGE=""
29
+ while [ $# -gt 0 ]; do
30
+ case "$1" in
31
+ --message-file)
32
+ _message_file="${2:-}"
33
+ if [ -z "$_message_file" ]; then
34
+ echo "[specify] Error: --message-file requires a path argument" >&2
35
+ exit 1
36
+ fi
37
+ if [ ! -f "$_message_file" ]; then
38
+ echo "[specify] Error: message file '$_message_file' not found" >&2
39
+ exit 1
40
+ fi
41
+ GENERATED_MESSAGE="$(cat "$_message_file")"
42
+ # The message file is a transport-only artifact: its content is
43
+ # now captured above, so remove it immediately. Otherwise, if it
44
+ # was written inside the worktree, it would be picked up as an
45
+ # untracked change by both the "any changes?" check below and by
46
+ # `git add .`, polluting the commit or defeating the no-changes
47
+ # short-circuit even when nothing else changed.
48
+ rm -f "$_message_file"
49
+ shift 2
50
+ ;;
51
+ *)
52
+ GENERATED_MESSAGE="$1"
53
+ shift
54
+ ;;
55
+ esac
56
+ done
57
+
58
+ SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
59
+
60
+ _find_project_root() {
61
+ local dir="$1"
62
+ while [ "$dir" != "/" ]; do
63
+ if [ -d "$dir/.duaer" ] || [ -d "$dir/.git" ]; then
64
+ echo "$dir"
65
+ return 0
66
+ fi
67
+ dir="$(dirname "$dir")"
68
+ done
69
+ return 1
70
+ }
71
+
72
+ REPO_ROOT=$(_find_project_root "$SCRIPT_DIR") || REPO_ROOT="$(pwd)"
73
+ cd "$REPO_ROOT"
74
+
75
+ # Check if git is available
76
+ if ! command -v git >/dev/null 2>&1; then
77
+ echo "[specify] Warning: Git not found; skipped auto-commit" >&2
78
+ exit 0
79
+ fi
80
+
81
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
82
+ echo "[specify] Warning: Not a Git repository; skipped auto-commit" >&2
83
+ exit 0
84
+ fi
85
+
86
+ # Read per-command config from git-config.yml
87
+ _config_file="$REPO_ROOT/.duaer/extensions/git/git-config.yml"
88
+ _enabled=false
89
+ _commit_msg=""
90
+ _commit_style="fixed"
91
+
92
+ if [ -f "$_config_file" ]; then
93
+ # Top-level scalar key: commit_style (fixed | conventional)
94
+ _style_val=$(grep -m1 '^commit_style:' "$_config_file" 2>/dev/null | sed 's/^commit_style:[[:space:]]*//' | sed 's/[[:space:]]\{1,\}#.*$//' | sed 's/[[:space:]]*$//' | sed 's/^["'\'']//' | sed 's/["'\'']*$//' | tr '[:upper:]' '[:lower:]')
95
+ if [ -n "$_style_val" ]; then
96
+ case "$_style_val" in
97
+ fixed|conventional)
98
+ _commit_style="$_style_val"
99
+ ;;
100
+ *)
101
+ echo "[specify] Warning: unknown commit_style '$_style_val' in git-config.yml (expected 'fixed' or 'conventional'); defaulting to 'fixed'" >&2
102
+ ;;
103
+ esac
104
+ fi
105
+
106
+ # Parse the auto_commit section for this event.
107
+ # Look for auto_commit.<event_name>.enabled and .message
108
+ # Also check auto_commit.default as fallback.
109
+ _in_auto_commit=false
110
+ _in_event=false
111
+ _default_enabled=false
112
+
113
+ while IFS= read -r _line; do
114
+ # Detect auto_commit: section
115
+ if echo "$_line" | grep -q '^auto_commit:'; then
116
+ _in_auto_commit=true
117
+ _in_event=false
118
+ continue
119
+ fi
120
+
121
+ # Exit auto_commit section on next top-level key
122
+ if $_in_auto_commit && echo "$_line" | grep -Eq '^[a-z]'; then
123
+ break
124
+ fi
125
+
126
+ if $_in_auto_commit; then
127
+ # Check default key
128
+ if echo "$_line" | grep -Eq "^[[:space:]]+default:[[:space:]]"; then
129
+ _val=$(echo "$_line" | sed 's/^[^:]*:[[:space:]]*//' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
130
+ [ "$_val" = "true" ] && _default_enabled=true
131
+ fi
132
+
133
+ # Detect our event subsection
134
+ if echo "$_line" | grep -Eq "^[[:space:]]+${EVENT_NAME}:"; then
135
+ _in_event=true
136
+ continue
137
+ fi
138
+
139
+ # Inside our event subsection
140
+ if $_in_event; then
141
+ # Exit on next sibling key (same indent level as event name)
142
+ if echo "$_line" | grep -Eq '^[[:space:]]{2}[a-z]' && ! echo "$_line" | grep -Eq '^[[:space:]]{4}'; then
143
+ _in_event=false
144
+ continue
145
+ fi
146
+ if echo "$_line" | grep -Eq '[[:space:]]+enabled:'; then
147
+ _val=$(echo "$_line" | sed 's/^[^:]*:[[:space:]]*//' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
148
+ [ "$_val" = "true" ] && _enabled=true
149
+ [ "$_val" = "false" ] && _enabled=false
150
+ fi
151
+ if echo "$_line" | grep -Eq '[[:space:]]+message:'; then
152
+ # Trim trailing whitespace before stripping the closing quote:
153
+ # a value like `message: "Done" ` (trailing spaces after the
154
+ # quote) would otherwise leave the quote dangling (`Done" `),
155
+ # since the closing-quote strip is anchored to end-of-string.
156
+ # The PowerShell twin .Trim()s first; match it for parity.
157
+ _commit_msg=$(echo "$_line" | sed 's/^[^:]*:[[:space:]]*//' | sed 's/[[:space:]]*$//' | sed 's/^["'\'']//' | sed 's/["'\'']*$//')
158
+ fi
159
+ fi
160
+ fi
161
+ done < "$_config_file"
162
+
163
+ # If event-specific key not found, use default
164
+ if [ "$_enabled" = "false" ] && [ "$_default_enabled" = "true" ]; then
165
+ # Only use default if the event wasn't explicitly set to false
166
+ # Check if event section existed at all
167
+ if ! grep -q "^[[:space:]]*${EVENT_NAME}:" "$_config_file" 2>/dev/null; then
168
+ _enabled=true
169
+ fi
170
+ fi
171
+ else
172
+ # No config file — auto-commit disabled by default
173
+ exit 0
174
+ fi
175
+
176
+ if [ "$_enabled" != "true" ]; then
177
+ exit 0
178
+ fi
179
+
180
+ # Check if there are changes to commit
181
+ if git diff --quiet HEAD 2>/dev/null && git diff --cached --quiet 2>/dev/null && [ -z "$(git ls-files --others --exclude-standard 2>/dev/null)" ]; then
182
+ echo "[specify] No changes to commit after $EVENT_NAME" >&2
183
+ exit 0
184
+ fi
185
+
186
+ # In conventional mode, the commit message must be supplied by the agent
187
+ # (via the generated_message argument); never fall back to the fixed message.
188
+ if [ "$_commit_style" = "conventional" ]; then
189
+ if [ -n "$GENERATED_MESSAGE" ]; then
190
+ _commit_msg="$GENERATED_MESSAGE"
191
+ else
192
+ echo "[specify] Error: commit_style is 'conventional' but no generated commit message was supplied; aborting auto-commit (pass --message-file <path>, or a raw message as arg 2, or set commit_style: fixed)" >&2
193
+ exit 1
194
+ fi
195
+ fi
196
+
197
+ # Derive a human-readable command name from the event
198
+ # e.g., after_specify -> specify, before_plan -> plan
199
+ _command_name=$(echo "$EVENT_NAME" | sed 's/^after_//' | sed 's/^before_//')
200
+ _phase=$(echo "$EVENT_NAME" | grep -q '^before_' && echo 'before' || echo 'after')
201
+
202
+ # Use custom message if configured, otherwise default
203
+ if [ -z "$_commit_msg" ]; then
204
+ _commit_msg="[Duaer] Auto-commit ${_phase} ${_command_name}"
205
+ fi
206
+
207
+ # Stage and commit
208
+ _git_out=$(git add . 2>&1) || { echo "[specify] Error: git add failed: $_git_out" >&2; exit 1; }
209
+ _git_out=$(git commit -q -m "$_commit_msg" 2>&1) || { echo "[specify] Error: git commit failed: $_git_out" >&2; exit 1; }
210
+
211
+ echo "[OK] Changes committed ${_phase} ${_command_name}" >&2