From 594c7e1a4d1e794f8c44f3405fb1f6df120ef1f8 Mon Sep 17 00:00:00 2001 From: seekee421 Date: Fri, 13 Mar 2026 14:14:09 +0800 Subject: [PATCH] install: default jj setup in one-click flow --- README.md | 97 +++++++++ ...2026-03-13-jj-default-installation-plan.md | 188 ++++++++++++++++++ install/install.ps1 | 140 ++++++++++++- install/install.sh | 125 +++++++++++- skills/gitea-issue-devops-agent/SKILL.md | 1 + .../references/jj-default-usage.md | 170 ++++++++++++++++ 6 files changed, 711 insertions(+), 10 deletions(-) create mode 100644 docs/superpowers/plans/2026-03-13-jj-default-installation-plan.md create mode 100644 skills/gitea-issue-devops-agent/references/jj-default-usage.md diff --git a/README.md b/README.md index 2b819f1..ca34eac 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ ## 一键安装 +安装器现在会先安装 skill,再默认尝试安装 `jj`。 +如果 `jj` 因本机环境、包管理器或网络原因安装失败,安装器不会失败,只会给出手动安装提示。 + ### Linux ```bash @@ -55,6 +58,41 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://fun-md - `~/.codex/skills/gitea-issue-devops-agent` +默认 `jj` 安装顺序: + +- Linux / macOS:`brew -> cargo-binstall -> cargo` +- Windows:`winget -> scoop -> cargo` + +安装控制项: + +### Bash + +```bash +INSTALL_JJ=0 +JJ_INSTALL_METHOD=auto|brew|binstall|cargo +JJ_CHANNEL=release|prerelease +``` + +### PowerShell + +```powershell +$env:INSTALL_JJ='0' +$env:JJ_INSTALL_METHOD='auto' # 或 winget / scoop / cargo +$env:JJ_CHANNEL='release' # 或 prerelease +``` + +验证命令: + +```bash +jj --version +jj config set --user user.name "Your Name" +jj config set --user user.email "you@example.com" +``` + +详细说明: + +- `skills/gitea-issue-devops-agent/references/jj-default-usage.md` + ## 工具使用说明 ### issue_audit.py @@ -97,6 +135,11 @@ python skills/gitea-issue-devops-agent/scripts/preview_slot_allocator.py --state - `issue` 或固定 issue 触发来源 - 可选:`target_base`、`plan_path`、`reviewers`、`test_entry`、`deploy_env`、`health_endpoint`、`min_quality_score`、`jj_policy` +推荐默认值: + +- `jj_policy=optional-internal` +- 先固定 issue,再进入 `Plan -> Draft PR -> 提测 -> 人工确认合并` + ### Claude Code Skills 目录(官方支持): @@ -161,6 +204,14 @@ api_key= mode=manual ``` +## `jj` 在工作流中的定位 + +默认安装 `jj`,但不要求非工程角色理解 `jj`。 + +- 对外:继续使用 `issue / git branch / PR / CI/CD / review apps` +- 对内:用 `jj` 承担本地执行、回退、并行 workspace、变更重写 +- 原则:`jj` 是内部可靠性增强层,不替代你们对外的 Git/Gitea 协作界面 + ## `skills` 命令参数释义(重点补充) > 本节把“`skills` 命令”统一理解为:在 Claude/Codex/OpenCode 中显式调用 `gitea-issue-devops-agent` 时提交的参数块。 @@ -213,6 +264,14 @@ min_quality_score=70 适用:问题描述完整、团队希望最大化自动化吞吐。 +典型流程: + +1. 人工在 Gitea 选中 issue。 +2. MajorAgent 生成 Plan 并创建分支、Draft PR。 +3. SubAgent 只读取必要上下文并修改计划内路径。 +4. TestAgent 跑单测、集成测试、issue 级 e2e。 +5. 通过后进入 preview slot 和人工复核。 + #### 场景 2:生产敏感仓库,人工确认每一步 ```text @@ -227,6 +286,13 @@ health_endpoint: /healthz 适用:高风险改动、强合规流程、需要逐步确认分支/提交/提测/关闭。 +典型流程: + +1. 先生成 Plan。 +2. 每次代码改动前都确认允许范围。 +3. 提测、回写 issue、关闭 issue、最终 merge 都要人工确认。 +4. 如 AI 偏航,可用 `jj` 做本地回退而不破坏外部 PR。 + #### 场景 3:半自动协作,先评审后提测 ```text @@ -243,6 +309,13 @@ preview_slots=preview-a,preview-b,preview-c 适用:多人协作项目,需要评审人显式批准后再进入提测和环境分配。 +典型流程: + +1. AI 先产出初始 Draft PR。 +2. 工程师在 AI 编码工具里继续白盒调整。 +3. reviewer 回复 `review-approved` 后才进入提测。 +4. maintainer 最后确认 merge。 + #### 场景 4:仅文档改动或轻量改动,资源最省策略 ```text @@ -251,10 +324,34 @@ preview_slots=preview-a,preview-b,preview-c 配合 `change_scope.py` 可自动得到 `skip` 或 `client_only`,避免不必要的服务端重启和环境开销。 +#### 场景 5:多 Agent 并行,但上下文不脑裂 + +```text +issue=48 +mode=semi-automatic +jj_policy=optional-internal +plan_path=.tmp/devops-plans/devops-skills__issue-48.md +``` + +典型流程: + +1. MajorAgent 只负责 issue 语义分析和 Plan。 +2. SubAgent 只负责修改代码。 +3. TestAgent 在独立 `jj workspace` 里验证。 +4. 人工 reviewer 再决定是否继续迭代或合并。 + +适用:长流程、多角色协作、希望降低 token 消耗和上下文漂移。 + ## 技能路径 - `skills/gitea-issue-devops-agent/SKILL.md` +## 核心文档 + +- `skills/gitea-issue-devops-agent/references/issue-template-standard.md` +- `skills/gitea-issue-devops-agent/references/plan-template.md` +- `skills/gitea-issue-devops-agent/references/jj-default-usage.md` + ## 核心脚本 - `skills/gitea-issue-devops-agent/scripts/issue_audit.py` diff --git a/docs/superpowers/plans/2026-03-13-jj-default-installation-plan.md b/docs/superpowers/plans/2026-03-13-jj-default-installation-plan.md new file mode 100644 index 0000000..24af17d --- /dev/null +++ b/docs/superpowers/plans/2026-03-13-jj-default-installation-plan.md @@ -0,0 +1,188 @@ +# Jj Default Installation Implementation Plan + +> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make `jj` a default installation target in this repository's one-command installers without making installer success depend on `jj` success, and expand documentation with clearer usage instructions and scenario-based examples. + +**Architecture:** Keep the public installer entrypoints unchanged while adding an internal second phase that attempts platform-appropriate `jj` installation. Preserve deterministic skill installation first, then run best-effort `jj` installation with explicit verification and manual fallback instructions. + +**Tech Stack:** Bash, PowerShell, Git, README Markdown, skill reference docs + +--- + +## Chunk 1: Installer Behavior + +### Task 1: Add plan-aware installer controls to the Bash installer + +**Files:** +- Modify: `install/install.sh` +- Test: `install/install.sh` syntax via `bash -n` + +- [ ] **Step 1: Define installer controls** + +Add environment-driven controls near the top of `install/install.sh`: +- `INSTALL_JJ` default `1` +- `JJ_INSTALL_METHOD` default `auto` +- `JJ_CHANNEL` default `release` + +- [ ] **Step 2: Add `jj` install attempt helpers** + +Implement focused functions for: +- logging +- command existence checks +- `brew` install path +- `cargo-binstall` install path +- `cargo install` fallback path +- manual fallback message + +- [ ] **Step 3: Add OS-aware default attempt flow** + +Implement this order: +- macOS: `brew`, then `cargo-binstall`, then `cargo` +- Linux: `brew` if available, then `cargo-binstall`, then `cargo` + +- [ ] **Step 4: Keep skill installation authoritative** + +Ensure the script: +- installs the skill first +- attempts `jj` only after the skill copy succeeds +- never exits non-zero only because `jj` failed + +- [ ] **Step 5: Verify shell syntax** + +Run: `bash -n install/install.sh` +Expected: no output, zero exit code + +### Task 2: Add plan-aware installer controls to the PowerShell installer + +**Files:** +- Modify: `install/install.ps1` +- Test: `install/install.ps1` parse check via PowerShell + +- [ ] **Step 1: Define parameters and defaults** + +Add parameters: +- `SkipJj` +- `JjInstallMethod = "auto"` +- `JjChannel = "release"` + +- [ ] **Step 2: Add `jj` install attempt helpers** + +Implement functions for: +- logging +- command existence checks +- `winget` install path +- `scoop` install path +- `cargo install` fallback path +- manual fallback message + +- [ ] **Step 3: Add Windows attempt flow** + +Implement this order: +- `winget` +- `scoop` +- `cargo` + +- [ ] **Step 4: Keep installer non-blocking for `jj`** + +Ensure skill installation still succeeds even if all `jj` attempts fail. + +- [ ] **Step 5: Verify script parses** + +Run: `powershell -NoProfile -Command "[void][scriptblock]::Create((Get-Content -Raw 'install/install.ps1'))"` +Expected: no output, zero exit code + +## Chunk 2: Documentation + +### Task 3: Expand README installation and usage guidance + +**Files:** +- Modify: `README.md` + +- [ ] **Step 1: Update one-command install sections** + +Document that installers now: +- install the skill +- attempt `jj` by default +- continue with warnings if `jj` cannot be installed automatically + +- [ ] **Step 2: Add installer controls and verification** + +Document: +- `INSTALL_JJ=0` +- `JJ_INSTALL_METHOD` +- `JJ_CHANNEL` +- PowerShell equivalents +- `jj --version` +- initial `jj config` commands + +- [ ] **Step 3: Add richer scenario examples** + +Include examples for: +- first-time team setup +- automatic bug fix flow +- semi-automatic engineering review flow +- manual hotfix flow +- multi-agent flow with `jj` workspaces + +### Task 4: Add detailed `jj` usage guide + +**Files:** +- Create: `skills/gitea-issue-devops-agent/references/jj-default-usage.md` + +- [ ] **Step 1: Explain repository policy** + +Document: +- `jj` is default to install +- `jj` is internal execution infrastructure +- Git branches/PRs/CI remain public system of record + +- [ ] **Step 2: Explain verification and fallback** + +Document: +- how to verify installation +- how to skip or force methods +- what to do when package managers are unavailable + +- [ ] **Step 3: Add workflow examples** + +Provide concrete examples for: +- issue -> plan -> draft PR +- engineer review after initial AI PR +- `jj workspace` for TestAgent and human reviewer +- rollback with operation log + +## Chunk 3: Verification and Delivery + +### Task 5: Verify, commit, and push + +**Files:** +- Modify: repo index and git history + +- [ ] **Step 1: Run syntax checks** + +Run: +- `bash -n install/install.sh` +- `powershell -NoProfile -Command "[void][scriptblock]::Create((Get-Content -Raw 'install/install.ps1'))"` + +Expected: both succeed + +- [ ] **Step 2: Review diff** + +Run: `git diff --check` +Expected: no diff formatting errors + +- [ ] **Step 3: Commit** + +Run: +```bash +git add README.md install/install.sh install/install.ps1 docs/superpowers/plans/2026-03-13-jj-default-installation-plan.md skills/gitea-issue-devops-agent/references/jj-default-usage.md +git commit -m "docs: default jj installation in installers" +``` + +- [ ] **Step 4: Push** + +Run: +```bash +git push origin main +``` diff --git a/install/install.ps1 b/install/install.ps1 index 69ea277..821aecb 100644 --- a/install/install.ps1 +++ b/install/install.ps1 @@ -1,6 +1,11 @@ param( [string]$RepoUrl = "https://fun-md.com/Fun_MD/devops-skills.git", - [string]$CodexHome = "$HOME\.codex" + [string]$CodexHome = "$HOME\.codex", + [switch]$SkipJj, + [ValidateSet("auto", "winget", "scoop", "cargo")] + [string]$JjInstallMethod = $(if ($env:JJ_INSTALL_METHOD) { $env:JJ_INSTALL_METHOD } else { "auto" }), + [ValidateSet("release", "prerelease")] + [string]$JjChannel = $(if ($env:JJ_CHANNEL) { $env:JJ_CHANNEL } else { "release" }) ) $ErrorActionPreference = "Stop" @@ -8,13 +13,136 @@ $ErrorActionPreference = "Stop" $skillName = "gitea-issue-devops-agent" $targetDir = Join-Path $CodexHome "skills\$skillName" $tmpRoot = Join-Path $env:TEMP ("devops-skills-" + [Guid]::NewGuid().ToString("N")) +$installJj = $true +if ($SkipJj.IsPresent) { + $installJj = $false +} +if ($env:INSTALL_JJ -and $env:INSTALL_JJ -eq "0") { + $installJj = $false +} + +function Write-InstallLog { + param([string]$Message) + Write-Host "[install] $Message" +} + +function Write-InstallWarn { + param([string]$Message) + Write-Warning "[install] $Message" +} + +function Test-CommandAvailable { + param([string]$Name) + return $null -ne (Get-Command $Name -ErrorAction SilentlyContinue) +} + +function Show-JjManualHelp { + Write-InstallWarn "jj was not installed automatically." + Write-InstallWarn "Manual options:" + Write-InstallWarn " - winget install jj-vcs.jj" + Write-InstallWarn " - scoop install main/jj" + if ($JjChannel -eq "prerelease") { + Write-InstallWarn " - cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli" + } + else { + Write-InstallWarn " - cargo install --locked --bin jj jj-cli" + } + Write-InstallWarn "After installation, verify with: jj --version" +} + +function Install-JjWithWinget { + if (-not (Test-CommandAvailable winget)) { + return $false + } + if ($JjChannel -ne "release") { + Write-InstallWarn "winget path skipped because prerelease jj is requested." + return $false + } + + Write-InstallLog "attempting jj installation via winget" + & winget install --id jj-vcs.jj -e --accept-source-agreements --accept-package-agreements + return $LASTEXITCODE -eq 0 +} + +function Install-JjWithScoop { + if (-not (Test-CommandAvailable scoop)) { + return $false + } + if ($JjChannel -ne "release") { + Write-InstallWarn "scoop path skipped because prerelease jj is requested." + return $false + } + + Write-InstallLog "attempting jj installation via scoop" + & scoop install main/jj + return $LASTEXITCODE -eq 0 +} + +function Install-JjWithCargo { + if (-not (Test-CommandAvailable cargo)) { + return $false + } + + Write-InstallLog "attempting jj installation via cargo" + if ($JjChannel -eq "prerelease") { + & cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli + } + else { + & cargo install --locked --bin jj jj-cli + } + return $LASTEXITCODE -eq 0 +} + +function Invoke-JjInstall { + if (-not $installJj) { + Write-InstallLog "skipping jj installation because INSTALL_JJ=0 or -SkipJj was provided" + return + } + + if (Test-CommandAvailable jj) { + Write-InstallLog "jj already installed: $(& jj --version)" + return + } + + $installed = $false + switch ($JjInstallMethod) { + "auto" { + $installed = (Install-JjWithWinget) -or (Install-JjWithScoop) -or (Install-JjWithCargo) + break + } + "winget" { + $installed = Install-JjWithWinget + break + } + "scoop" { + $installed = Install-JjWithScoop + break + } + "cargo" { + $installed = Install-JjWithCargo + break + } + } + + if (-not $installed) { + Show-JjManualHelp + return + } + + if (Test-CommandAvailable jj) { + Write-InstallLog "jj installation succeeded: $(& jj --version)" + } + else { + Show-JjManualHelp + } +} try { - if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + if (-not (Test-CommandAvailable git)) { throw "[install] git is required but not found." } - Write-Host "[install] downloading $skillName from $RepoUrl" + Write-InstallLog "downloading $skillName from $RepoUrl" git clone --depth 1 $RepoUrl $tmpRoot | Out-Null $sourceDir = Join-Path $tmpRoot "skills\$skillName" @@ -28,8 +156,10 @@ try { } Copy-Item -Path $sourceDir -Destination $targetDir -Recurse -Force - Write-Host "[install] done" - Write-Host "[install] installed path: $targetDir" + Write-InstallLog "skill installed" + Write-InstallLog "installed path: $targetDir" + Invoke-JjInstall + Write-InstallLog "done" } finally { if (Test-Path $tmpRoot) { diff --git a/install/install.sh b/install/install.sh index c22d7db..0f18af4 100644 --- a/install/install.sh +++ b/install/install.sh @@ -6,6 +6,119 @@ SKILL_NAME="gitea-issue-devops-agent" CODEX_HOME="${CODEX_HOME:-$HOME/.codex}" TARGET_DIR="${CODEX_HOME}/skills/${SKILL_NAME}" TMP_DIR="$(mktemp -d)" +INSTALL_JJ="${INSTALL_JJ:-1}" +JJ_INSTALL_METHOD="${JJ_INSTALL_METHOD:-auto}" +JJ_CHANNEL="${JJ_CHANNEL:-release}" + +log() { + echo "[install] $*" +} + +warn() { + echo "[install] warning: $*" >&2 +} + +manual_jj_help() { + warn "jj was not installed automatically." + warn "Manual options:" + warn " - Homebrew: brew install jj" + warn " - cargo-binstall: cargo binstall --strategies crate-meta-data jj-cli" + if [ "$JJ_CHANNEL" = "prerelease" ]; then + warn " - cargo prerelease: cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli" + else + warn " - cargo release: cargo install --locked --bin jj jj-cli" + fi + warn "After installation, verify with: jj --version" +} + +install_jj_with_brew() { + if ! command -v brew >/dev/null 2>&1; then + return 1 + fi + if [ "$JJ_CHANNEL" != "release" ]; then + warn "brew path skipped because prerelease jj is requested." + return 1 + fi + + log "attempting jj installation via Homebrew" + brew install jj +} + +install_jj_with_binstall() { + if ! command -v cargo >/dev/null 2>&1 || ! command -v cargo-binstall >/dev/null 2>&1; then + return 1 + fi + if [ "$JJ_CHANNEL" != "release" ]; then + warn "cargo-binstall path skipped because prerelease jj is requested." + return 1 + fi + + log "attempting jj installation via cargo-binstall" + cargo binstall --strategies crate-meta-data jj-cli +} + +install_jj_with_cargo() { + if ! command -v cargo >/dev/null 2>&1; then + return 1 + fi + + log "attempting jj installation via cargo" + if [ "$JJ_CHANNEL" = "prerelease" ]; then + cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli + else + cargo install --locked --bin jj jj-cli + fi +} + +attempt_jj_install() { + if [ "$INSTALL_JJ" = "0" ]; then + log "skipping jj installation because INSTALL_JJ=0" + return 0 + fi + + if command -v jj >/dev/null 2>&1; then + log "jj already installed: $(jj --version)" + return 0 + fi + + case "$JJ_INSTALL_METHOD" in + auto) + install_jj_with_brew || install_jj_with_binstall || install_jj_with_cargo || { + manual_jj_help + return 0 + } + ;; + brew) + install_jj_with_brew || { + manual_jj_help + return 0 + } + ;; + binstall) + install_jj_with_binstall || { + manual_jj_help + return 0 + } + ;; + cargo) + install_jj_with_cargo || { + manual_jj_help + return 0 + } + ;; + *) + warn "unsupported JJ_INSTALL_METHOD='$JJ_INSTALL_METHOD'; skipping jj install." + manual_jj_help + return 0 + ;; + esac + + if command -v jj >/dev/null 2>&1; then + log "jj installation succeeded: $(jj --version)" + else + manual_jj_help + fi +} cleanup() { rm -rf "$TMP_DIR" @@ -13,15 +126,15 @@ cleanup() { trap cleanup EXIT if ! command -v git >/dev/null 2>&1; then - echo "[install] git is required but not found." + log "git is required but not found." exit 1 fi -echo "[install] downloading ${SKILL_NAME} from ${REPO_URL}" +log "downloading ${SKILL_NAME} from ${REPO_URL}" git clone --depth 1 "$REPO_URL" "$TMP_DIR/repo" >/dev/null 2>&1 if [ ! -d "$TMP_DIR/repo/skills/${SKILL_NAME}" ]; then - echo "[install] skill directory not found in repository." + log "skill directory not found in repository." exit 1 fi @@ -29,5 +142,7 @@ mkdir -p "${CODEX_HOME}/skills" rm -rf "$TARGET_DIR" cp -R "$TMP_DIR/repo/skills/${SKILL_NAME}" "$TARGET_DIR" -echo "[install] done" -echo "[install] installed path: ${TARGET_DIR}" +log "skill installed" +log "installed path: ${TARGET_DIR}" +attempt_jj_install +log "done" diff --git a/skills/gitea-issue-devops-agent/SKILL.md b/skills/gitea-issue-devops-agent/SKILL.md index 81f48ab..ea85f4a 100644 --- a/skills/gitea-issue-devops-agent/SKILL.md +++ b/skills/gitea-issue-devops-agent/SKILL.md @@ -414,6 +414,7 @@ Use `jj` only under these rules: - `references/triage-standard.md`: scoring rubric and templates for needs-info, review request, test submission, and merge approval. - `references/issue-template-standard.md`: standard issue templates for `bug`, `enhancement`, and `feature`. - `references/plan-template.md`: default plan structure and status machine for MajorAgent/SubAgent/TestAgent handoff. +- `references/jj-default-usage.md`: default `jj` installation strategy, verification, and scenario-based usage guidance. ## Operational Constraints diff --git a/skills/gitea-issue-devops-agent/references/jj-default-usage.md b/skills/gitea-issue-devops-agent/references/jj-default-usage.md new file mode 100644 index 0000000..bfecb2e --- /dev/null +++ b/skills/gitea-issue-devops-agent/references/jj-default-usage.md @@ -0,0 +1,170 @@ +# Jj Default Installation and Usage + +This repository installs the `gitea-issue-devops-agent` skill first, then attempts to install `jj` by default. + +`jj` is the internal execution layer for agent reliability. Git branches, PRs, CI/CD pipelines, and merge approvals remain the external system of record. + +## Default Install Strategy + +The one-command installers now behave like this: + +1. Install the skill into the target Codex directory. +2. Check whether `jj` is already available. +3. If not, try OS-specific install methods. +4. If all methods fail, keep the skill installed and print manual fallback instructions. + +## OS-Specific Attempt Order + +### Linux + +- `brew install jj` +- `cargo binstall --strategies crate-meta-data jj-cli` +- `cargo install --locked --bin jj jj-cli` + +For prerelease: + +- `cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli` + +### macOS + +- `brew install jj` +- `cargo binstall --strategies crate-meta-data jj-cli` +- `cargo install --locked --bin jj jj-cli` + +For prerelease: + +- `cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli` + +### Windows + +- `winget install jj-vcs.jj` +- `scoop install main/jj` +- `cargo install --locked --bin jj jj-cli` + +For prerelease: + +- `cargo install --git https://github.com/jj-vcs/jj.git --locked --bin jj jj-cli` + +## Installer Controls + +### Bash installers + +- `INSTALL_JJ=0`: skip `jj` installation +- `JJ_INSTALL_METHOD=auto|brew|binstall|cargo` +- `JJ_CHANNEL=release|prerelease` + +Example: + +```bash +INSTALL_JJ=0 curl -fsSL https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.sh | bash +``` + +```bash +JJ_INSTALL_METHOD=cargo JJ_CHANNEL=prerelease curl -fsSL https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.sh | bash +``` + +### PowerShell installers + +With the one-liner, prefer environment variables: + +- `$env:INSTALL_JJ='0'` +- `$env:JJ_INSTALL_METHOD='auto'|'winget'|'scoop'|'cargo'` +- `$env:JJ_CHANNEL='release'|'prerelease'` + +Example: + +```powershell +$env:JJ_INSTALL_METHOD='winget' +iwr -useb https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.ps1 | iex +``` + +```powershell +$env:INSTALL_JJ='0' +iwr -useb https://fun-md.com/Fun_MD/devops-skills/raw/branch/main/install/install.ps1 | iex +``` + +If you save the script locally first, you can also use the `-SkipJj`, `-JjInstallMethod`, and `-JjChannel` parameters directly. + +## Verification + +After installation: + +```bash +jj --version +``` + +Set identity: + +```bash +jj config set --user user.name "Your Name" +jj config set --user user.email "you@example.com" +``` + +Optional shell completion: + +```bash +source <(jj util completion bash) +``` + +PowerShell completion: + +```powershell +jj util completion power-shell | Out-String | Invoke-Expression +``` + +## Working Model + +Use `jj` as an internal operator tool: + +- issue selection, branch naming, PR creation, CI, and merge stay Git/Gitea-native +- `jj` handles local history rewrites, workspace isolation, and recovery +- each issue branch can map to one `jj` bookmark + +## Scenario Examples + +### 1) First-Time Team Setup + +1. Run the one-command installer. +2. Verify `jj --version`. +3. Configure `user.name` and `user.email`. +4. Start with one fixed issue in `manual` or `semi-automatic` mode. + +Recommended when a team is new to AI-assisted delivery and wants controlled adoption. + +### 2) Initial AI PR for a Bug + +1. Human selects issue `#48`. +2. MajorAgent creates the plan. +3. Issue branch and draft PR are created. +4. SubAgent changes only the planned paths. +5. TestAgent validates build, targeted tests, and issue e2e. +6. Engineer reviews and refines before merge approval. + +Recommended default flow for day-to-day bug fixing. + +### 3) Semi-Automatic Review Flow + +1. AI produces the initial draft PR. +2. Reviewer inspects the plan, diff scope, and evidence. +3. Engineer uses the AI coding tool for follow-up edits if needed. +4. Only after review approval does the branch enter preview-slot testing. + +Recommended when engineering review must happen before environment allocation. + +### 4) Human + TestAgent Parallel Verification with Workspaces + +1. SubAgent works in the main issue workspace. +2. TestAgent creates a separate `jj workspace` for validation. +3. Human reviewer can create another workspace for white-box adjustments. +4. All three flows remain tied to the same issue branch and plan. + +Recommended for larger issues where testing and code refinement happen in parallel. + +### 5) Recovery After AI Drift + +1. AI rewrites the change incorrectly or edits too broadly. +2. Engineer inspects `jj op log`. +3. Engineer uses `jj undo`, `jj op revert`, or `jj op restore`. +4. The issue branch and PR remain intact while local execution history is repaired. + +Recommended when AI behavior is fast but unreliable and quick recovery matters.