Conversation
📝 WalkthroughWalkthroughThis is a tremendous PR, folks—absolutely tremendous. We're talking major infrastructure overhaul here. New GitHub Actions workflows for CI across Windows, macOS, and Android platforms. We're removing old workflow files, updating path resolutions from Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/macos/Sources/Argent/GatewayEndpointStore.swift (1)
87-126:⚠️ Potential issue | 🟡 MinorMake the password warning match the token path.
Right now this logs an “overrides” warning even when the config password and
ARGENT_GATEWAY_PASSWORDare identical. Because the warning is one-shot, that false positive can also suppress the real mismatch warning later. Not good.💡 Small fix
- if let configPassword = self.resolveConfigPassword(isRemote: isRemote, root: root), - !configPassword.isEmpty + if let configPassword = self.resolveConfigPassword(isRemote: isRemote, root: root), + !configPassword.isEmpty, + configPassword != trimmed { self.warnEnvOverrideOnce( kind: .password, envVar: "ARGENT_GATEWAY_PASSWORD", configKey: isRemote ? "gateway.remote.password" : "gateway.auth.password")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/macos/Sources/Argent/GatewayEndpointStore.swift` around lines 87 - 126, The warning currently logs an override anytime both an env password and a config password exist even if they are identical; change the logic in the ARGENT_GATEWAY_PASSWORD handling so you first obtain the config value via resolveConfigPassword(isRemote:root:), trim it and compare it to the env-derived trimmed value, and only call warnEnvOverrideOnce(kind:.password, envVar:"ARGENT_GATEWAY_PASSWORD", configKey: ...) when the two trimmed values differ; keep the existing return of the env value when present. Ensure you reference resolveConfigPassword and warnEnvOverrideOnce and compare trimmed strings to avoid false-positive one-shot warnings.dashboard/src/App.tsx (1)
4922-4922:⚠️ Potential issue | 🔴 CriticalAdd the missing closing
</div>tag before the next ternary condition.The outer wrapper opened at line 4922 never closes before the next ternary arm on line 5043. This will break JSX parsing. The verification shows 12 opening
<div>tags versus only 10 closing tags in this section—tremendous problem, folks!✅ Minimal fix
</div> + </div> ) : showWorkforce && allowWorkforceSurface ? (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@dashboard/src/App.tsx` at line 4922, In App.tsx the JSX wrapper <div className="flex-1 flex flex-col min-h-0 overflow-hidden"> is not closed, causing mismatched tags and broken JSX; add a matching closing </div> immediately before the start of the next ternary/conditional branch so the fragment inside the App component (the block that opens with <div className="flex-1 flex flex-col min-h-0 overflow-hidden">) is properly closed and all nested divs balance.
🧹 Nitpick comments (5)
dashboard/src/components/ConfigPanelCore.tsx (1)
41-46: Folks, we have a tremendous dictionary here, but the IDs? Not so great.Look, I've seen a lot of IDs in my time — the best IDs, believe me — and this sequence goes 1, 2, 3, then jumps right to 5. Where's 4? Did somebody forget about 4? It's like building the most beautiful building and skipping the fourth floor. The code works, it's still winning, but for consistency and future maintainability, you might want to fix that numbering. Very minor, very small potatoes, but we like perfection here.
🔧 Proposed fix to make the IDs sequential — believe me, it's beautiful
dictionary: [ { id: "1", term: "COMEX", replacement: "Coe-Mex", enabled: true }, { id: "2", term: "oz", replacement: "ounces", enabled: true }, { id: "3", term: "SGE", replacement: "Shanghai Gold Exchange", enabled: true }, - { id: "5", term: "API", replacement: "A P I", enabled: true }, + { id: "4", term: "API", replacement: "A P I", enabled: true }, ],🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@dashboard/src/components/ConfigPanelCore.tsx` around lines 41 - 46, The dictionary array in ConfigPanelCore.tsx has non-sequential IDs (entries in the dictionary property: { id: "1" ... }, { id: "2" ... }, { id: "3" ... }, then { id: "5" ... }) — update the id value on the final entry in the dictionary array from "5" to "4" so IDs are sequential; locate the dictionary constant/prop in ConfigPanelCore (the dictionary array) and change the id string for the API replacement entry to "4".src/data/storage-factory.ts (1)
202-213: Add a documentation comment explaining the dynamic import pattern for optional dependencies.The
new Functionpattern is a standard technique in this codebase for optional dependencies like the PostgreSQL adapter. Since it's intentionally used across multiple files (storage-factory.ts and storage-factory-core.ts), consider adding a brief comment to clarify the design choice for future developers.📝 Suggested documentation comment
async function createPgAdapter(config: StorageConfig): Promise<StorageAdapter> { if (!config.postgres) { throw new Error("StorageConfig: postgres config is required for PG adapter"); } + // Using dynamic import via new Function to allow truly runtime resolution + // of optional pg-adapter module, preventing bundlers from statically analyzing + // dependencies that may not be present in all deployment environments. let PgAdapter: new (postgres: NonNullable<StorageConfig["postgres"]>) => StorageAdapter;CSP is not a concern in this codebase — the configured policy only restricts frame ancestors, not eval operations.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/data/storage-factory.ts` around lines 202 - 213, Add a brief documentation comment above the dynamic import block explaining that the new Function("specifier","return import(specifier)") pattern is intentionally used to load optional dependencies at runtime (here to obtain PgAdapter) without static import/require; mention that this mirrors the pattern used in storage-factory-core.ts, that it returns a Promise resolving to an object with PgAdapter (a constructor matching StorageAdapter), and note CSP is not a concern in this codebase (CSP only restricts frame-ancestors). Include references to PgAdapter, dynamicImport, and StorageAdapter in the comment so future maintainers can quickly find and understand the pattern and rationale..github/workflows/ci.yml (2)
410-411: iOS job disabled—I get it, but let's keep an eye on this!Look, you've got
if: falsehere which means this beautiful iOS test setup (simulators, coverage gates, the whole thing) is just sitting there doing nothing. That's fine for now—sometimes you gotta focus on what's important—but don't forget about it. Dead code gets stale, and when you flip that switch totrue, things might not work like they used to.Consider adding a TODO or tracking issue so this doesn't become forgotten infrastructure.
Would you like me to create a tracking issue to remind you to re-enable iOS CI when ready?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/ci.yml around lines 410 - 411, The iOS CI job is disabled by setting the 'ios' job's conditional to "if: false"; add a short TODO comment above the 'ios' job and create or reference a tracking issue so the disabled state isn't forgotten—update the 'ios' job block to include a comment like "TODO: re-enable iOS CI — see ISSUE-XXXX" and create/link that issue in your issue tracker, or add an entry to the repo's roadmap so whoever flips 'if: false' back to true has the context and checklist for revalidating simulators, coverage gates, and any platform-specific setup.
22-33: Lots of repeated code here—could be tremendous with a composite action!I'm seeing the same submodule retry logic copied 7 times across this file. Same with the pnpm setup. Now look, I understand—GitHub Actions makes you do this sometimes—but if you wanted to make this really classy, you could extract these into a composite action or reusable workflow.
Something like
.github/actions/checkout-with-submodules/action.yml. It would make maintenance much easier, believe me. But hey, it works as-is, so this is just a suggestion for when you want to make it even better.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/ci.yml around lines 22 - 33, The "Checkout submodules (retry)" shell step and the repeated pnpm setup blocks are duplicated across the workflow; extract the retry logic into a reusable composite action (e.g., a new action that runs the git submodule loop using the existing git submodule update --init --force --depth=1 --recursive command and retry sleep strategy) and similarly extract the pnpm setup into a reusable action or workflow call, then replace each duplicated step with calls to those new actions so the workflow uses the single reusable action instead of copying the shell block seven times.apps/macos/Tests/ArgentIPCTests/GatewayEndpointStoreTests.swift (1)
13-37: Keep the config-before-launchd assertion here.Right now this only proves
envwins andlaunchdis the fallback. The resolver still hasconfigsitting in the middle, and if that branch slips, local auth can quietly choose the wrong credential. Easy one to lock down.🧪 Add the missing precedence check
let envToken = GatewayEndpointStore._testResolveGatewayToken( isRemote: false, root: [:], env: ["ARGENT_GATEWAY_TOKEN": "env-token"], launchdSnapshot: snapshot) `#expect`(envToken == "env-token") + let configToken = GatewayEndpointStore._testResolveGatewayToken( + isRemote: false, + root: [ + "gateway": [ + "auth": [ + "token": "config-token", + ], + ], + ], + env: [:], + launchdSnapshot: snapshot) + `#expect`(configToken == "config-token") + let fallbackToken = GatewayEndpointStore._testResolveGatewayToken( isRemote: false, root: [:], env: [:], launchdSnapshot: snapshot)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/macos/Tests/ArgentIPCTests/GatewayEndpointStoreTests.swift` around lines 13 - 37, The test currently only verifies env wins and launchd is fallback; add assertions to verify config (passed via the root parameter) sits between env and launchd in precedence. Call GatewayEndpointStore._testResolveGatewayToken with root: ["ARGENT_GATEWAY_TOKEN": "config-token"], env: [:], launchdSnapshot: snapshot and assert the result equals "config-token" to ensure config overrides launchd, and also add a case with env present (env: ["ARGENT_GATEWAY_TOKEN": "env-token"], root: ["ARGENT_GATEWAY_TOKEN": "config-token"]) asserting the result is "env-token" to ensure env still beats config; use the existing test function resolveGatewayTokenPrefersEnvAndFallsBackToLaunchd and the _testResolveGatewayToken symbol to locate where to add these assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/dependabot.yml:
- Around line 1-113: Dependabot is configured to run Swift updates for
directories "/apps/shared/MoltbotKit" and "/Swabble" which do not exist; either
remove the two swift update blocks referencing those directories (the
package-ecosystem: swift entries with directory: /apps/shared/MoltbotKit and
directory: /Swabble) from .github/dependabot.yml or create the missing
directories and add valid Swift package manifests there so Dependabot can run;
ensure you keep the working swift block for directory: /apps/macos and the other
ecosystems unchanged.
In @.github/workflows/ci.yml:
- Around line 393-396: The workflow step named "Select Xcode 26.1" is selecting
a non-existent path (/Applications/Xcode_26.1.app); update that run command to
point to an available Xcode bundle (for example /Applications/Xcode_26.1.1.app)
or another supported version (26.0.1, 26.2, 26.3) so xcode-select -s uses a real
installation and xcodebuild -version succeeds.
In @.github/workflows/labeler.yml:
- Around line 3-7: The workflow currently triggers on both pull_request_target
and issues but the label job assumes context.payload.pull_request exists (used
in the early return), so scope jobs to their relevant events: update the label
job to run only when github.event_name == 'pull_request_target' (or check
context.payload.pull_request) and any issue-only job to run only when
github.event_name == 'issues'; use job-level if conditions (referencing the
label job and context.payload.pull_request) so the label job won't execute for
issue events and compute won't be wasted.
In `@dashboard/src/App.tsx`:
- Around line 1119-1125: The localStorage initializer for workspaceTabs accepts
any JSON and can return invalid shapes (null, object, legacy), causing
workspaceTabs.map to crash; update the initializer (the useState call that
defines workspaceTabs and setWorkspaceTabs) to parse "argent-workspaces", verify
the parsed value is an Array, and that each item conforms to the WorkspaceTab
shape (has required properties like id and name, optional icon),
filter/transform valid entries, and fall back to the default [{ id: "home",
name: "Home", icon: "🏠" }] if validation fails or parsing throws.
- Line 1110: The component currently seeds surfaceProfile to "full" which causes
the add-only operations tab to appear before the async profile fetch and on
transient failures; change the initial useState for surfaceProfile to a neutral
value (e.g., undefined or null) and only call setSurfaceProfile("full" |
"public-core" etc.) after the async fetch resolves successfully; update the
effect that adds the operations tab to run only when surfaceProfile is
explicitly "full" (guard on surfaceProfile !== undefined) and stop
writing/persisting the operations workspace on transient settings errors—do not
setSurfaceProfile("full") in the transient-failure paths (the code referenced by
setSurfaceProfile and the add-operations effect should be the targets).
In `@dashboard/src/lib/configSurfaceProfile.ts`:
- Around line 21-28: Do not "fail open" to "full" when the config is missing,
malformed, or contains unexpected values; instead have the parser return a
neutral/absent value so callers must explicitly opt into unlocking. Update the
logic around rawConfigText and JSON.parse so that: if rawConfigText is empty
return undefined (not "full"); on successful parse return "public-core" only
when parsed?.distribution?.surfaceProfile === "public-core" and otherwise return
undefined; and on JSON.parse errors return undefined. Reference rawConfigText
and parsed.distribution.surfaceProfile so callers can explicitly choose to treat
undefined as "full" if they want a temporary override.
In `@src/agents/workspace.ts`:
- Around line 16-18: The change hardcodes ~/.argent/... and ignores the
ARGENT_STATE_DIR override; update the workspace path resolver to honor the
ARGENT_STATE_DIR environment override when present (fall back to the existing
homedir-based default otherwise). In the function that builds the workspace path
(the code that currently returns path.join(homedir(), ".argent",
`workspace-${profile}`) or path.join(homedir(), ".argent", "workspace")), first
check for process.env.ARGENT_STATE_DIR (or the passed-in env/stateDir value if
the caller passes an env object) and join that with the workspace name/profile;
keep the new default behavior only when the env override is absent so callers
that pass env continue to get deployment-specific state roots.
In `@src/canvas-host/server.ts`:
- Line 238: The current code builds a single-item candidates array pointing only
to path.join(os.homedir(), ".argent", "canvas"), which ignores any legacy
install location and can cause upgrades to lose existing data; update the
candidates construction (the variable named candidates) to include the legacy
canvas path(s) in order of preference (e.g., add path.join(os.homedir(),
"<legacy-dir>", "canvas") or path.join(os.homedir(), ".canvas") before the new
path) so the host will detect and prefer existing content during startup; ensure
any downstream discovery logic that iterates candidates still respects the new
order.
In `@src/daemon/inspect.ts`:
- Line 129: The change narrows ignored launchd labels to only
resolveGatewayLaunchAgentLabel(), causing first-party services (e.g.,
ai.argent.node, ai.argent.dashboard-ui, ai.argent.dashboard-api) to be reported
as “extra”; update the filtering logic in the function that returns label ===
resolveGatewayLaunchAgentLabel() so it excludes the full set of first-party
launchd labels instead of just the gateway label—use a predicate or list (e.g.,
an array of known first-party labels) and check against it where scanLaunchdDir
results are processed (refer to resolveGatewayLaunchAgentLabel(),
scanLaunchdDir, and the label variable) to restore the original exclusion
behavior.
In `@src/daemon/program-args.ts`:
- Around line 119-124: The early return when a .git directory is found is
overriding an explicit install snapshot override; update the logic in the
function that inspects currentRoot (references to currentRoot and the
fs.access(".git") check) to first detect if ARGENT_INSTALL_PACKAGE_DIR
(process.env.ARGENT_INSTALL_PACKAGE_DIR or the config variable used) is set and,
if so, skip the .git early-return path so the explicit install dir wins; adjust
the try/catch block so it only returns null for a repo checkout when no
ARGENT_INSTALL_PACKAGE_DIR is provided, and add a regression test that sets
ARGENT_INSTALL_PACKAGE_DIR and ensures the code prefers the install package dir
rather than falling back to the repo build.
In `@src/gateway/server-close.ts`:
- Around line 86-92: The direct calls to params.cron.stop(),
params.heartbeatRunner.stop(), params.contemplationRunner.stop(),
params.executionWorkerRunner.stop(), params.jobOrchestratorRunner.stop(),
params.sisRunner.stop(), and params.consciousnessKernelRunner.stop() can throw
and abort shutdown; wrap each .stop() call in a defensive try-catch (or
implement a small helper safeStop(name, runner) that calls runner.stop() inside
try-catch) so that if one runner throws we log the error via the available
logger (e.g., params.logger.error or console.error) including the runner name
and error details, then continue to the next stop call to ensure full shutdown
proceeds.
- Around line 24-30: The JobOrchestratorRunner type is currently incompatible
with code that calls .stop() on it; update the type or the shutdown call so they
match: either change the JobOrchestratorRunner type definition to include a
stop(): void (or stop: () => Promise<void> if async) so it exposes the stop
method, or make the property optional and guard the call (e.g., if
(jobOrchestratorRunner?.stop) jobOrchestratorRunner.stop()), and ensure the
shutdown sequence that invokes .stop() (the server close/shutdown routine that
iterates
cron/heartbeatRunner/contemplationRunner/executionWorkerRunner/jobOrchestratorRunner/...)
reflects the chosen signature (synchronous vs async) so types and runtime
behavior align.
- Line 90: The code calls params.jobOrchestratorRunner.stop() but
JobOrchestratorRunner is currently an empty/void type and
startJobOrchestratorRunner returns void, causing a runtime/type error; fix by
making the runner API consistent: update the JobOrchestratorRunner type to
include stop(): Promise<void> (or stop(): void) like SisRunner/HeartbeatRunner
and change startJobOrchestratorRunner to return an instance implementing that
interface, or alternatively change the call site to treat the start function as
void (remove the .stop() call or guard it with if (params.jobOrchestratorRunner
&& typeof params.jobOrchestratorRunner.stop === 'function') await
params.jobOrchestratorRunner.stop();). Ensure symbol names JobOrchestratorRunner
and startJobOrchestratorRunner are updated together so the type system and
runtime match.
---
Outside diff comments:
In `@apps/macos/Sources/Argent/GatewayEndpointStore.swift`:
- Around line 87-126: The warning currently logs an override anytime both an env
password and a config password exist even if they are identical; change the
logic in the ARGENT_GATEWAY_PASSWORD handling so you first obtain the config
value via resolveConfigPassword(isRemote:root:), trim it and compare it to the
env-derived trimmed value, and only call warnEnvOverrideOnce(kind:.password,
envVar:"ARGENT_GATEWAY_PASSWORD", configKey: ...) when the two trimmed values
differ; keep the existing return of the env value when present. Ensure you
reference resolveConfigPassword and warnEnvOverrideOnce and compare trimmed
strings to avoid false-positive one-shot warnings.
In `@dashboard/src/App.tsx`:
- Line 4922: In App.tsx the JSX wrapper <div className="flex-1 flex flex-col
min-h-0 overflow-hidden"> is not closed, causing mismatched tags and broken JSX;
add a matching closing </div> immediately before the start of the next
ternary/conditional branch so the fragment inside the App component (the block
that opens with <div className="flex-1 flex flex-col min-h-0 overflow-hidden">)
is properly closed and all nested divs balance.
---
Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 410-411: The iOS CI job is disabled by setting the 'ios' job's
conditional to "if: false"; add a short TODO comment above the 'ios' job and
create or reference a tracking issue so the disabled state isn't
forgotten—update the 'ios' job block to include a comment like "TODO: re-enable
iOS CI — see ISSUE-XXXX" and create/link that issue in your issue tracker, or
add an entry to the repo's roadmap so whoever flips 'if: false' back to true has
the context and checklist for revalidating simulators, coverage gates, and any
platform-specific setup.
- Around line 22-33: The "Checkout submodules (retry)" shell step and the
repeated pnpm setup blocks are duplicated across the workflow; extract the retry
logic into a reusable composite action (e.g., a new action that runs the git
submodule loop using the existing git submodule update --init --force --depth=1
--recursive command and retry sleep strategy) and similarly extract the pnpm
setup into a reusable action or workflow call, then replace each duplicated step
with calls to those new actions so the workflow uses the single reusable action
instead of copying the shell block seven times.
In `@apps/macos/Tests/ArgentIPCTests/GatewayEndpointStoreTests.swift`:
- Around line 13-37: The test currently only verifies env wins and launchd is
fallback; add assertions to verify config (passed via the root parameter) sits
between env and launchd in precedence. Call
GatewayEndpointStore._testResolveGatewayToken with root:
["ARGENT_GATEWAY_TOKEN": "config-token"], env: [:], launchdSnapshot: snapshot
and assert the result equals "config-token" to ensure config overrides launchd,
and also add a case with env present (env: ["ARGENT_GATEWAY_TOKEN":
"env-token"], root: ["ARGENT_GATEWAY_TOKEN": "config-token"]) asserting the
result is "env-token" to ensure env still beats config; use the existing test
function resolveGatewayTokenPrefersEnvAndFallsBackToLaunchd and the
_testResolveGatewayToken symbol to locate where to add these assertions.
In `@dashboard/src/components/ConfigPanelCore.tsx`:
- Around line 41-46: The dictionary array in ConfigPanelCore.tsx has
non-sequential IDs (entries in the dictionary property: { id: "1" ... }, { id:
"2" ... }, { id: "3" ... }, then { id: "5" ... }) — update the id value on the
final entry in the dictionary array from "5" to "4" so IDs are sequential;
locate the dictionary constant/prop in ConfigPanelCore (the dictionary array)
and change the id string for the API replacement entry to "4".
In `@src/data/storage-factory.ts`:
- Around line 202-213: Add a brief documentation comment above the dynamic
import block explaining that the new Function("specifier","return
import(specifier)") pattern is intentionally used to load optional dependencies
at runtime (here to obtain PgAdapter) without static import/require; mention
that this mirrors the pattern used in storage-factory-core.ts, that it returns a
Promise resolving to an object with PgAdapter (a constructor matching
StorageAdapter), and note CSP is not a concern in this codebase (CSP only
restricts frame-ancestors). Include references to PgAdapter, dynamicImport, and
StorageAdapter in the comment so future maintainers can quickly find and
understand the pattern and rationale.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ab3d2639-8db8-45bc-947f-3eefb237f92f
📒 Files selected for processing (30)
.github/dependabot.yml.github/workflows/ci.yml.github/workflows/labeler.yml.github/workflows/platform-manual.ymlARGENT_ARCHITECTURE.mdREADME.mdVISION.mdapps/macos/Sources/Argent/GatewayEndpointStore.swiftapps/macos/Tests/ArgentIPCTests/GatewayEndpointStoreTests.swiftdashboard/api-server.cjsdashboard/src/App.tsxdashboard/src/components/ConfigPanelCore.tsxdashboard/src/components/widgets/widgetRegistry.tsdashboard/src/lib/configSurfaceProfile.tsdashboard/static-server.cjsdocs.acp.mdsrc/agents/workspace.tssrc/canvas-host/server.tssrc/config/config.public-core-surface.test.tssrc/config/zod-schema.tssrc/daemon/inspect.tssrc/daemon/paths.test.tssrc/daemon/paths.tssrc/daemon/program-args.test.tssrc/daemon/program-args.tssrc/daemon/service-env.test.tssrc/daemon/service-env.tssrc/data/storage-factory.tssrc/gateway/server-close.test.tssrc/gateway/server-close.ts
💤 Files with no reviewable changes (5)
- src/config/config.public-core-surface.test.ts
- src/config/zod-schema.ts
- src/gateway/server-close.test.ts
- .github/workflows/platform-manual.yml
- dashboard/static-server.cjs
| # Dependabot configuration | ||
| # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file | ||
|
|
||
| version: 2 | ||
|
|
||
| registries: | ||
| npm-npmjs: | ||
| type: npm-registry | ||
| url: https://registry.npmjs.org | ||
| replaces-base: true | ||
|
|
||
| updates: | ||
| # npm dependencies (root) | ||
| - package-ecosystem: npm | ||
| directory: / | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| production: | ||
| dependency-type: production | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| development: | ||
| dependency-type: development | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 10 | ||
| registries: | ||
| - npm-npmjs | ||
|
|
||
| # GitHub Actions | ||
| - package-ecosystem: github-actions | ||
| directory: / | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| actions: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 5 | ||
|
|
||
| # Swift Package Manager - macOS app | ||
| - package-ecosystem: swift | ||
| directory: /apps/macos | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| swift-deps: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 5 | ||
|
|
||
| # Swift Package Manager - shared MoltbotKit | ||
| - package-ecosystem: swift | ||
| directory: /apps/shared/MoltbotKit | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| swift-deps: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 5 | ||
|
|
||
| # Swift Package Manager - Swabble | ||
| - package-ecosystem: swift | ||
| directory: /Swabble | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| swift-deps: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 5 | ||
|
|
||
| # Gradle - Android app | ||
| - package-ecosystem: gradle | ||
| directory: /apps/android | ||
| schedule: | ||
| interval: weekly | ||
| cooldown: | ||
| default-days: 7 | ||
| groups: | ||
| android-deps: | ||
| patterns: | ||
| - "*" | ||
| update-types: | ||
| - minor | ||
| - patch | ||
| open-pull-requests-limit: 5 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify the directories referenced in dependabot.yml exist
for dir in "apps/macos" "apps/shared/MoltbotKit" "Swabble" "apps/android"; do
if [ -d "$dir" ]; then
echo "✓ Directory exists: $dir"
else
echo "✗ Directory NOT found: $dir"
fi
doneRepository: ArgentAIOS/argentos-core
Length of output: 208
The Swift directories don't exist—big problem, we need to fix this right now.
Look, this Dependabot config has excellent structure—the grouping strategy is smart, the PR limits are professional, the cooldown periods are solid. Really well done on that. But we've got a major issue here, and it's a real one.
Two of your Swift package directories in the config don't actually exist in the repository:
/apps/shared/MoltbotKit— not found/Swabble— not found
These are referenced in lines 54-74 of the dependabot.yml, but they're not in the repo. Dependabot will fail on these entries. You need to either:
- Remove the non-existent directories from the configuration, or
- Create these directories if they should exist
The apps/macos and apps/android directories check out fine—those are good. But get those Swift entries fixed immediately. This is critical.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/dependabot.yml around lines 1 - 113, Dependabot is configured to run
Swift updates for directories "/apps/shared/MoltbotKit" and "/Swabble" which do
not exist; either remove the two swift update blocks referencing those
directories (the package-ecosystem: swift entries with directory:
/apps/shared/MoltbotKit and directory: /Swabble) from .github/dependabot.yml or
create the missing directories and add valid Swift package manifests there so
Dependabot can run; ensure you keep the working swift block for directory:
/apps/macos and the other ecosystems unchanged.
| - name: Select Xcode 26.1 | ||
| run: | | ||
| sudo xcode-select -s /Applications/Xcode_26.1.app | ||
| xcodebuild -version |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What Xcode versions are available on GitHub Actions macos-latest runner March 2026?
💡 Result:
On the GitHub Actions macos-latest runner (macOS 15 arm64) in March 2026, the available Xcode versions are: 16.4 (default), 16.3, 16.0, 26.0.1, 26.1.1, 26.2, and 26.3. To switch to a specific version, use: sudo xcode-select -s "/Applications/Xcode_X.Y.app/Contents/Developer" where X.Y is the version (e.g., Xcode_16.4.app). macos-latest labels the arm64 macOS 15 runner, as macOS 26 arm64 uses explicit macos-26 labels per official documentation. Images update weekly; latest as of early March 2026 (image version 20260303.0188.2) lists these Xcodes via runner-images Readme and release notes.
Citations:
- 1: https://newreleases.io/project/github/actions/runner-images/release/macos-15-arm64%2F20260303.0188
- 2: https://github.com/actions/virtual-environments
- 3: https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md
- 4: https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md
Fix Xcode version—26.1 doesn't exist on the runner, only 26.1.1 and beyond!
Look, this is a huge problem. You're trying to select /Applications/Xcode_26.1.app on macos-latest, but here's the thing—26.1 is NOT available on GitHub Actions right now. The actual versions available are 26.0.1, 26.1.1, 26.2, and 26.3. Your job is going to fail immediately when it tries to select a non-existent app directory. You need to change this to Xcode_26.1.1.app or use one of the other available versions. Believe me, this is not working as-is.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/ci.yml around lines 393 - 396, The workflow step named
"Select Xcode 26.1" is selecting a non-existent path
(/Applications/Xcode_26.1.app); update that run command to point to an available
Xcode bundle (for example /Applications/Xcode_26.1.1.app) or another supported
version (26.0.1, 26.2, 26.3) so xcode-select -s uses a real installation and
xcodebuild -version succeeds.
| on: | ||
| pull_request_target: | ||
| types: [opened, synchronize, reopened] | ||
| issues: | ||
| types: [opened] |
There was a problem hiding this comment.
We've got a little trigger issue here, folks—needs attention!
Look, I'm a big fan of automation, the biggest, but we have a situation. Your workflow triggers on BOTH pull_request_target AND issues events (lines 4-7), but the label job runs on all events and tries to access context.payload.pull_request which will be undefined for issue events.
The early return on line 34-36 saves you from a crash, but both jobs will run on both event types, wasting compute. That's not how we make workflows great again!
🔧 Proposed fix to scope jobs to their respective events
jobs:
label:
+ if: github.event_name == 'pull_request_target'
permissions:
contents: read
pull-requests: write label-issues:
+ if: github.event_name == 'issues'
permissions:
issues: write🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/labeler.yml around lines 3 - 7, The workflow currently
triggers on both pull_request_target and issues but the label job assumes
context.payload.pull_request exists (used in the early return), so scope jobs to
their relevant events: update the label job to run only when github.event_name
== 'pull_request_target' (or check context.payload.pull_request) and any
issue-only job to run only when github.event_name == 'issues'; use job-level if
conditions (referencing the label job and context.payload.pull_request) so the
label job won't execute for issue events and compute won't be wasted.
| const [avatarState, setAvatarState] = useState<AvatarState>("idle"); | ||
| const [avatarMood, setAvatarMood] = useState<MoodName | undefined>(undefined); | ||
| const [surfaceProfile, setSurfaceProfile] = useState<DashboardSurfaceProfile>("public-core"); | ||
| const [surfaceProfile, setSurfaceProfile] = useState<DashboardSurfaceProfile>("full"); |
There was a problem hiding this comment.
Starting on "full" will seed a stale Operations workspace.
Big UX problem. The add-only operations-tab effect runs before the async profile fetch, so Line 1110 makes the tab appear on first mount even for installs that should resolve to public-core. Then Lines 1301-1303 do the same thing on transient settings failures. Since nothing removes that tab afterward, it gets persisted to argent-workspaces and users can keep landing on a workspace they are not allowed to use.
Also applies to: 1301-1303
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dashboard/src/App.tsx` at line 1110, The component currently seeds
surfaceProfile to "full" which causes the add-only operations tab to appear
before the async profile fetch and on transient failures; change the initial
useState for surfaceProfile to a neutral value (e.g., undefined or null) and
only call setSurfaceProfile("full" | "public-core" etc.) after the async fetch
resolves successfully; update the effect that adds the operations tab to run
only when surfaceProfile is explicitly "full" (guard on surfaceProfile !==
undefined) and stop writing/persisting the operations workspace on transient
settings errors—do not setSurfaceProfile("full") in the transient-failure paths
(the code referenced by setSurfaceProfile and the add-operations effect should
be the targets).
| const [workspaceTabs, setWorkspaceTabs] = useState<WorkspaceTab[]>(() => { | ||
| try { | ||
| const stored = localStorage.getItem("argent-workspaces"); | ||
| if (stored) { | ||
| const parsed = JSON.parse(stored) as WorkspaceTab[]; | ||
| return sanitizeWorkspaceTabs(parsed, false); | ||
| } | ||
| if (stored) return JSON.parse(stored); | ||
| } catch {} | ||
| return DEFAULT_WORKSPACE_TABS; | ||
| return [{ id: "home", name: "Home", icon: "🏠" }]; | ||
| }); |
There was a problem hiding this comment.
Validate argent-workspaces before you trust it.
Right now any JSON value is accepted. If storage contains null, an object, or a legacy shape, the first render reaches workspaceTabs.map(...) and the dashboard falls over. We need the old sanitize/fallback step back here.
🛠️ A tighter initializer
const [workspaceTabs, setWorkspaceTabs] = useState<WorkspaceTab[]>(() => {
try {
const stored = localStorage.getItem("argent-workspaces");
- if (stored) return JSON.parse(stored);
+ if (stored) {
+ const parsed = JSON.parse(stored);
+ if (Array.isArray(parsed)) {
+ const tabs = parsed.filter(
+ (tab): tab is WorkspaceTab =>
+ tab &&
+ typeof tab === "object" &&
+ typeof tab.id === "string" &&
+ typeof tab.name === "string" &&
+ typeof tab.icon === "string",
+ );
+ if (tabs.length > 0) return tabs;
+ }
+ }
} catch {}
return [{ id: "home", name: "Home", icon: "🏠" }];
});🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@dashboard/src/App.tsx` around lines 1119 - 1125, The localStorage initializer
for workspaceTabs accepts any JSON and can return invalid shapes (null, object,
legacy), causing workspaceTabs.map to crash; update the initializer (the
useState call that defines workspaceTabs and setWorkspaceTabs) to parse
"argent-workspaces", verify the parsed value is an Array, and that each item
conforms to the WorkspaceTab shape (has required properties like id and name,
optional icon), filter/transform valid entries, and fall back to the default [{
id: "home", name: "Home", icon: "🏠" }] if validation fails or parsing throws.
| return ( | ||
| label === resolveGatewayLaunchAgentLabel() || IGNORED_FIRST_PARTY_LAUNCHD_LABELS.has(label) | ||
| ); | ||
| return label === resolveGatewayLaunchAgentLabel(); |
There was a problem hiding this comment.
Restore first-party launchd label filtering here — this change causes false positives.
At Line 129, narrowing ignore logic to only the gateway label means first-party services like ai.argent.node, ai.argent.dashboard-ui, and ai.argent.dashboard-api now flow into scanLaunchdDir results as “extra” services. That’s a big regression risk for onboarding/service cleanup UX.
Suggested fix
-import {
- GATEWAY_SERVICE_KIND,
- GATEWAY_SERVICE_MARKER,
- resolveGatewayLaunchAgentLabel,
- resolveGatewaySystemdServiceName,
- resolveGatewayWindowsTaskName,
-} from "./constants.js";
+import {
+ GATEWAY_SERVICE_KIND,
+ GATEWAY_SERVICE_MARKER,
+ resolveDashboardApiLaunchAgentLabel,
+ resolveDashboardUiLaunchAgentLabel,
+ resolveGatewayLaunchAgentLabel,
+ resolveGatewaySystemdServiceName,
+ resolveGatewayWindowsTaskName,
+ resolveNodeLaunchAgentLabel,
+} from "./constants.js";+const IGNORED_FIRST_PARTY_LAUNCHD_LABELS = new Set<string>([
+ resolveGatewayLaunchAgentLabel(),
+ resolveNodeLaunchAgentLabel(),
+ resolveDashboardUiLaunchAgentLabel(),
+ resolveDashboardApiLaunchAgentLabel(),
+]);
+
function isIgnoredLaunchdLabel(label: string): boolean {
- return label === resolveGatewayLaunchAgentLabel();
+ return IGNORED_FIRST_PARTY_LAUNCHD_LABELS.has(label);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/daemon/inspect.ts` at line 129, The change narrows ignored launchd labels
to only resolveGatewayLaunchAgentLabel(), causing first-party services (e.g.,
ai.argent.node, ai.argent.dashboard-ui, ai.argent.dashboard-api) to be reported
as “extra”; update the filtering logic in the function that returns label ===
resolveGatewayLaunchAgentLabel() so it excludes the full set of first-party
launchd labels instead of just the gateway label—use a predicate or list (e.g.,
an array of known first-party labels) and check against it where scanLaunchdDir
results are processed (refer to resolveGatewayLaunchAgentLabel(),
scanLaunchdDir, and the label variable) to restore the original exclusion
behavior.
| try { | ||
| await fs.access(path.join(currentRoot, ".git")); | ||
| return null; | ||
| } catch { | ||
| // Not a source checkout; keep considering installed runtime snapshots. | ||
| } |
There was a problem hiding this comment.
Don't let .git override the explicit install package dir.
Big regression. If ARGENT_INSTALL_PACKAGE_DIR is set, this early return null still fires inside a real checkout, so the service falls back to the repo build instead of the requested runtime snapshot. Keep the .git shortcut for the default ~/.argentos/... probe, but let the explicit override win. I’d also add the matching regression test.
💡 Suggested fix
async function resolveInstalledCliEntrypointPathForService(): Promise<string | null> {
const stateDir =
process.env.ARGENT_STATE_DIR ||
(process.env.HOME ? path.join(process.env.HOME, ".argentos") : undefined);
+ const hasExplicitInstallPackageDir = Boolean(
+ process.env.ARGENT_INSTALL_PACKAGE_DIR?.trim(),
+ );
const installPackageDir =
process.env.ARGENT_INSTALL_PACKAGE_DIR ||
(stateDir ? path.join(stateDir, "lib", "node_modules", "argentos") : undefined);
@@
if (currentArgv1) {
const currentRoot = resolveProjectRootFromEntrypoint(currentArgv1);
const installedRoot = resolveProjectRootFromEntrypoint(resolvedInstalledCliPath);
- try {
- await fs.access(path.join(currentRoot, ".git"));
- return null;
- } catch {
- // Not a source checkout; keep considering installed runtime snapshots.
- }
+ if (!hasExplicitInstallPackageDir) {
+ try {
+ await fs.access(path.join(currentRoot, ".git"));
+ return null;
+ } catch {
+ // Not a source checkout; keep considering installed runtime snapshots.
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try { | |
| await fs.access(path.join(currentRoot, ".git")); | |
| return null; | |
| } catch { | |
| // Not a source checkout; keep considering installed runtime snapshots. | |
| } | |
| async function resolveInstalledCliEntrypointPathForService(): Promise<string | null> { | |
| const stateDir = | |
| process.env.ARGENT_STATE_DIR || | |
| (process.env.HOME ? path.join(process.env.HOME, ".argentos") : undefined); | |
| const hasExplicitInstallPackageDir = Boolean( | |
| process.env.ARGENT_INSTALL_PACKAGE_DIR?.trim(), | |
| ); | |
| const installPackageDir = | |
| process.env.ARGENT_INSTALL_PACKAGE_DIR || | |
| (stateDir ? path.join(stateDir, "lib", "node_modules", "argentos") : undefined); | |
| if (currentArgv1) { | |
| const currentRoot = resolveProjectRootFromEntrypoint(currentArgv1); | |
| const installedRoot = resolveProjectRootFromEntrypoint(resolvedInstalledCliPath); | |
| if (!hasExplicitInstallPackageDir) { | |
| try { | |
| await fs.access(path.join(currentRoot, ".git")); | |
| return null; | |
| } catch { | |
| // Not a source checkout; keep considering installed runtime snapshots. | |
| } | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/daemon/program-args.ts` around lines 119 - 124, The early return when a
.git directory is found is overriding an explicit install snapshot override;
update the logic in the function that inspects currentRoot (references to
currentRoot and the fs.access(".git") check) to first detect if
ARGENT_INSTALL_PACKAGE_DIR (process.env.ARGENT_INSTALL_PACKAGE_DIR or the config
variable used) is set and, if so, skip the .git early-return path so the
explicit install dir wins; adjust the try/catch block so it only returns null
for a repo checkout when no ARGENT_INSTALL_PACKAGE_DIR is provided, and add a
regression test that sets ARGENT_INSTALL_PACKAGE_DIR and ensures the code
prefers the install package dir rather than falling back to the repo build.
| cron: { stop: () => void }; | ||
| heartbeatRunner: HeartbeatRunner; | ||
| contemplationRunner: ContemplationRunner; | ||
| executionWorkerRunner: ExecutionWorkerRunner; | ||
| jobOrchestratorRunner: JobOrchestratorRunner; | ||
| sisRunner: SisRunner; | ||
| consciousnessKernelRunner: ConsciousnessKernelRunner; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify JobOrchestratorRunner type definition
echo "=== JobOrchestratorRunner type definition ==="
rg -n "export type JobOrchestratorRunner" -A 5
echo ""
echo "=== Check if stop method exists anywhere in job-orchestrator files ==="
ast-grep --pattern 'stop() {
$$$
}'Repository: ArgentAIOS/argentos-core
Length of output: 283
Fix this JobOrchestratorRunner disaster—massive type mismatch!
We've got a huge problem here, folks. JobOrchestratorRunner is defined as Record<string, never> (total empty type), but line 90 is calling .stop() on it. That's going to blow up at runtime—total nightmare! Either add the stop() method to the type definition or get rid of this runner requirement. This is a big one. We need to fix it now—not later, now.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/gateway/server-close.ts` around lines 24 - 30, The JobOrchestratorRunner
type is currently incompatible with code that calls .stop() on it; update the
type or the shutdown call so they match: either change the JobOrchestratorRunner
type definition to include a stop(): void (or stop: () => Promise<void> if
async) so it exposes the stop method, or make the property optional and guard
the call (e.g., if (jobOrchestratorRunner?.stop) jobOrchestratorRunner.stop()),
and ensure the shutdown sequence that invokes .stop() (the server close/shutdown
routine that iterates
cron/heartbeatRunner/contemplationRunner/executionWorkerRunner/jobOrchestratorRunner/...)
reflects the chosen signature (synchronous vs async) so types and runtime
behavior align.
| params.cron.stop(); | ||
| params.heartbeatRunner.stop(); | ||
| params.contemplationRunner.stop(); | ||
| params.executionWorkerRunner.stop(); | ||
| params.jobOrchestratorRunner.stop(); | ||
| params.sisRunner.stop(); | ||
| params.consciousnessKernelRunner.stop(); |
There was a problem hiding this comment.
We removed the safety nets—not good, not good at all!
The previous implementation had defensive shutdown handling that was absolutely tremendous—it caught errors and kept going. Now we're just calling .stop() directly without any try-catch protection. If any of these runners throws an exception—and believe me, things can go wrong—the entire shutdown sequence stops dead in its tracks. Redis stays open, storage adapters don't close, WebSocket connections hang around. It's a mess, a complete mess.
This is especially concerning because:
- The AI summary confirms tests covering "missing runner handles" were deleted
- These are synchronous calls that could throw synchronous exceptions
We need error handling here, folks. Make shutdown great again!
🛡️ Proposed fix to add defensive error handling
- params.cron.stop();
- params.heartbeatRunner.stop();
- params.contemplationRunner.stop();
- params.executionWorkerRunner.stop();
- params.jobOrchestratorRunner.stop();
- params.sisRunner.stop();
- params.consciousnessKernelRunner.stop();
+ try { params.cron.stop(); } catch { /* ignore */ }
+ try { params.heartbeatRunner.stop(); } catch { /* ignore */ }
+ try { params.contemplationRunner.stop(); } catch { /* ignore */ }
+ try { params.executionWorkerRunner.stop(); } catch { /* ignore */ }
+ try { params.jobOrchestratorRunner.stop(); } catch { /* ignore */ }
+ try { params.sisRunner.stop(); } catch { /* ignore */ }
+ try { params.consciousnessKernelRunner.stop(); } catch { /* ignore */ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| params.cron.stop(); | |
| params.heartbeatRunner.stop(); | |
| params.contemplationRunner.stop(); | |
| params.executionWorkerRunner.stop(); | |
| params.jobOrchestratorRunner.stop(); | |
| params.sisRunner.stop(); | |
| params.consciousnessKernelRunner.stop(); | |
| try { params.cron.stop(); } catch { /* ignore */ } | |
| try { params.heartbeatRunner.stop(); } catch { /* ignore */ } | |
| try { params.contemplationRunner.stop(); } catch { /* ignore */ } | |
| try { params.executionWorkerRunner.stop(); } catch { /* ignore */ } | |
| try { params.jobOrchestratorRunner.stop(); } catch { /* ignore */ } | |
| try { params.sisRunner.stop(); } catch { /* ignore */ } | |
| try { params.consciousnessKernelRunner.stop(); } catch { /* ignore */ } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/gateway/server-close.ts` around lines 86 - 92, The direct calls to
params.cron.stop(), params.heartbeatRunner.stop(),
params.contemplationRunner.stop(), params.executionWorkerRunner.stop(),
params.jobOrchestratorRunner.stop(), params.sisRunner.stop(), and
params.consciousnessKernelRunner.stop() can throw and abort shutdown; wrap each
.stop() call in a defensive try-catch (or implement a small helper
safeStop(name, runner) that calls runner.stop() inside try-catch) so that if one
runner throws we log the error via the available logger (e.g.,
params.logger.error or console.error) including the runner name and error
details, then continue to the next stop call to ensure full shutdown proceeds.
| params.heartbeatRunner.stop(); | ||
| params.contemplationRunner.stop(); | ||
| params.executionWorkerRunner.stop(); | ||
| params.jobOrchestratorRunner.stop(); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check all runner type definitions for consistency
echo "=== All Runner type exports ==="
rg -n "export type.*Runner\s*=" src/infra/ -A 3
echo ""
echo "=== Check if JobOrchestratorRunner has any actual implementation ==="
rg -n "JobOrchestratorRunner" --type tsRepository: ArgentAIOS/argentos-core
Length of output: 3828
🏁 Script executed:
# Check the actual implementation of startJobOrchestratorRunner
echo "=== startJobOrchestratorRunner implementation ==="
cat -n src/infra/job-orchestrator-runner.ts | head -20
echo ""
echo "=== How jobOrchestratorRunner is assigned in server.impl.ts ==="
sed -n '725,735p' src/gateway/server.impl.ts
echo ""
echo "=== Check server-close.ts context around line 90 ==="
sed -n '85,95p' src/gateway/server-close.ts
echo ""
echo "=== Check if TypeScript compilation catches this ==="
rg "jobOrchestratorRunner" src/gateway/server-close.ts -B 2 -A 2Repository: ArgentAIOS/argentos-core
Length of output: 1827
🏁 Script executed:
# Check if there are type assertions or casts hiding this
echo "=== Check for type assertions around jobOrchestratorRunner assignment ==="
sed -n '725,735p' src/gateway/server.impl.ts
echo ""
echo "=== Check type context in server-close.ts for the parameter ==="
sed -n '20,35p' src/gateway/server-close.ts
echo ""
echo "=== Search for any 'as' casts or type assertions related to jobOrchestratorRunner ==="
rg "jobOrchestratorRunner.*as\s" src/
echo ""
echo "=== Check the full function signature of server-close ==="
sed -n '1,30p' src/gateway/server-close.tsRepository: ArgentAIOS/argentos-core
Length of output: 3292
🏁 Script executed:
# Check tsconfig and TypeScript settings
echo "=== Check tsconfig.json ==="
cat tsconfig.json | head -50
echo ""
echo "=== Look for any `@ts-ignore` or `@ts-expect-error` around line 730 in server.impl.ts ==="
sed -n '725,735p' src/gateway/server.impl.ts
echo ""
echo "=== Look for suppressions in server-close.ts around line 90 ==="
sed -n '88,92p' src/gateway/server-close.ts
echo ""
echo "=== Check if there's actually a void being assigned (very literal check) ==="
rg "startJobOrchestratorRunner" src/gateway/server.impl.ts -A 1 -B 1Repository: ArgentAIOS/argentos-core
Length of output: 2002
The JobOrchestratorRunner type is completely broken, and that .stop() call will fail.
Here's the deal: startJobOrchestratorRunner returns void, but you're assigning it to a variable typed as JobOrchestratorRunner — which is Record<string, never> (an empty object). Then you try to call .stop() on it. That's a major winner of a TypeError, believe me.
The function is marked as a stub ("No-op in Core"), but the type system is a disaster. You need to either:
- Make
JobOrchestratorRunneractually include thestop()method (likeSisRunner,HeartbeatRunner, etc. — they're all doing it the right way), or - Handle the void return properly instead of pretending it's a real runner
With TypeScript's strict mode on, this should already be screaming at you with compilation errors. Fix this type — it's a critical mess.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/gateway/server-close.ts` at line 90, The code calls
params.jobOrchestratorRunner.stop() but JobOrchestratorRunner is currently an
empty/void type and startJobOrchestratorRunner returns void, causing a
runtime/type error; fix by making the runner API consistent: update the
JobOrchestratorRunner type to include stop(): Promise<void> (or stop(): void)
like SisRunner/HeartbeatRunner and change startJobOrchestratorRunner to return
an instance implementing that interface, or alternatively change the call site
to treat the start function as void (remove the .stop() call or guard it with if
(params.jobOrchestratorRunner && typeof params.jobOrchestratorRunner.stop ===
'function') await params.jobOrchestratorRunner.stop();). Ensure symbol names
JobOrchestratorRunner and startJobOrchestratorRunner are updated together so the
type system and runtime match.
|
Triaging this as an |
Fix.
Summary by CodeRabbit
Release Notes
New Features
Chores