create-harness-btp 0.2.5 → 0.3.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 (81) hide show
  1. package/AI/VERSION +1 -1
  2. package/AI/agents/analyst.md +30 -0
  3. package/AI/agents/architect.md +29 -0
  4. package/AI/agents/backend-cap.md +19 -0
  5. package/AI/agents/deploy-cf.md +26 -0
  6. package/AI/agents/documentarian.md +20 -0
  7. package/AI/agents/e2e-fiori.md +62 -0
  8. package/AI/agents/frontend-ui5.md +20 -0
  9. package/AI/agents/harness-evolution.md +38 -0
  10. package/AI/agents/orchestrator.md +41 -0
  11. package/AI/agents/qa-review.md +28 -0
  12. package/AI/agents/researcher.md +29 -0
  13. package/AI/clients/claude/agents/analyst.md +22 -0
  14. package/AI/clients/claude/agents/architect.md +21 -0
  15. package/AI/clients/claude/agents/backend-cap.md +18 -0
  16. package/AI/clients/claude/agents/deploy-cf.md +25 -0
  17. package/AI/clients/claude/agents/documentarian.md +15 -0
  18. package/AI/clients/claude/agents/e2e-fiori.md +61 -0
  19. package/AI/clients/claude/agents/frontend-ui5.md +19 -0
  20. package/AI/clients/claude/agents/harness-evolution.md +37 -0
  21. package/AI/clients/claude/agents/orchestrator.md +40 -0
  22. package/AI/clients/claude/agents/qa-review.md +27 -0
  23. package/AI/clients/claude/agents/researcher.md +21 -0
  24. package/AI/clients/claude/commands/flow.md +16 -0
  25. package/AI/clients/claude/commands/verify.md +18 -0
  26. package/AI/clients/claude/skills/cap-cli/SKILL.md +21 -0
  27. package/AI/clients/claude/skills/cf-cli/SKILL.md +41 -0
  28. package/AI/clients/claude/skills/mta-build/SKILL.md +45 -0
  29. package/AI/clients/claude/skills/sap-verify/SKILL.md +27 -0
  30. package/AI/clients/copilot/agents/analyst.agent.md +22 -0
  31. package/AI/clients/copilot/agents/architect.agent.md +21 -0
  32. package/AI/clients/copilot/agents/backend-cap.agent.md +18 -0
  33. package/AI/clients/copilot/agents/deploy-cf.agent.md +25 -0
  34. package/AI/clients/copilot/agents/documentarian.agent.md +15 -0
  35. package/AI/clients/copilot/agents/e2e-fiori.agent.md +61 -0
  36. package/AI/clients/copilot/agents/frontend-ui5.agent.md +19 -0
  37. package/AI/clients/copilot/agents/harness-evolution.agent.md +37 -0
  38. package/AI/clients/copilot/agents/orchestrator.agent.md +40 -0
  39. package/AI/clients/copilot/agents/qa-review.agent.md +27 -0
  40. package/AI/clients/copilot/agents/researcher.agent.md +21 -0
  41. package/AI/clients/copilot/prompts/flow.prompt.md +16 -0
  42. package/AI/clients/copilot/prompts/verify.prompt.md +18 -0
  43. package/AI/clients/copilot/skills/cap-cli/SKILL.md +21 -0
  44. package/AI/clients/copilot/skills/cf-cli/SKILL.md +41 -0
  45. package/AI/clients/copilot/skills/mta-build/SKILL.md +45 -0
  46. package/AI/clients/copilot/skills/sap-verify/SKILL.md +27 -0
  47. package/AI/clients/cursor/commands/flow.md +12 -0
  48. package/AI/clients/cursor/commands/verify.md +14 -0
  49. package/AI/clients/cursor/skills/cap-cli/SKILL.md +21 -0
  50. package/AI/clients/cursor/skills/cf-cli/SKILL.md +41 -0
  51. package/AI/clients/cursor/skills/mta-build/SKILL.md +45 -0
  52. package/AI/clients/cursor/skills/sap-verify/SKILL.md +27 -0
  53. package/AI/clients/opencode/agents/analyst.md +29 -0
  54. package/AI/clients/opencode/agents/architect.md +28 -0
  55. package/AI/clients/opencode/agents/backend-cap.md +18 -0
  56. package/AI/clients/opencode/agents/deploy-cf.md +25 -0
  57. package/AI/clients/opencode/agents/documentarian.md +19 -0
  58. package/AI/clients/opencode/agents/e2e-fiori.md +61 -0
  59. package/AI/clients/opencode/agents/frontend-ui5.md +19 -0
  60. package/AI/clients/opencode/agents/harness-evolution.md +37 -0
  61. package/AI/clients/opencode/agents/orchestrator.md +40 -0
  62. package/AI/clients/opencode/agents/qa-review.md +27 -0
  63. package/AI/clients/opencode/agents/researcher.md +28 -0
  64. package/AI/clients/opencode/commands/flow.md +16 -0
  65. package/AI/clients/opencode/commands/verify.md +18 -0
  66. package/AI/clients/opencode/skills/cap-cli/SKILL.md +21 -0
  67. package/AI/clients/opencode/skills/cf-cli/SKILL.md +41 -0
  68. package/AI/clients/opencode/skills/mta-build/SKILL.md +45 -0
  69. package/AI/clients/opencode/skills/sap-verify/SKILL.md +27 -0
  70. package/AI/commands/flow.md +16 -0
  71. package/AI/commands/verify.md +18 -0
  72. package/AI/skills/cap-cli/SKILL.md +21 -0
  73. package/AI/skills/cf-cli/SKILL.md +41 -0
  74. package/AI/skills/mta-build/SKILL.md +45 -0
  75. package/AI/skills/sap-verify/SKILL.md +27 -0
  76. package/README.md +52 -18
  77. package/VERSION +1 -1
  78. package/bin/harness-btp.js +74 -28
  79. package/install.ps1 +72 -22
  80. package/install.sh +88 -28
  81. package/package.json +1 -1
