@unimatrix27/ralph-harness 1.0.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 (103) hide show
  1. package/CONTRIBUTING.md +89 -0
  2. package/README.md +401 -0
  3. package/dist/bin/ralph-bootstrap-aws.d.ts +3 -0
  4. package/dist/bin/ralph-bootstrap-aws.d.ts.map +1 -0
  5. package/dist/bin/ralph-bootstrap-aws.js +43 -0
  6. package/dist/bin/ralph-bootstrap-aws.js.map +1 -0
  7. package/dist/bin/ralph-fire.d.ts +3 -0
  8. package/dist/bin/ralph-fire.d.ts.map +1 -0
  9. package/dist/bin/ralph-fire.js +59 -0
  10. package/dist/bin/ralph-fire.js.map +1 -0
  11. package/dist/bin/ralph-gsm.d.ts +3 -0
  12. package/dist/bin/ralph-gsm.d.ts.map +1 -0
  13. package/dist/bin/ralph-gsm.js +93 -0
  14. package/dist/bin/ralph-gsm.js.map +1 -0
  15. package/dist/bin/ralph-orchestrate.d.ts +3 -0
  16. package/dist/bin/ralph-orchestrate.d.ts.map +1 -0
  17. package/dist/bin/ralph-orchestrate.js +20 -0
  18. package/dist/bin/ralph-orchestrate.js.map +1 -0
  19. package/dist/bin/ralph-sync-credential.d.ts +3 -0
  20. package/dist/bin/ralph-sync-credential.d.ts.map +1 -0
  21. package/dist/bin/ralph-sync-credential.js +44 -0
  22. package/dist/bin/ralph-sync-credential.js.map +1 -0
  23. package/dist/bin/ralph-sync-github-pat.d.ts +3 -0
  24. package/dist/bin/ralph-sync-github-pat.d.ts.map +1 -0
  25. package/dist/bin/ralph-sync-github-pat.js +93 -0
  26. package/dist/bin/ralph-sync-github-pat.js.map +1 -0
  27. package/dist/bin/ralph-tail-logs.d.ts +3 -0
  28. package/dist/bin/ralph-tail-logs.d.ts.map +1 -0
  29. package/dist/bin/ralph-tail-logs.js +72 -0
  30. package/dist/bin/ralph-tail-logs.js.map +1 -0
  31. package/dist/bin/ralph-validate-config.d.ts +3 -0
  32. package/dist/bin/ralph-validate-config.d.ts.map +1 -0
  33. package/dist/bin/ralph-validate-config.js +41 -0
  34. package/dist/bin/ralph-validate-config.js.map +1 -0
  35. package/dist/lib/aws-bootstrap.d.ts +53 -0
  36. package/dist/lib/aws-bootstrap.d.ts.map +1 -0
  37. package/dist/lib/aws-bootstrap.js +438 -0
  38. package/dist/lib/aws-bootstrap.js.map +1 -0
  39. package/dist/lib/aws-clients.d.ts +17 -0
  40. package/dist/lib/aws-clients.d.ts.map +1 -0
  41. package/dist/lib/aws-clients.js +25 -0
  42. package/dist/lib/aws-clients.js.map +1 -0
  43. package/dist/lib/claude-runner.d.ts +21 -0
  44. package/dist/lib/claude-runner.d.ts.map +1 -0
  45. package/dist/lib/claude-runner.js +101 -0
  46. package/dist/lib/claude-runner.js.map +1 -0
  47. package/dist/lib/credential-syncer.d.ts +27 -0
  48. package/dist/lib/credential-syncer.d.ts.map +1 -0
  49. package/dist/lib/credential-syncer.js +116 -0
  50. package/dist/lib/credential-syncer.js.map +1 -0
  51. package/dist/lib/ec2-orchestrator.d.ts +38 -0
  52. package/dist/lib/ec2-orchestrator.d.ts.map +1 -0
  53. package/dist/lib/ec2-orchestrator.js +469 -0
  54. package/dist/lib/ec2-orchestrator.js.map +1 -0
  55. package/dist/lib/env-loader.d.ts +18 -0
  56. package/dist/lib/env-loader.d.ts.map +1 -0
  57. package/dist/lib/env-loader.js +120 -0
  58. package/dist/lib/env-loader.js.map +1 -0
  59. package/dist/lib/fire-launcher.d.ts +59 -0
  60. package/dist/lib/fire-launcher.d.ts.map +1 -0
  61. package/dist/lib/fire-launcher.js +320 -0
  62. package/dist/lib/fire-launcher.js.map +1 -0
  63. package/dist/lib/gh-runner.d.ts +13 -0
  64. package/dist/lib/gh-runner.d.ts.map +1 -0
  65. package/dist/lib/gh-runner.js +50 -0
  66. package/dist/lib/gh-runner.js.map +1 -0
  67. package/dist/lib/github-state-mutator.d.ts +11 -0
  68. package/dist/lib/github-state-mutator.d.ts.map +1 -0
  69. package/dist/lib/github-state-mutator.js +179 -0
  70. package/dist/lib/github-state-mutator.js.map +1 -0
  71. package/dist/lib/phase-result-schemas.d.ts +88 -0
  72. package/dist/lib/phase-result-schemas.d.ts.map +1 -0
  73. package/dist/lib/phase-result-schemas.js +180 -0
  74. package/dist/lib/phase-result-schemas.js.map +1 -0
  75. package/dist/lib/post-hoc-agent-stuck-checker.d.ts +26 -0
  76. package/dist/lib/post-hoc-agent-stuck-checker.d.ts.map +1 -0
  77. package/dist/lib/post-hoc-agent-stuck-checker.js +142 -0
  78. package/dist/lib/post-hoc-agent-stuck-checker.js.map +1 -0
  79. package/dist/lib/prompt-renderer.d.ts +4 -0
  80. package/dist/lib/prompt-renderer.d.ts.map +1 -0
  81. package/dist/lib/prompt-renderer.js +30 -0
  82. package/dist/lib/prompt-renderer.js.map +1 -0
  83. package/dist/lib/security-runner.d.ts +7 -0
  84. package/dist/lib/security-runner.d.ts.map +1 -0
  85. package/dist/lib/security-runner.js +53 -0
  86. package/dist/lib/security-runner.js.map +1 -0
  87. package/dist/lib/structured-log-emitter.d.ts +53 -0
  88. package/dist/lib/structured-log-emitter.d.ts.map +1 -0
  89. package/dist/lib/structured-log-emitter.js +122 -0
  90. package/dist/lib/structured-log-emitter.js.map +1 -0
  91. package/dist/lib/target-config-schema.d.ts +28 -0
  92. package/dist/lib/target-config-schema.d.ts.map +1 -0
  93. package/dist/lib/target-config-schema.js +157 -0
  94. package/dist/lib/target-config-schema.js.map +1 -0
  95. package/dist/lib/user-data-renderer.d.ts +20 -0
  96. package/dist/lib/user-data-renderer.d.ts.map +1 -0
  97. package/dist/lib/user-data-renderer.js +75 -0
  98. package/dist/lib/user-data-renderer.js.map +1 -0
  99. package/lib/cloud-init/system-setup.sh +338 -0
  100. package/package.json +55 -0
  101. package/prompts/discovery.md +182 -0
  102. package/prompts/implementation.md +161 -0
  103. package/prompts/review.md +135 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-config-schema.js","sourceRoot":"","sources":["../../src/lib/target-config-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export declare const MODULE_PREFIX = "user-data-renderer";
