* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
453
gsd-core/workflows/profile-user.md
Normal file
453
gsd-core/workflows/profile-user.md
Normal file
@@ -0,0 +1,453 @@
|
||||
<purpose>
|
||||
Orchestrate the full developer profiling flow: consent, session analysis (or questionnaire fallback), profile generation, result display, and artifact creation.
|
||||
|
||||
This workflow wires Phase 1 (session pipeline) and Phase 2 (profiling engine) into a cohesive user-facing experience. All heavy lifting is done by existing `gsd-tools.cjs query` handlers (with legacy `gsd-tools.cjs` parity where needed) and the gsd-user-profiler agent -- this workflow orchestrates the sequence, handles branching, and provides the UX.
|
||||
</purpose>
|
||||
|
||||
<required_reading>
|
||||
Read all files referenced by the invoking prompt's execution_context before starting.
|
||||
|
||||
Key references:
|
||||
- @$HOME/.claude/gsd-core/references/ui-brand.md (display patterns)
|
||||
- @$HOME/.claude/agents/gsd-user-profiler.md (profiler agent definition)
|
||||
- @$HOME/.claude/gsd-core/references/user-profiling.md (profiling reference doc)
|
||||
</required_reading>
|
||||
|
||||
<process>
|
||||
|
||||
## 1. Initialize
|
||||
|
||||
Parse flags from $ARGUMENTS:
|
||||
- Detect `--questionnaire` flag (skip session analysis, questionnaire-only)
|
||||
- Detect `--refresh` flag (rebuild profile even when one exists)
|
||||
|
||||
Check for existing profile:
|
||||
|
||||
```bash
|
||||
PROFILE_PATH="$HOME/.claude/gsd-core/USER-PROFILE.md"
|
||||
[ -f "$PROFILE_PATH" ] && echo "EXISTS" || echo "NOT_FOUND"
|
||||
```
|
||||
|
||||
**If profile exists AND --refresh NOT set AND --questionnaire NOT set:**
|
||||
|
||||
|
||||
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
||||
Use AskUserQuestion:
|
||||
- header: "Existing Profile"
|
||||
- question: "You already have a profile. What would you like to do?"
|
||||
- options:
|
||||
- "View it" -- Display summary card from existing profile data, then exit
|
||||
- "Refresh it" -- Continue with --refresh behavior
|
||||
- "Cancel" -- Exit workflow
|
||||
|
||||
If "View it": Read USER-PROFILE.md, display its content formatted as a summary card, then exit.
|
||||
If "Refresh it": Set --refresh behavior and continue.
|
||||
If "Cancel": Display "No changes made." and exit.
|
||||
|
||||
**If profile exists AND --refresh IS set:**
|
||||
|
||||
Backup existing profile:
|
||||
```bash
|
||||
cp "$HOME/.claude/gsd-core/USER-PROFILE.md" "$HOME/.claude/USER-PROFILE.backup.md"
|
||||
```
|
||||
|
||||
Display: "Re-analyzing your sessions to update your profile."
|
||||
Continue to step 2.
|
||||
|
||||
**If no profile exists:** Continue to step 2.
|
||||
|
||||
---
|
||||
|
||||
## 2. Consent Gate (ACTV-06)
|
||||
|
||||
**Skip if** `--questionnaire` flag is set (no JSONL reading occurs -- jump directly to step 4b).
|
||||
|
||||
Display consent screen:
|
||||
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD > PROFILE YOUR CODING STYLE
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Claude starts every conversation generic. A profile teaches Claude
|
||||
how YOU actually work -- not how you think you work.
|
||||
|
||||
## What We'll Analyze
|
||||
|
||||
Your recent Claude Code sessions, looking for patterns in these
|
||||
8 behavioral dimensions:
|
||||
|
||||
| Dimension | What It Measures |
|
||||
|----------------------|---------------------------------------------|
|
||||
| Communication Style | How you phrase requests (terse vs. detailed) |
|
||||
| Decision Speed | How you choose between options |
|
||||
| Explanation Depth | How much explanation you want with code |
|
||||
| Debugging Approach | How you tackle errors and bugs |
|
||||
| UX Philosophy | How much you care about design vs. function |
|
||||
| Vendor Philosophy | How you evaluate libraries and tools |
|
||||
| Frustration Triggers | What makes you correct Claude |
|
||||
| Learning Style | How you prefer to learn new things |
|
||||
|
||||
## Data Handling
|
||||
|
||||
✓ Reads session files locally (read-only, nothing modified)
|
||||
✓ Analyzes message patterns (not content meaning)
|
||||
✓ Stores profile at $HOME/.claude/gsd-core/USER-PROFILE.md
|
||||
✗ Nothing is sent to external services
|
||||
✗ Sensitive content (API keys, passwords) is automatically excluded
|
||||
```
|
||||
|
||||
**If --refresh path:**
|
||||
Show abbreviated consent instead:
|
||||
|
||||
```
|
||||
Re-analyzing your sessions to update your profile.
|
||||
Your existing profile has been backed up to USER-PROFILE.backup.md.
|
||||
```
|
||||
|
||||
Use AskUserQuestion:
|
||||
- header: "Refresh"
|
||||
- question: "Continue with profile refresh?"
|
||||
- options:
|
||||
- "Continue" -- Proceed to step 3
|
||||
- "Cancel" -- Exit workflow
|
||||
|
||||
**If default (no --refresh) path:**
|
||||
|
||||
Use AskUserQuestion:
|
||||
- header: "Ready?"
|
||||
- question: "Ready to analyze your sessions?"
|
||||
- options:
|
||||
- "Let's go" -- Proceed to step 3 (session analysis)
|
||||
- "Use questionnaire instead" -- Jump to step 4b (questionnaire path)
|
||||
- "Not now" -- Display "No worries. Run /gsd:profile-user when ready." and exit
|
||||
|
||||
---
|
||||
|
||||
## 3. Session Scan
|
||||
|
||||
Display: "◆ Scanning sessions..."
|
||||
|
||||
Run session scan:
|
||||
```bash
|
||||
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
||||
SCAN_RESULT=$(gsd_run query scan-sessions --json 2>/dev/null)
|
||||
```
|
||||
|
||||
Parse the JSON output to get session count and project count.
|
||||
|
||||
Display: "✓ Found N sessions across M projects"
|
||||
|
||||
**Determine data sufficiency:**
|
||||
- Count total messages available from the scan result (sum sessions across projects)
|
||||
- If 0 sessions found: Display "No sessions found. Switching to questionnaire." and jump to step 4b
|
||||
- If sessions found: Continue to step 4a
|
||||
|
||||
---
|
||||
|
||||
## 4a. Session Analysis Path
|
||||
|
||||
Display: "◆ Sampling messages..."
|
||||
|
||||
Run profile sampling:
|
||||
```bash
|
||||
SAMPLE_RESULT=$(gsd_run query profile-sample --json 2>/dev/null)
|
||||
```
|
||||
|
||||
Parse the JSON output to get the temp directory path and message count.
|
||||
|
||||
Display: "✓ Sampled N messages from M projects"
|
||||
|
||||
Display: "◆ Analyzing patterns..."
|
||||
|
||||
**Spawn gsd-user-profiler agent using Task tool:**
|
||||
|
||||
Use the Task tool to spawn the `gsd-user-profiler` agent. Provide it with:
|
||||
- The sampled JSONL file path from profile-sample output
|
||||
- The user-profiling reference doc at `$HOME/.claude/gsd-core/references/user-profiling.md`
|
||||
|
||||
The agent prompt should follow this structure:
|
||||
```
|
||||
Read the profiling reference document and the sampled session messages, then analyze the developer's behavioral patterns across all 8 dimensions.
|
||||
|
||||
Reference: @$HOME/.claude/gsd-core/references/user-profiling.md
|
||||
Session data: @{temp_dir}/profile-sample.jsonl
|
||||
|
||||
Analyze these messages and return your analysis in the <analysis> JSON format specified in the reference document.
|
||||
```
|
||||
|
||||
**Parse the agent's output:**
|
||||
- Extract the `<analysis>` JSON block from the agent's response
|
||||
- Save analysis JSON to a temp file (in the same temp directory created by profile-sample)
|
||||
|
||||
```bash
|
||||
ANALYSIS_PATH="{temp_dir}/analysis.json"
|
||||
```
|
||||
|
||||
Write the analysis JSON to `$ANALYSIS_PATH`.
|
||||
|
||||
Display: "✓ Analysis complete (N dimensions scored)"
|
||||
|
||||
**Check for thin data:**
|
||||
- Read the analysis JSON and check the total message count
|
||||
- If < 50 messages were analyzed: Note that a questionnaire supplement could improve accuracy. Display: "Note: Limited session data (N messages). Results may have lower confidence."
|
||||
|
||||
Continue to step 5.
|
||||
|
||||
---
|
||||
|
||||
## 4b. Questionnaire Path
|
||||
|
||||
Display: "Using questionnaire to build your profile."
|
||||
|
||||
**Get questions:**
|
||||
```bash
|
||||
QUESTIONS=$(gsd_run query profile-questionnaire --json 2>/dev/null)
|
||||
```
|
||||
|
||||
Parse the questions JSON. It contains 8 questions, one per dimension.
|
||||
|
||||
**Present each question to the user via AskUserQuestion:**
|
||||
|
||||
For each question in the questions array:
|
||||
- header: The dimension name (e.g., "Communication Style")
|
||||
- question: The question text
|
||||
- options: The answer options from the question definition
|
||||
|
||||
Collect all answers into an answers JSON object mapping dimension keys to selected answer values.
|
||||
|
||||
**Save answers to temp file:**
|
||||
```bash
|
||||
ANSWERS_PATH=$(mktemp /tmp/gsd-profile-answers-XXXXXX.json)
|
||||
```
|
||||
|
||||
Write the answers JSON to `$ANSWERS_PATH`.
|
||||
|
||||
**Convert answers to analysis:**
|
||||
```bash
|
||||
ANALYSIS_RESULT=$(gsd_run query profile-questionnaire --answers "$ANSWERS_PATH" --json 2>/dev/null)
|
||||
```
|
||||
|
||||
Parse the analysis JSON from the result.
|
||||
|
||||
Save analysis JSON to a temp file:
|
||||
```bash
|
||||
ANALYSIS_PATH=$(mktemp /tmp/gsd-profile-analysis-XXXXXX.json)
|
||||
```
|
||||
|
||||
Write the analysis JSON to `$ANALYSIS_PATH`.
|
||||
|
||||
Continue to step 5 (skip split resolution since questionnaire handles ambiguity internally).
|
||||
|
||||
---
|
||||
|
||||
## 5. Split Resolution
|
||||
|
||||
**Skip if** questionnaire-only path (splits already handled internally).
|
||||
|
||||
Read the analysis JSON from `$ANALYSIS_PATH`.
|
||||
|
||||
Check each dimension for `cross_project_consistent: false`.
|
||||
|
||||
**For each split detected:**
|
||||
|
||||
Use AskUserQuestion:
|
||||
- header: The dimension name (e.g., "Communication Style")
|
||||
- question: "Your sessions show different patterns:" followed by the split context (e.g., "CLI/backend projects -> terse-direct, Frontend/UI projects -> detailed-structured")
|
||||
- options:
|
||||
- Rating option A (e.g., "terse-direct")
|
||||
- Rating option B (e.g., "detailed-structured")
|
||||
- "Context-dependent (keep both)"
|
||||
|
||||
**If user picks a specific rating:** Update the dimension's `rating` field in the analysis JSON to the selected value.
|
||||
|
||||
**If user picks "Context-dependent":** Keep the dominant rating in the `rating` field. Add a `context_note` to the dimension's summary describing the split (e.g., "Context-dependent: terse in CLI projects, detailed in frontend projects").
|
||||
|
||||
Write updated analysis JSON back to `$ANALYSIS_PATH`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Profile Write
|
||||
|
||||
Display: "◆ Writing profile..."
|
||||
|
||||
```bash
|
||||
gsd_run query write-profile --input "$ANALYSIS_PATH" --json
|
||||
```
|
||||
|
||||
Display: "✓ Profile written to $HOME/.claude/gsd-core/USER-PROFILE.md"
|
||||
|
||||
---
|
||||
|
||||
## 7. Result Display
|
||||
|
||||
Read the analysis JSON from `$ANALYSIS_PATH` to build the display.
|
||||
|
||||
**Show report card table:**
|
||||
|
||||
```
|
||||
## Your Profile
|
||||
|
||||
| Dimension | Rating | Confidence |
|
||||
|----------------------|----------------------|------------|
|
||||
| Communication Style | detailed-structured | HIGH |
|
||||
| Decision Speed | deliberate-informed | MEDIUM |
|
||||
| Explanation Depth | concise | HIGH |
|
||||
| Debugging Approach | hypothesis-driven | MEDIUM |
|
||||
| UX Philosophy | pragmatic | LOW |
|
||||
| Vendor Philosophy | thorough-evaluator | HIGH |
|
||||
| Frustration Triggers | scope-creep | MEDIUM |
|
||||
| Learning Style | self-directed | HIGH |
|
||||
```
|
||||
|
||||
(Populate with actual values from the analysis JSON.)
|
||||
|
||||
**Show highlight reel:**
|
||||
|
||||
Pick 3-4 dimensions with the highest confidence and most evidence signals. Format as:
|
||||
|
||||
```
|
||||
## Highlights
|
||||
|
||||
- **Communication (HIGH):** You consistently provide structured context with
|
||||
headers and problem statements before making requests
|
||||
- **Vendor Choices (HIGH):** You research alternatives thoroughly -- comparing
|
||||
docs, GitHub activity, and bundle sizes before committing
|
||||
- **Frustrations (MEDIUM):** You correct Claude most often for doing things
|
||||
you didn't ask for -- scope creep is your primary trigger
|
||||
```
|
||||
|
||||
Build highlights from the `evidence` array and `summary` fields in the analysis JSON. Use the most compelling evidence quotes. Format each as "You tend to..." or "You consistently..." with evidence attribution.
|
||||
|
||||
**Offer full profile view:**
|
||||
|
||||
Use AskUserQuestion:
|
||||
- header: "Profile"
|
||||
- question: "Want to see the full profile?"
|
||||
- options:
|
||||
- "Yes" -- Read and display the full USER-PROFILE.md content, then continue to step 8
|
||||
- "Continue to artifacts" -- Proceed directly to step 8
|
||||
|
||||
---
|
||||
|
||||
## 8. Artifact Selection (ACTV-05)
|
||||
|
||||
Use AskUserQuestion with multiSelect:
|
||||
- header: "Artifacts"
|
||||
- question: "Which artifacts should I generate?"
|
||||
- options (ALL pre-selected by default):
|
||||
- "/gsd-dev-preferences command file" -- "Load your preferences in any session"
|
||||
- "CLAUDE.md profile section" -- "Add profile to this project's CLAUDE.md"
|
||||
- "Global CLAUDE.md" -- "Add profile to $HOME/.claude/CLAUDE.md for all projects"
|
||||
|
||||
**If no artifacts selected:** Display "No artifacts generated. Your profile is saved at $HOME/.claude/gsd-core/USER-PROFILE.md" and jump to step 10.
|
||||
|
||||
---
|
||||
|
||||
## 9. Artifact Generation
|
||||
|
||||
Generate selected artifacts sequentially (file I/O is fast, no benefit from parallel agents):
|
||||
|
||||
**For /gsd-dev-preferences (if selected):**
|
||||
|
||||
```bash
|
||||
gsd_run query generate-dev-preferences --analysis "$ANALYSIS_PATH" --json
|
||||
```
|
||||
|
||||
Display: "✓ Generated /gsd-dev-preferences at $HOME/.claude/skills/gsd-dev-preferences/SKILL.md"
|
||||
|
||||
**For CLAUDE.md profile section (if selected):**
|
||||
|
||||
```bash
|
||||
gsd_run query generate-claude-profile --analysis "$ANALYSIS_PATH" --json
|
||||
```
|
||||
|
||||
Display: "✓ Added profile section to CLAUDE.md"
|
||||
|
||||
**For Global CLAUDE.md (if selected):**
|
||||
|
||||
```bash
|
||||
gsd_run query generate-claude-profile --analysis "$ANALYSIS_PATH" --global --json
|
||||
```
|
||||
|
||||
Display: "✓ Added profile section to $HOME/.claude/CLAUDE.md"
|
||||
|
||||
**Error handling:** If any `gsd-tools.cjs query` or gsd-tools.cjs call fails, display the error message and use AskUserQuestion to offer "Retry" or "Skip this artifact". On retry, re-run the command. On skip, continue to next artifact.
|
||||
|
||||
---
|
||||
|
||||
## 10. Summary & Refresh Diff
|
||||
|
||||
**If --refresh path:**
|
||||
|
||||
Read both old backup and new analysis to compare dimension ratings/confidence.
|
||||
|
||||
Read the backed-up profile:
|
||||
```bash
|
||||
BACKUP_PATH="$HOME/.claude/USER-PROFILE.backup.md"
|
||||
```
|
||||
|
||||
Compare each dimension's rating and confidence between old and new. Display diff table showing only changed dimensions:
|
||||
|
||||
```
|
||||
## Changes
|
||||
|
||||
| Dimension | Before | After |
|
||||
|-----------------|-----------------------------|-----------------------------|
|
||||
| Communication | terse-direct (LOW) | detailed-structured (HIGH) |
|
||||
| Debugging | fix-first (MEDIUM) | hypothesis-driven (MEDIUM) |
|
||||
```
|
||||
|
||||
If nothing changed: Display "No changes detected -- your profile is already up to date."
|
||||
|
||||
**Display final summary:**
|
||||
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD > PROFILE COMPLETE ✓
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Your profile: $HOME/.claude/gsd-core/USER-PROFILE.md
|
||||
```
|
||||
|
||||
Then list paths for each generated artifact:
|
||||
```
|
||||
Artifacts:
|
||||
✓ /gsd-dev-preferences $HOME/.claude/skills/gsd-dev-preferences/SKILL.md
|
||||
✓ CLAUDE.md section ./CLAUDE.md
|
||||
✓ Global CLAUDE.md $HOME/.claude/CLAUDE.md
|
||||
```
|
||||
|
||||
(Only show artifacts that were actually generated.)
|
||||
|
||||
**Clean up temp files:**
|
||||
|
||||
Remove the temp directory created by profile-sample (contains sample JSONL and analysis JSON):
|
||||
```bash
|
||||
rm -rf "$TEMP_DIR"
|
||||
```
|
||||
|
||||
Also remove any standalone temp files created for questionnaire answers:
|
||||
```bash
|
||||
rm -f "$ANSWERS_PATH" 2>/dev/null
|
||||
rm -f "$ANALYSIS_PATH" 2>/dev/null
|
||||
```
|
||||
|
||||
(Only clean up temp paths that were actually created during this workflow run.)
|
||||
|
||||
</process>
|
||||
|
||||
<success_criteria>
|
||||
- [ ] Initialization detects existing profile and handles all three responses (view/refresh/cancel)
|
||||
- [ ] Consent gate shown for session analysis path, skipped for questionnaire path
|
||||
- [ ] Session scan discovers sessions and reports statistics
|
||||
- [ ] Session analysis path: samples messages, spawns profiler agent, extracts analysis JSON
|
||||
- [ ] Questionnaire path: presents 8 questions, collects answers, converts to analysis JSON
|
||||
- [ ] Split resolution presents context-dependent splits with user resolution options
|
||||
- [ ] Profile written to USER-PROFILE.md via write-profile subcommand
|
||||
- [ ] Result display shows report card table and highlight reel with evidence
|
||||
- [ ] Artifact selection uses multiSelect with all options pre-selected
|
||||
- [ ] Artifacts generated sequentially via gsd-tools.cjs query (or gsd-tools.cjs) subcommands
|
||||
- [ ] Refresh diff shows changed dimensions when --refresh was used
|
||||
- [ ] Temp files cleaned up on completion
|
||||
</success_criteria>
|
||||
Reference in New Issue
Block a user