package/install.ps1 CHANGED
@@ -1,13 +1,18 @@
1
1
  <# Instalador del harness BTP (idempotente, PowerShell 5.1).
2
- Uso: .\install.ps1 [-Dest "."] [-Force]
2
+ Uso: .\install.ps1 [-Dest "."] [-Force] [-Client auto]
3
3
  - Copia AI/ al proyecto destino (SKIP si ya existe; con -Force hace backup a AI.bak).
4
- - Fusiona AI/.opencode/{agents,commands,skills} en .opencode/ raíz (solo faltantes; con -Force hace backup a .opencode.bak).
4
+ - Fusiona el árbol del cliente agéntico desde AI/clients/<cliente>/ en la raíz
5
+ (solo faltantes; con -Force hace backup a <dir>.bak):
6
+ -Client auto (defecto): detecta por huellas (CLAUDE.md|.claude→claude,
7
+ .cursor→cursor, .github→copilot, opencode.json*|.opencode→opencode;
8
+ sin huellas→opencode) | all: todos | lista explícita (p. ej. claude,copilot).
5
9
  - Crea AGENTS.md raíz desde la plantilla solo si no existe.
6
10
  - Fusiona .gitignore con las líneas del fragmento (solo agrega faltantes).
7
11
  - NO toca package.json ni mta.yaml del proyecto. Sin secretos. #>
8
12
  param(
9
13
  [string]$Dest = ".",
10
- [switch]$Force
14
+ [switch]$Force,
15
+ $Client = "auto"
11
16
  )
12
17
 
13
18
  $ErrorActionPreference = "Stop"
@@ -50,35 +55,80 @@ if (Test-Path $AgentsDst) {
50
55
  Write-Output "CREATE: AGENTS.md (puntero a AI/AGENTS.md)"
51
56
  }
52
57
 