2
+ export declare const USER_DATA_CAP_BYTES = 16384;
3
+ export declare class RawSizeExceededError extends Error {
4
+ readonly bytes: number;
5
+ constructor(bytes: number);
6
+ }
7
+ export interface UserDataInput {
8
+ targetRepo: string;
9
+ harnessVersion: string;
10
+ awsRegion: string;
11
+ logGroup: string;
12
+ githubTokenSsmKey: string;
13
+ claudeOauthSsmKey: string;
14
+ agentStuckLabel: string;
15
+ extraEnv?: Readonly<Record<string, string>>;
16
+ packageName?: string;
17
+ }
18
+ export declare function shellSingleQuote(value: string): string;
19
+ export declare function renderUserData(input: UserDataInput): string;
20
+ //# sourceMappingURL=user-data-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-data-renderer.d.ts","sourceRoot":"","sources":["../../src/lib/user-data-renderer.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAIlD,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,qBAAa,oBAAqB,SAAQ,KAAK;aACjB,KAAK,EAAE,MAAM;gBAAb,KAAK,EAAE,MAAM;CAM1C;AAED,MAAM,WAAW,aAAa;IAE5B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IAGxB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAG5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAOD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAqC3D"}
@@ -0,0 +1,75 @@
1
+ // user-data-renderer — renders the small inline bash stub that EC2 receives
2
+ // as user-data. Iteration 1 bundled the entire bash harness (`fire-launcher`
3
+ // + `ec2-orchestrator` + `cloud-init/bootstrap`) inline, which forced gzip
4
+ // compression to fit under the 16 KiB cap. Iteration 2 ships the harness via
5
+ // npm; the user-data shrinks to ~15 lines that install Node 24, install the
6
+ // harness package, then `exec ralph-orchestrate`.
7
+ //
8
+ // Cap-check: EC2's user-data cap is 16,384 bytes on the *raw* decoded
9
+ // payload — NOT on the base64 wire form, NOT on the gzipped bytes. PR #20
10
+ // and #21 (iteration 1) checked the gzipped size against this dimension,
11
+ // which let oversized payloads slip through when gzip happened to compress
12
+ // well. We check the raw rendered bytes here; the new stub is well under
13
+ // the cap so a `RawSizeExceeded` throw should be the equivalent of an
14
+ // assertion failure rather than a regular operating condition.
15
+ //
16
+ // Public surface:
17
+ // renderUserData(input) — returns the rendered bash string
18
+ // USER_DATA_CAP_BYTES — the EC2 16 KiB cap (raw bytes)
19
+ // RawSizeExceededError — thrown when the rendered output exceeds the cap
20
+ export const MODULE_PREFIX = "user-data-renderer";
21
+ // EC2 caps user-data at 16,384 raw decoded bytes. cf.
22
+ // docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html
23
+ export const USER_DATA_CAP_BYTES = 16_384;
24
+ export class RawSizeExceededError extends Error {
25
+ bytes;
26
+ constructor(bytes) {
27
+ super(`${MODULE_PREFIX}: rendered user-data is ${bytes} bytes, exceeds the EC2 cap of ${USER_DATA_CAP_BYTES} raw bytes`);
28
+ this.bytes = bytes;
29
+ this.name = "RawSizeExceededError";
30
+ }
31
+ }
32
+ const DEFAULT_PACKAGE_NAME = "@unimatrix27/ralph-harness";
33
+ // shellSingleQuote — wrap a value in POSIX single quotes, escaping any
34
+ // embedded `'` as `'\''`. Single-quoted strings are safe against every
35
+ // other shell metacharacter.
36
+ export function shellSingleQuote(value) {
37
+ return `'${value.replace(/'/g, `'\\''`)}'`;
38
+ }
39
+ export function renderUserData(input) {
40
+ const pkg = input.packageName ?? DEFAULT_PACKAGE_NAME;
41
+ // Build the export block deterministically — sorted keys keep the
42
+ // snapshot test stable across object literal reorders.
43
+ const baseEnv = {
44
+ RALPH_TARGET_REPO: input.targetRepo,
45
+ RALPH_AWS_REGION: input.awsRegion,
46
+ RALPH_LOG_GROUP: input.logGroup,
47
+ RALPH_GITHUB_TOKEN_SSM_KEY: input.githubTokenSsmKey,
48
+ RALPH_CLAUDE_OAUTH_SSM_KEY: input.claudeOauthSsmKey,
49
+ RALPH_AGENT_STUCK_LABEL: input.agentStuckLabel,
50
+ RALPH_HARNESS_VERSION: input.harnessVersion,
51
+ };
52
+ const merged = { ...baseEnv, ...(input.extraEnv ?? {}) };
53
+ const sortedKeys = Object.keys(merged).sort();
54
+ const exports = sortedKeys
55
+ .map((k) => `export ${k}=${shellSingleQuote(merged[k])}`)
56
+ .join("\n");
57
+ // 15-line target — keep this tight. Anything heavyweight goes in
58
+ // `lib/cloud-init/system-setup.sh` (shipped inside the npm package and
59
+ // invoked by `ralph-orchestrate` as its first step).
60
+ const stub = `#!/bin/bash
61
+ set -euo pipefail
62
+ exec > >(tee -a /var/log/ralph-user-data.log) 2>&1
63
+ ${exports}
64
+ curl -fsSL https://rpm.nodesource.com/setup_24.x | bash -
65
+ dnf install -y nodejs git jq awscli
66
+ npm install -g ${pkg}@${input.harnessVersion}
67
+ exec ralph-orchestrate
68
+ `;
69
+ const bytes = Buffer.byteLength(stub, "utf8");
70
+ if (bytes > USER_DATA_CAP_BYTES) {
71
+ throw new RawSizeExceededError(bytes);
72
+ }
73
+ return stub;
74
+ }
75
+ //# sourceMappingURL=user-data-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-data-renderer.js","sourceRoot":"","sources":["../../src/lib/user-data-renderer.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,4EAA4E;AAC5E,kDAAkD;AAClD,EAAE;AACF,sEAAsE;AACtE,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,sEAAsE;AACtE,+DAA+D;AAC/D,EAAE;AACF,kBAAkB;AAClB,oEAAoE;AACpE,kEAAkE;AAClE,mFAAmF;AAEnF,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD,sDAAsD;AACtD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAE1C,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACjB;IAA5B,YAA4B,KAAa;QACvC,KAAK,CACH,GAAG,aAAa,2BAA2B,KAAK,kCAAkC,mBAAmB,YAAY,CAClH,CAAC;QAHwB,UAAK,GAAL,KAAK,CAAQ;QAIvC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAmBD,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;AAE1D,uEAAuE;AACvE,uEAAuE;AACvE,6BAA6B;AAC7B,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAoB;IACjD,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,IAAI,oBAAoB,CAAC;IACtD,kEAAkE;IAClE,uDAAuD;IACvD,MAAM,OAAO,GAA2B;QACtC,iBAAiB,EAAE,KAAK,CAAC,UAAU;QACnC,gBAAgB,EAAE,KAAK,CAAC,SAAS;QACjC,eAAe,EAAE,KAAK,CAAC,QAAQ;QAC/B,0BAA0B,EAAE,KAAK,CAAC,iBAAiB;QACnD,0BAA0B,EAAE,KAAK,CAAC,iBAAiB;QACnD,uBAAuB,EAAE,KAAK,CAAC,eAAe;QAC9C,qBAAqB,EAAE,KAAK,CAAC,cAAc;KAC5C,CAAC;IACF,MAAM,MAAM,GAA2B,EAAE,GAAG,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;IACjF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,UAAU;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;SACzD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,iEAAiE;IACjE,uEAAuE;IACvE,qDAAqD;IACrD,MAAM,IAAI,GAAG;;;EAGb,OAAO;;;iBAGQ,GAAG,IAAI,KAAK,CAAC,cAAc;;CAE3C,CAAC;IAEA,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,KAAK,GAAG,mBAAmB,EAAE,CAAC;QAChC,MAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,338 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # system-setup.sh — slice 5 OS-level setup. Runs as the first step of
4
+ # `ralph-orchestrate` on the EC2 worker, AFTER the user-data stub has
5
+ # installed Node + git + jq + awscli + the harness package.
6
+ #
7
+ # Scope (intentionally OS-level only — everything else is in TS):
8
+ # 1. start the amazon-cloudwatch-agent so /var/log/ralph.log streams
9
+ # live to CloudWatch (every ~5s) — survives force-termination
10
+ # 2. install gh, .NET 10 SDK, Docker, and the claude CLI
11
+ # 3. fetch GitHub PAT and Claude OAuth credential from SSM SecureString
12
+ # into mode-0600 files
13
+ # 4. clone the target repo on its resolved default branch
14
+ # 5. safety guards (default branch, clean working tree, origin matches
15
+ # RALPH_TARGET_REPO)
16
+ # 6. configure claude MCPs (serena, morph-mcp, context7, github,
17
+ # sequential-thinking; `memory` excluded)
18
+ # 7. validate .ralph/config.yaml via `ralph-validate-config`
19
+ # 8. write RALPH_WORK_DIR / RALPH_DEFAULT_BRANCH / RALPH_CONFIG /
20
+ # RALPH_LAUNCH_TAG to /tmp/ralph/setup.env so the TS orchestrator
21
+ # picks them up after this subprocess exits
22
+ #
23
+ # Inputs (env, set by ralph-fire's user-data stub):
24
+ # RALPH_TARGET_REPO required, owner/repo
25
+ # RALPH_AWS_REGION required, e.g. eu-central-1
26
+ # RALPH_GITHUB_TOKEN_SSM_KEY SSM SecureString name for the GitHub PAT
27
+ # RALPH_CLAUDE_OAUTH_SSM_KEY SSM SecureString name for the OAuth cred
28
+ # RALPH_LOG_GROUP CloudWatch log group
29
+ #
30
+ # Output: /tmp/ralph/setup.env (KEY=VALUE per line) — read by ralph-orchestrate
31
+ # after this script exits.
32
+
33
+ set -uo pipefail
34
+
35
+ : "${HOME:=/root}"
36
+ export HOME
37
+
38
+ # claude CLI refuses --permission-mode bypassPermissions when running as
39
+ # root unless IS_SANDBOX=1. cloud-init runs as root and the orchestrator
40
+ # needs the bypass. The throwaway EC2 (scoped IAM, no SSH, ≤75-min
41
+ # lifetime) is the sandbox this knob exists for.
42
+ export IS_SANDBOX=1
43
+
44
+ : "${RALPH_LOG_GROUP:=/ralph/main}"
45
+ : "${RALPH_GITHUB_TOKEN_SSM_KEY:=/ralph/github-pat}"
46
+ : "${RALPH_CLAUDE_OAUTH_SSM_KEY:=/ralph/claude-oauth-credential}"
47
+
48
+ LOG_FILE="/var/log/ralph.log"
49
+ : > "$LOG_FILE" 2>/dev/null || true
50
+
51
+ # ---- IMDSv2 + metadata -------------------------------------------------------
52
+
53
+ setup__md_token=$(curl -fsS -m 5 -X PUT \
54
+ "http://169.254.169.254/latest/api/token" \
55
+ -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || true)
56
+
57
+ setup__md() {
58
+ curl -fsS -m 5 \
59
+ -H "X-aws-ec2-metadata-token: ${setup__md_token}" \
60
+ "http://169.254.169.254/latest/meta-data/$1" 2>/dev/null || true
61
+ }
62
+
63
+ INSTANCE_ID=$(setup__md instance-id)
64
+ REGION="${RALPH_AWS_REGION:-$(setup__md placement/region)}"
65
+ LOG_STREAM="${INSTANCE_ID:-unknown-instance}"
66
+
67
+ # Per-launch identifier embedded by the implementation call as an HTML
68
+ # comment in the PR body so the launcher can correlate post-hoc when the
69
+ # instance was hard-killed before recording state. Defaults to the
70
+ # instance id; falls back to a timestamp+pid pair if IMDS is unreachable.
71
+ RALPH_LAUNCH_TAG="${INSTANCE_ID:-$(date -u +%s)-$$}"
72
+ export RALPH_LAUNCH_TAG
73
+
74
+ setup__info() { printf 'system-setup: %s\n' "$*"; }
75
+ setup__err() { printf 'system-setup: error: %s\n' "$*" >&2; }
76
+
77
+ # Pulls a SecureString parameter, decrypts under the role's permitted KMS
78
+ # alias, prints the value to stdout. Caller redirects to a 0600 file.
79
+ setup__ssm_get() {
80
+ local name="$1"
81
+ aws --region "$REGION" ssm get-parameter \
82
+ --name "$name" \
83
+ --with-decryption \
84
+ --query 'Parameter.Value' \
85
+ --output text
86
+ }
87
+
88
+ # ---- live log streaming via amazon-cloudwatch-agent --------------------------
89
+
90
+ setup__start_cwagent() {
91
+ setup__info "PHASE_START phase=cwagent stream=${LOG_STREAM}"
92
+ if ! dnf -y -q --allowerasing install amazon-cloudwatch-agent >/dev/null 2>&1; then
93
+ setup__err "amazon-cloudwatch-agent install failed; live log streaming disabled"
94
+ return 0
95
+ fi
96
+ local cfg=/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ralph.json
97
+ install -d -m 755 "$(dirname "$cfg")"
98
+ cat > "$cfg" <<JSON
99
+ {
100
+ "agent": { "run_as_user": "root" },
101
+ "logs": {
102
+ "force_flush_interval": 5,
103
+ "logs_collected": {
104
+ "files": {
105
+ "collect_list": [
106
+ {
107
+ "file_path": "${LOG_FILE}",
108
+ "log_group_name": "${RALPH_LOG_GROUP}",
109
+ "log_stream_name": "${LOG_STREAM}",
110
+ "timezone": "UTC"
111
+ },
112
+ {
113
+ "file_path": "/var/log/cloud-init-output.log",
114
+ "log_group_name": "${RALPH_LOG_GROUP}",
115
+ "log_stream_name": "${LOG_STREAM}-cloud-init",
116
+ "timezone": "UTC"
117
+ }
118
+ ]
119
+ }
120
+ }
121
+ }
122
+ }
123
+ JSON
124
+ if /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
125
+ -a fetch-config -m ec2 -c "file:${cfg}" -s >/dev/null 2>&1; then
126
+ setup__info "PHASE_END phase=cwagent"
127
+ else
128
+ setup__err "amazon-cloudwatch-agent failed to start; live log streaming disabled"
129
+ fi
130
+ }
131
+
132
+ # ---- install OS deps (gh, .NET 10, Docker, claude) ---------------------------
133
+
134
+ setup__install_deps() {
135
+ setup__info "PHASE_START phase=install-deps"
136
+
137
+ # gh CLI — official rpm repo.
138
+ dnf -y -q config-manager --add-repo \
139
+ https://cli.github.com/packages/rpm/gh-cli.repo >/dev/null
140
+ dnf -y -q --allowerasing install gh >/dev/null
141
+
142
+ # Docker — required by the github MCP container.
143
+ dnf -y -q --allowerasing install docker >/dev/null
144
+ systemctl enable --now docker >/dev/null 2>&1 || true
145
+
146
+ # uv (astral) — used by serena.
147
+ if ! command -v uv >/dev/null 2>&1; then
148
+ curl -LsSf https://astral.sh/uv/install.sh | sh >/dev/null 2>&1 || true
149
+ export PATH="/root/.local/bin:${HOME}/.local/bin:${PATH}"
150
+ fi
151
+
152
+ # .NET 10 SDK via dotnet-install.sh.
153
+ if ! command -v dotnet >/dev/null 2>&1; then
154
+ curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
155
+ chmod +x /tmp/dotnet-install.sh
156
+ /tmp/dotnet-install.sh --channel 10.0 \
157
+ --install-dir /usr/share/dotnet >/dev/null
158
+ ln -sf /usr/share/dotnet/dotnet /usr/local/bin/dotnet
159
+ rm -f /tmp/dotnet-install.sh
160
+ fi
161
+
162
+ # claude CLI (npm global).
163
+ npm install -g @anthropic-ai/claude-code >/dev/null
164
+
165
+ setup__info "PHASE_END phase=install-deps"
166
+ }
167
+
168
+ # ---- fetch secrets from SSM --------------------------------------------------
169
+
170
+ setup__fetch_secrets() {
171
+ setup__info "PHASE_START phase=fetch-secrets"
172
+
173
+ local pat_dir="${HOME}/.ralph"
174
+ install -d -m 700 "$pat_dir"
175
+ local pat_file="${pat_dir}/github-pat"
176
+ if ! setup__ssm_get "$RALPH_GITHUB_TOKEN_SSM_KEY" > "$pat_file"; then
177
+ setup__err "could not fetch GitHub PAT from ${RALPH_GITHUB_TOKEN_SSM_KEY}"
178
+ return 1
179
+ fi
180
+ chmod 600 "$pat_file"
181
+ if ! gh auth login --with-token < "$pat_file" >/dev/null 2>&1; then
182
+ setup__err "gh auth login failed"
183
+ return 1
184
+ fi
185
+ if ! gh auth setup-git >/dev/null 2>&1; then
186
+ setup__err "gh auth setup-git failed"
187
+ return 1
188
+ fi
189
+ GH_TOKEN="$(<"$pat_file")"
190
+ GITHUB_PERSONAL_ACCESS_TOKEN="$GH_TOKEN"
191
+ export GH_TOKEN GITHUB_PERSONAL_ACCESS_TOKEN
192
+
193
+ local cred_dir="${HOME}/.claude"
194
+ install -d -m 700 "$cred_dir"
195
+ local cred_file="${cred_dir}/.credentials.json"
196
+ if ! setup__ssm_get "$RALPH_CLAUDE_OAUTH_SSM_KEY" > "$cred_file"; then
197
+ setup__err "could not fetch OAuth credential from ${RALPH_CLAUDE_OAUTH_SSM_KEY}"
198
+ return 1
199
+ fi
200
+ chmod 600 "$cred_file"
201
+
202
+ setup__info "PHASE_END phase=fetch-secrets"
203
+ }
204
+
205
+ # ---- fresh clone of target on resolved default branch ------------------------
206
+
207
+ setup__clone_target() {
208
+ setup__info "PHASE_START phase=clone-target target=${RALPH_TARGET_REPO}"
209
+ if [[ -z "${RALPH_TARGET_REPO:-}" ]]; then
210
+ setup__err "RALPH_TARGET_REPO is required"
211
+ return 2
212
+ fi
213
+ local default_branch
214
+ default_branch=$(gh repo view "$RALPH_TARGET_REPO" \
215
+ --json defaultBranchRef \
216
+ --jq '.defaultBranchRef.name')
217
+ if [[ -z "$default_branch" ]]; then
218
+ setup__err "could not resolve default branch for ${RALPH_TARGET_REPO}"
219
+ return 1
220
+ fi
221
+ local work_dir
222
+ work_dir="$(mktemp -d -t ralph-work-XXXXXX)"
223
+ if ! git clone --depth 1 --branch "$default_branch" \
224
+ "https://github.com/${RALPH_TARGET_REPO}.git" "$work_dir" \
225
+ >/dev/null 2>&1; then
226
+ setup__err "git clone of ${RALPH_TARGET_REPO} failed"
227
+ return 1
228
+ fi
229
+ RALPH_WORK_DIR="$work_dir"
230
+ RALPH_DEFAULT_BRANCH="$default_branch"
231
+ export RALPH_WORK_DIR RALPH_DEFAULT_BRANCH
232
+ cd "$RALPH_WORK_DIR"
233
+ setup__info "PHASE_END phase=clone-target branch=${default_branch} dir=${RALPH_WORK_DIR}"
234
+ }
235
+
236
+ # ---- safety guards -----------------------------------------------------------
237
+
238
+ setup__safety_guards() {
239
+ setup__info "PHASE_START phase=safety-guards"
240
+ cd "${RALPH_WORK_DIR:?work dir required}"
241
+
242
+ local current_branch
243
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
244
+ if [[ "$current_branch" != "$RALPH_DEFAULT_BRANCH" ]]; then
245
+ setup__err "post-clone branch is ${current_branch}, expected ${RALPH_DEFAULT_BRANCH}"
246
+ return 1
247
+ fi
248
+
249
+ if [[ -n "$(git status --porcelain)" ]]; then
250
+ setup__err "fresh clone has uncommitted state — refusing to continue"
251
+ return 1
252
+ fi
253
+
254
+ local origin
255
+ origin=$(git remote get-url origin)
256
+ if [[ "$origin" != *"${RALPH_TARGET_REPO}"* ]]; then
257
+ setup__err "origin (${origin}) does not match RALPH_TARGET_REPO (${RALPH_TARGET_REPO})"
258
+ return 1
259
+ fi
260
+
261
+ setup__info "PHASE_END phase=safety-guards"
262
+ }
263
+
264
+ # ---- configure claude MCPs (memory excluded) ---------------------------------
265
+
266
+ setup__configure_mcps() {
267
+ setup__info "PHASE_START phase=configure-mcps"
268
+ claude mcp add serena -- \
269
+ uvx --from git+https://github.com/oraios/serena serena-mcp-server \
270
+ >/dev/null 2>&1 || true
271
+ claude mcp add morph-mcp -- \
272
+ npx -y @morph-labs/morph-mcp \
273
+ >/dev/null 2>&1 || true
274
+ claude mcp add context7 -- \
275
+ npx -y @upstash/context7-mcp \
276
+ >/dev/null 2>&1 || true
277
+ claude mcp add github -- \
278
+ docker run -i --rm \
279
+ -e GITHUB_PERSONAL_ACCESS_TOKEN \
280
+ ghcr.io/github/github-mcp-server \
281
+ >/dev/null 2>&1 || true
282
+ claude mcp add sequential-thinking -- \
283
+ npx -y @modelcontextprotocol/server-sequential-thinking \
284
+ >/dev/null 2>&1 || true
285
+ setup__info "PHASE_END phase=configure-mcps"
286
+ }
287
+
288
+ # ---- validate target config via ralph-validate-config ------------------------
289
+
290
+ setup__validate_config() {
291
+ setup__info "PHASE_START phase=validate-config"
292
+ local cfg="${RALPH_WORK_DIR}/.ralph/config.yaml"
293
+ if [[ ! -f "$cfg" ]]; then
294
+ setup__err "${RALPH_TARGET_REPO} is missing .ralph/config.yaml — refusing to continue"
295
+ return 2
296
+ fi
297
+ if ! ralph-validate-config "$cfg" >/dev/null; then
298
+ setup__err "${cfg} failed schema validation"
299
+ return 2
300
+ fi
301
+ RALPH_CONFIG="$cfg"
302
+ export RALPH_CONFIG
303
+ setup__info "PHASE_END phase=validate-config config=${cfg}"
304
+ }
305
+
306
+ # ---- write setup.env for ralph-orchestrate -----------------------------------
307
+
308
+ setup__write_env_file() {
309
+ install -d -m 755 /tmp/ralph
310
+ cat > /tmp/ralph/setup.env <<EOF
311
+ RALPH_WORK_DIR=${RALPH_WORK_DIR}
312
+ RALPH_DEFAULT_BRANCH=${RALPH_DEFAULT_BRANCH}
313
+ RALPH_CONFIG=${RALPH_CONFIG}
314
+ RALPH_LAUNCH_TAG=${RALPH_LAUNCH_TAG}
315
+ EOF
316
+ chmod 644 /tmp/ralph/setup.env
317
+ }
318
+
319
+ # ---- main --------------------------------------------------------------------
320
+
321
+ setup__main() {
322
+ local now
323
+ now=$(date -u +%FT%TZ)
324
+ setup__info "ralph-harness slice 5 system-setup"
325
+ setup__info "instance=${INSTANCE_ID} region=${REGION} ts=${now}"
326
+ setup__info "target=${RALPH_TARGET_REPO:-unset} log_group=${RALPH_LOG_GROUP} log_stream=${LOG_STREAM}"
327
+
328
+ setup__start_cwagent
329
+ setup__install_deps || return $?
330
+ setup__fetch_secrets || return $?
331
+ setup__clone_target || return $?
332
+ setup__safety_guards || return $?
333
+ setup__configure_mcps || return $?
334
+ setup__validate_config || return $?
335
+ setup__write_env_file
336
+ }
337
+
338
+ setup__main 2>&1 | tee -a "$LOG_FILE"
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@unimatrix27/ralph-harness",
3
+ "version": "1.0.0",
4
+ "description": "Throwaway-EC2 loop that picks one ready-for-agent GitHub issue, implements it, opens a PR, runs one auto-review pass, then terminates.",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=24"
8
+ },
9
+ "bin": {
10
+ "ralph-bootstrap-aws": "dist/bin/ralph-bootstrap-aws.js",
11
+ "ralph-fire": "dist/bin/ralph-fire.js",
12
+ "ralph-gsm": "dist/bin/ralph-gsm.js",
13
+ "ralph-orchestrate": "dist/bin/ralph-orchestrate.js",
14
+ "ralph-sync-credential": "dist/bin/ralph-sync-credential.js",
15
+ "ralph-sync-github-pat": "dist/bin/ralph-sync-github-pat.js",
16
+ "ralph-tail-logs": "dist/bin/ralph-tail-logs.js",
17
+ "ralph-validate-config": "dist/bin/ralph-validate-config.js"
18
+ },
19
+ "files": [
20
+ "dist/",
21
+ "lib/cloud-init/",
22
+ "prompts/",
23
+ "README.md",
24
+ "CONTRIBUTING.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "test": "vitest run",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "dependencies": {
32
+ "@aws-sdk/client-cloudwatch-logs": "^3.700.0",
33
+ "@aws-sdk/client-ec2": "^3.700.0",
34
+ "@aws-sdk/client-iam": "^3.700.0",
35
+ "@aws-sdk/client-kms": "^3.700.0",
36
+ "@aws-sdk/client-ssm": "^3.700.0",
37
+ "@aws-sdk/client-sts": "^3.700.0",
38
+ "yaml": "^2.8.4",
39
+ "zod": "^4.4.3"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^24.0.0",
43
+ "tsx": "^4.19.0",
44
+ "typescript": "^5.6.0",
45
+ "vitest": "^2.1.0"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/unimatrix27/ralph-harness.git"
53
+ },
54
+ "license": "MIT"
55
+ }