53
- $OpSrc = Join-Path $AiSrc ".opencode"
54
- $OpDst = Join-Path $Dest ".opencode"
55
- if (Test-Path $OpSrc) {
58
+ $ClientsSrc = Join-Path $AiSrc "clients"
59
+
60
+ function Get-ClientList($Spec, $DestDir) {
61
+ $s = (($Spec -join ",") + "").Trim().ToLower()
62
+ if ($s -eq "auto") {
63
+ $d = @()
64
+ if ((Test-Path (Join-Path $DestDir "CLAUDE.md")) -or (Test-Path (Join-Path $DestDir ".claude"))) { $d += "claude" }
65
+ if (Test-Path (Join-Path $DestDir ".cursor")) { $d += "cursor" }
66
+ if (Test-Path (Join-Path $DestDir ".github")) { $d += "copilot" }
67
+ $opHints = @(Get-ChildItem $DestDir -Filter "opencode.json*" -File -ErrorAction SilentlyContinue)
68
+ if (($opHints.Count -gt 0) -or (Test-Path (Join-Path $DestDir ".opencode"))) { $d += "opencode" }
69
+ if ($d.Count -eq 0) { $d = @("opencode") }
70
+ return $d
71
+ }
72
+ if ($s -eq "all") { return @("opencode", "claude", "cursor", "copilot") }
73
+ $list = @($s -split "," | ForEach-Object { $_.Trim().ToLower() } | Where-Object { $_ -ne "" })
74
+ $known = @("opencode", "claude", "cursor", "copilot", "aider")
75
+ foreach ($c in $list) {
76
+ if ($known -notcontains $c) { Write-Host "ABORT: cliente desconocido '$c' (usa auto|all|opencode,claude,cursor,copilot,aider)"; exit 1 }
77
+ }
78
+ if ($list.Count -eq 0) { Write-Host "ABORT: -Client vacío (usa auto|all|opencode,claude,cursor,copilot,aider)"; exit 1 }
79
+ return $list
80
+ }
81
+
82
+ function Merge-Tree($TreeSrc, $TreeDst, $Label) {
83
+ if (-not (Test-Path $TreeSrc)) { Write-Output "AVISO: no existe $TreeSrc (regenera con node scripts/render-clients.js)"; return }
84
+ $BakLabel = $Label.TrimEnd("/") + ".bak"
56
85
  if ($Force) {
57
- if (Test-Path $OpDst) {
58
- $OpBak = Join-Path $Dest ".opencode.bak"
59
- if (Test-Path $OpBak) { Remove-Item $OpBak -Recurse -Force }
60
- Rename-Item $OpDst ".opencode.bak"
61
- Write-Output "BACKUP: .opencode/ -> .opencode.bak"
86
+ if (Test-Path $TreeDst) {
87
+ $Bak = "$TreeDst.bak"
88
+ if (Test-Path $Bak) { Remove-Item $Bak -Recurse -Force }
89
+ Rename-Item $TreeDst ([IO.Path]::GetFileName($Bak))
90
+ Write-Output "BACKUP: $Label -> $BakLabel"
62
91
  }
63
- Copy-Item $OpSrc $OpDst -Recurse -Force
64
- $OpCount = @(Get-ChildItem $OpDst -Recurse -File).Count
65
- Write-Output ("CREATE: .opencode/ (+{0} archivos)" -f $OpCount)
92
+ Copy-Item $TreeSrc $TreeDst -Recurse -Force
93
+ $TreeCount = @(Get-ChildItem $TreeDst -Recurse -File).Count
94
+ Write-Output ("CREATE: {0} (+{1} archivos)" -f $Label, $TreeCount)
66
95
  } else {
67
- $OpCount = 0
68
- $OpFiles = @(Get-ChildItem $OpSrc -Recurse -File)
69
- foreach ($f in $OpFiles) {
70
- $rel = $f.FullName.Substring($OpSrc.Length + 1)
71
- $tgt = Join-Path $OpDst $rel
96
+ $TreeCount = 0
97
+ $TreeFiles = @(Get-ChildItem $TreeSrc -Recurse -File)
98
+ foreach ($f in $TreeFiles) {
99
+ $rel = $f.FullName.Substring($TreeSrc.Length + 1)
100
+ $tgt = Join-Path $TreeDst $rel
72
101
  if (Test-Path $tgt) {
73
- Write-Output ("SKIP: .opencode/{0} ya existe" -f ($rel -replace "\\","/"))
102
+ Write-Output ("SKIP: {0}{1} ya existe" -f $Label, ($rel -replace "\\","/"))
74
103
  } else {
75
104
  $tgtDir = Split-Path -Parent $tgt
76
105
  if (-not (Test-Path $tgtDir)) { New-Item $tgtDir -ItemType Directory -Force | Out-Null }
77
106
  Copy-Item $f.FullName $tgt -Force
78
- $OpCount++
107
+ $TreeCount++
79
108
  }
80
109
  }
81
- Write-Output ("CREATE: .opencode/ (+{0} archivos)" -f $OpCount)
110
+ Write-Output ("CREATE: {0} (+{1} archivos)" -f $Label, $TreeCount)
111
+ }
112
+ }
113
+
114
+ $SelectedClients = @(Get-ClientList $Client $Dest)
115
+ if ((($Client -join ",") + "").Trim().ToLower() -eq "auto") {
116
+ Write-Output ("CLIENT: auto -> {0}" -f ($SelectedClients -join ","))
117
+ }
118
+ foreach ($c in $SelectedClients) {
119
+ if ($c -eq "opencode") {
120
+ Merge-Tree (Join-Path $ClientsSrc "opencode") (Join-Path $Dest ".opencode") ".opencode/"
121
+ } elseif ($c -eq "claude") {
122
+ Merge-Tree (Join-Path $ClientsSrc "claude") (Join-Path $Dest ".claude") ".claude/"
123
+ } elseif ($c -eq "cursor") {
124
+ Merge-Tree (Join-Path $ClientsSrc "cursor\commands") (Join-Path $Dest ".cursor\commands") ".cursor/commands/"
125
+ Merge-Tree (Join-Path $ClientsSrc "cursor\skills") (Join-Path $Dest ".agents\skills") ".agents/skills/"
126
+ } elseif ($c -eq "copilot") {
127
+ Merge-Tree (Join-Path $ClientsSrc "copilot\agents") (Join-Path $Dest ".github\agents") ".github/agents/"
128
+ Merge-Tree (Join-Path $ClientsSrc "copilot\skills") (Join-Path $Dest ".github\skills") ".github/skills/"
129
+ Merge-Tree (Join-Path $ClientsSrc "copilot\prompts") (Join-Path $Dest ".github\prompts") ".github/prompts/"
130
+ } elseif ($c -eq "aider") {
131
+ Write-Output "SKIP: aider usa AGENTS.md raiz (nada que fusionar)"
82
132
  }
83
133
  }
84
134
 
package/install.sh CHANGED
@@ -1,20 +1,26 @@
1
1
  #!/bin/sh
2
2
  # Instalador del harness BTP (idempotente, POSIX sh).
3
- # Uso: ./install.sh [--dest <dir>] [--force] [--help]
3
+ # Uso: ./install.sh [--dest <dir>] [--force] [--client auto|all|opencode,claude,...] [--help]
4
4
  # Sin secretos. No toca package.json ni mta.yaml del proyecto.
5
- # Fusiona AI/.opencode/{agents,commands,skills} en .opencode/ raíz
6
- # (solo faltantes; con --force hace backup a .opencode.bak).
5
+ # Fusiona el árbol del cliente agéntico desde AI/clients/<cliente>/ en la raíz
6
+ # (solo faltantes; con --force hace backup a <dir>.bak).
7
+ # --client auto (defecto): detecta por huellas (CLAUDE.md|.claude→claude,
8
+ # .cursor→cursor, .github→copilot, opencode.json*|.opencode→opencode;
9
+ # sin huellas→opencode). all: todos. Lista explícita: esos.
7
10
  DEST="."
8
11
  FORCE=0
12
+ CLIENT="auto"
9
13
  while [ $# -gt 0 ]; do
10
14
  case "$1" in
11
15
  --dest) DEST="$2"; shift 2 ;;
12
16
  --force) FORCE=1; shift ;;
17
+ --client) CLIENT="$2"; shift 2 ;;
13
18
  -h|--help)
14
- echo "Uso: ./install.sh [--dest <dir>] [--force] [--help]"
15
- echo " --dest <dir> proyecto destino (por defecto: .)"
16
- echo " --force reinstala AI/ con backup a AI.bak"
17
- echo " -h, --help muestra esta ayuda"
19
+ echo "Uso: ./install.sh [--dest <dir>] [--force] [--client <clientes>] [--help]"
20
+ echo " --dest <dir> proyecto destino (por defecto: .)"
21
+ echo " --force reinstala AI/ con backup a AI.bak"
22
+ echo " --client <list> auto (defecto) | all | opencode,claude,cursor,copilot,aider"
23
+ echo " -h, --help muestra esta ayuda"
18
24
  exit 0 ;;
19
25
  *) echo "ABORT: opción desconocida $1 (usa --help)"; exit 1 ;;
20
26
  esac
@@ -45,33 +51,87 @@ else
45
51
  cp "$SRC/templates/AGENTS.pointer.md" "$DEST/AGENTS.md" && echo "CREATE: AGENTS.md (puntero a AI/AGENTS.md)"
46
52
  fi
47
53
 
48
- OP_SRC="$SRC/AI/.opencode"
49
- OP_DST="$DEST/.opencode"
50
- if [ -d "$OP_SRC" ]; then
54
+ # Fusion idempotente de un arbol: merge_tree <origen> <destino> <etiqueta>
55
+ # (etiqueta p. ej. ".opencode/"; el backup va a <destino>.bak).
56
+ merge_tree() {
57
+ MT_SRC="$1"; MT_DST="$2"; MT_LABEL="$3"
58
+ if [ ! -d "$MT_SRC" ]; then echo "AVISO: no existe $MT_SRC (regenera con node scripts/render-clients.js)"; return 0; fi
59
+ MT_BAKLABEL="$(printf '%s' "$MT_LABEL" | sed 's:/$::').bak"
51
60
  if [ "$FORCE" -eq 1 ]; then
52
- if [ -d "$OP_DST" ]; then
53
- rm -rf "$DEST/.opencode.bak" && mv "$DEST/.opencode" "$DEST/.opencode.bak"
54
- echo "BACKUP: .opencode/ -> .opencode.bak"
61
+ if [ -d "$MT_DST" ]; then
62
+ rm -rf "$MT_DST.bak" && mv "$MT_DST" "$MT_DST.bak"
63
+ echo "BACKUP: $MT_LABEL -> $MT_BAKLABEL"
55
64
  fi
56
- cp -r "$OP_SRC" "$OP_DST" && OP_COUNT=$(find "$OP_DST" -type f | wc -l) && echo "CREATE: .opencode/ (+$OP_COUNT archivos)"
65
+ mkdir -p "$(dirname "$MT_DST")"
66
+ cp -r "$MT_SRC" "$MT_DST" && MT_COUNT=$(find "$MT_DST" -type f | wc -l) && echo "CREATE: $MT_LABEL (+$MT_COUNT archivos)"
57
67
  else
58
- OP_COUNT=0
59
- OP_LIST="${TMPDIR:-/tmp}/harness-opcount-$$.tmp"
60
- find "$OP_SRC" -type f -print > "$OP_LIST"
61
- while IFS= read -r OP_FILE; do
62
- OP_REL=${OP_FILE#"$OP_SRC"/}
63
- if [ -f "$OP_DST/$OP_REL" ]; then
64
- echo "SKIP: .opencode/$OP_REL ya existe"
68
+ MT_COUNT=0
69
+ MT_LIST="${TMPDIR:-/tmp}/harness-mt-$$.tmp"
70
+ find "$MT_SRC" -type f -print > "$MT_LIST"
71
+ while IFS= read -r MT_FILE; do
72
+ MT_REL=${MT_FILE#"$MT_SRC"/}
73
+ if [ -f "$MT_DST/$MT_REL" ]; then
74
+ echo "SKIP: $MT_LABEL$MT_REL ya existe"
65
75
  else
66
- mkdir -p "$(dirname "$OP_DST/$OP_REL")"
67
- cp "$OP_FILE" "$OP_DST/$OP_REL"
68
- OP_COUNT=$((OP_COUNT + 1))
76
+ mkdir -p "$(dirname "$MT_DST/$MT_REL")"
77
+ cp "$MT_FILE" "$MT_DST/$MT_REL"
78
+ MT_COUNT=$((MT_COUNT + 1))
69
79
  fi
70
- done < "$OP_LIST"
71
- rm -f "$OP_LIST"
72
- echo "CREATE: .opencode/ (+$OP_COUNT archivos)"
80
+ done < "$MT_LIST"
81
+ rm -f "$MT_LIST"
82
+ echo "CREATE: $MT_LABEL (+$MT_COUNT archivos)"
73
83
  fi
74
- fi
84
+ }
85
+
86
+ # Resuelve la lista de clientes: detecta huellas en auto, valida explícitos.
87
+ resolve_clients() {
88
+ case "$CLIENT" in
89
+ auto)
90
+ RC_LIST=""
91
+ { [ -f "$DEST/CLAUDE.md" ] || [ -d "$DEST/.claude" ]; } && RC_LIST="$RC_LIST claude"
92
+ [ -d "$DEST/.cursor" ] && RC_LIST="$RC_LIST cursor"
93
+ [ -d "$DEST/.github" ] && RC_LIST="$RC_LIST copilot"
94
+ if ls "$DEST"/opencode.json* >/dev/null 2>&1 || [ -d "$DEST/.opencode" ]; then RC_LIST="$RC_LIST opencode"; fi
95
+ [ -z "$RC_LIST" ] && RC_LIST=" opencode"
96
+ echo "CLIENT: auto -> $(printf '%s' "$RC_LIST" | tr ' ' ',' | sed 's/^,//')" >&2
97
+ printf '%s' "$RC_LIST"
98
+ ;;
99
+ all) printf ' opencode claude cursor copilot' ;;
100
+ *)
101
+ RC_OUT=""
102
+ RC_REST="$CLIENT,"
103
+ while [ -n "$RC_REST" ]; do
104
+ RC_ONE=${RC_REST%%,*}; RC_REST=${RC_REST#*,}
105
+ RC_ONE=$(printf '%s' "$RC_ONE" | tr 'A-Z' 'a-z' | tr -d ' ')
106
+ [ -z "$RC_ONE" ] && continue
107
+ case "$RC_ONE" in
108
+ opencode|claude|cursor|copilot|aider) RC_OUT="$RC_OUT $RC_ONE" ;;
109
+ *) echo "ABORT: cliente desconocido '$RC_ONE' (usa auto|all|opencode,claude,cursor,copilot,aider)" >&2; exit 1 ;;
110
+ esac
111
+ done
112
+ [ -z "$RC_OUT" ] && { echo "ABORT: --client vacío (usa auto|all|opencode,claude,cursor,copilot,aider)" >&2; exit 1; }
113
+ printf '%s' "$RC_OUT"
114
+ ;;
115
+ esac
116
+ }
117
+
118
+ CLIENTS_SRC="$SRC/AI/clients"
119
+ RC_RESOLVED=$(resolve_clients); RC_STATUS=$?
120
+ if [ "$RC_STATUS" -ne 0 ]; then exit "$RC_STATUS"; fi
121
+ for C in $RC_RESOLVED; do
122
+ case "$C" in
123
+ opencode) merge_tree "$CLIENTS_SRC/opencode" "$DEST/.opencode" ".opencode/" ;;
124
+ claude) merge_tree "$CLIENTS_SRC/claude" "$DEST/.claude" ".claude/" ;;
125
+ cursor)
126
+ merge_tree "$CLIENTS_SRC/cursor/commands" "$DEST/.cursor/commands" ".cursor/commands/"
127
+ merge_tree "$CLIENTS_SRC/cursor/skills" "$DEST/.agents/skills" ".agents/skills/" ;;
128
+ copilot)
129
+ merge_tree "$CLIENTS_SRC/copilot/agents" "$DEST/.github/agents" ".github/agents/"
130
+ merge_tree "$CLIENTS_SRC/copilot/skills" "$DEST/.github/skills" ".github/skills/"
131
+ merge_tree "$CLIENTS_SRC/copilot/prompts" "$DEST/.github/prompts" ".github/prompts/" ;;
132
+ aider) echo "SKIP: aider usa AGENTS.md raiz (nada que fusionar)" ;;
133
+ esac
134
+ done
75
135
 
76
136
  FRAG="$SRC/AI/.gitignore.fragment"
77
137
  touch "$DEST/.gitignore"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-harness-btp",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "Instala el harness MVP SAP BTP como carpeta AI/ en cualquier proyecto",
5
5
  "keywords": ["sap-btp", "opencode", "harness", "agents", "scaffolder", "create"],
6
6
  "homepage": "https://github.com/horangelmillan/harness-btp#readme",