Compare commits
4 Commits
93216125d6
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 45ac13141c | |||
| 879bdb3005 | |||
| c692ca1c63 | |||
| 2a1dbe540a |
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"nixosConfigDir": "/home/m3tam3re/p/NIX/nixos-config",
|
||||
"m3taHomeDir": "/home/m3tam3re/p/NIX/m3ta-home",
|
||||
"specPath": "/home/m3tam3re/p/NIX/nixos-config/.a5c/inputs/fix-eval-warnings-spec.md"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
Fix the following Nix/Home Manager evaluation warnings except for the gc/nh conflict warning:
|
||||
|
||||
- `evaluation warning: 'system' has been renamed to/replaced by 'stdenv.hostPlatform.system'`
|
||||
- `evaluation warning: m3tam3re profile: programs.ssh.matchBlocks defined in /nix/store/...-users/m3tam3re/identities/private.nix is deprecated. Use programs.ssh.settings.`
|
||||
|
||||
Do not fix or change the warning:
|
||||
|
||||
- `evaluation warning: programs.nh.clean.enable and nix.gc.automatic are both enabled. Please use one or the other to avoid conflict.`
|
||||
|
||||
The private identity source file is in `/home/m3tam3re/p/NIX/m3ta-home/users/m3tam3re/identities/private.nix`.
|
||||
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* @process local/fix-nix-eval-warnings
|
||||
* @description Fix Nix/Home Manager evaluation warnings except the nh/gc conflict warning.
|
||||
* @skill systematic-debugging methodologies/superpowers/systematic-debugging.js
|
||||
* @skill verification-before-completion methodologies/superpowers/verification-before-completion.js
|
||||
* @skill root-cause-diagnosis methodologies/shared/root-cause-diagnosis.js
|
||||
*/
|
||||
|
||||
import { defineTask } from '@a5c-ai/babysitter-sdk';
|
||||
|
||||
const q = (value) => `'${String(value).replace(/'/g, `'\\''`)}'`;
|
||||
|
||||
export async function process(inputs, ctx) {
|
||||
const nixosConfigDir = inputs.nixosConfigDir || '/home/m3tam3re/p/NIX/nixos-config';
|
||||
const m3taHomeDir = inputs.m3taHomeDir || '/home/m3tam3re/p/NIX/m3ta-home';
|
||||
const specPath = inputs.specPath || `${nixosConfigDir}/.a5c/inputs/fix-eval-warnings-spec.md`;
|
||||
|
||||
const spec = await ctx.task(readSpecTask, { specPath });
|
||||
|
||||
const inspection = await ctx.task(inspectWarningSourcesTask, {
|
||||
nixosConfigDir,
|
||||
m3taHomeDir,
|
||||
});
|
||||
|
||||
const implementation = await ctx.task(implementFixesTask, {
|
||||
nixosConfigDir,
|
||||
m3taHomeDir,
|
||||
spec: spec.stdout,
|
||||
inspection: inspection.stdout,
|
||||
});
|
||||
|
||||
const formatting = await ctx.task(formatChangedNixTask, {
|
||||
m3taHomeDir,
|
||||
});
|
||||
|
||||
const verification = await ctx.task(verifyWarningsTask, {
|
||||
nixosConfigDir,
|
||||
m3taHomeDir,
|
||||
});
|
||||
|
||||
const artifacts = await ctx.task(collectArtifactsTask, {
|
||||
nixosConfigDir,
|
||||
m3taHomeDir,
|
||||
verifyStdout: verification.stdout || '',
|
||||
verifyStderr: verification.stderr || '',
|
||||
});
|
||||
|
||||
const acceptance = await ctx.task(acceptanceReviewTask, {
|
||||
spec: spec.stdout,
|
||||
artifacts: artifacts.stdout,
|
||||
});
|
||||
|
||||
if (!acceptance.accepted) {
|
||||
await ctx.breakpoint({
|
||||
title: 'Warning fix acceptance review failed',
|
||||
question: `Acceptance review did not approve the changes: ${acceptance.reason}`,
|
||||
context: {
|
||||
runId: ctx.runId,
|
||||
files: [
|
||||
{ path: `${m3taHomeDir}/users/m3tam3re/identities/private.nix`, format: 'nix', label: 'Private SSH identity' },
|
||||
{ path: `${m3taHomeDir}/profiles/sets/coding/agents/agents.nix`, format: 'nix', label: 'Agent packages' },
|
||||
{ path: `${m3taHomeDir}/profiles/contexts/desktop/default.nix`, format: 'nix', label: 'Desktop packages' },
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
success: acceptance.accepted,
|
||||
summary: implementation.summary,
|
||||
changedFiles: implementation.changedFiles,
|
||||
verification: {
|
||||
formatting: formatting.stdout,
|
||||
warnings: verification.stdout,
|
||||
review: acceptance,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const readSpecTask = defineTask('read-spec', (args, taskCtx) => ({
|
||||
kind: 'shell',
|
||||
title: 'Read warning-fix spec',
|
||||
shell: {
|
||||
command: `cat ${q(args.specPath)}`,
|
||||
expectedExitCode: 0,
|
||||
timeout: 10000,
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['spec', 'shell'],
|
||||
}));
|
||||
|
||||
export const inspectWarningSourcesTask = defineTask('inspect-warning-sources', (args, taskCtx) => ({
|
||||
kind: 'shell',
|
||||
title: 'Inspect current warning sources',
|
||||
shell: {
|
||||
command: [
|
||||
'set -euo pipefail',
|
||||
`echo '== nixos-config status =='`,
|
||||
`cd ${q(args.nixosConfigDir)} && git status --short`,
|
||||
`echo`,
|
||||
`echo '== m3ta-home status =='`,
|
||||
`cd ${q(args.m3taHomeDir)} && git status --short`,
|
||||
`echo`,
|
||||
`echo '== active pkgs.system-style package selectors =='`,
|
||||
`grep -RIn --include='*.nix' -E 'packages[.]\\$\\{pkgs[.]system\\}|packages[.]\\$\\{prev[.]system\\}|packages[.]\\$\\{final[.]system\\}' ${q(args.nixosConfigDir)} ${q(args.m3taHomeDir)} || true`,
|
||||
`echo`,
|
||||
`echo '== SSH matchBlocks in m3ta-home identities =='`,
|
||||
`grep -RIn --include='*.nix' 'matchBlocks' ${q(`${args.m3taHomeDir}/users/m3tam3re/identities`)} || true`,
|
||||
].join('\n'),
|
||||
expectedExitCode: 0,
|
||||
timeout: 30000,
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['diagnosis', 'shell'],
|
||||
}));
|
||||
|
||||
export const implementFixesTask = defineTask('implement-warning-fixes', (args, taskCtx) => ({
|
||||
kind: 'agent',
|
||||
title: 'Implement requested warning fixes',
|
||||
agent: {
|
||||
name: 'worker',
|
||||
prompt: {
|
||||
role: 'Nix/Home Manager maintenance engineer',
|
||||
task: 'Edit the repositories to remove the requested evaluation warnings, excluding the nh/gc warning by request.',
|
||||
context: {
|
||||
nixosConfigDir: args.nixosConfigDir,
|
||||
m3taHomeDir: args.m3taHomeDir,
|
||||
specVerbatim: args.spec,
|
||||
inspectionStdout: args.inspection,
|
||||
},
|
||||
instructions: [
|
||||
'Execute the task fully; do not just provide a plan.',
|
||||
'Do not invoke the babysit skill or create another babysitter run.',
|
||||
'Read every file before editing it.',
|
||||
'Preserve unrelated existing user changes, especially any dirty files in nixos-config such as flake.nix or flake.lock.',
|
||||
'Fix active uses of pkgs.system/prev.system/final.system that trigger the Nixpkgs deprecation warning by using stdenv.hostPlatform.system through the appropriate package set.',
|
||||
'Migrate /home/m3tam3re/p/NIX/m3ta-home/users/m3tam3re/identities/private.nix from programs.ssh.matchBlocks to programs.ssh.settings.',
|
||||
'For programs.ssh.settings, use OpenSSH directive names such as HostName, User, Port, and IdentityFile; do not keep legacy camelCase option names under settings.',
|
||||
'Do not change programs.nh.clean.enable or nix.gc.automatic; the user explicitly excluded that warning.',
|
||||
'Keep the change minimal and focused on the warnings in the spec.',
|
||||
'Run a quick static check of the edited files if practical, but leave deterministic verification to the process quality gate.',
|
||||
],
|
||||
outputFormat: 'JSON with summary, changedFiles, and verificationNotes.',
|
||||
},
|
||||
outputSchema: {
|
||||
type: 'object',
|
||||
required: ['summary', 'changedFiles', 'verificationNotes'],
|
||||
properties: {
|
||||
summary: { type: 'string' },
|
||||
changedFiles: { type: 'array', items: { type: 'string' } },
|
||||
verificationNotes: { type: 'array', items: { type: 'string' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['implementation', 'agent', 'nix'],
|
||||
}));
|
||||
|
||||
export const formatChangedNixTask = defineTask('format-changed-nix', (args, taskCtx) => ({
|
||||
kind: 'shell',
|
||||
title: 'Format changed Nix files',
|
||||
shell: {
|
||||
command: [
|
||||
'set -euo pipefail',
|
||||
`cd ${q(args.m3taHomeDir)}`,
|
||||
`if command -v alejandra >/dev/null 2>&1; then`,
|
||||
` alejandra users/m3tam3re/identities/private.nix profiles/sets/coding/agents/agents.nix profiles/contexts/desktop/default.nix`,
|
||||
`else`,
|
||||
` nix run nixpkgs#alejandra -- users/m3tam3re/identities/private.nix profiles/sets/coding/agents/agents.nix profiles/contexts/desktop/default.nix`,
|
||||
`fi`,
|
||||
].join('\n'),
|
||||
expectedExitCode: 0,
|
||||
timeout: 120000,
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['format', 'shell'],
|
||||
}));
|
||||
|
||||
export const verifyWarningsTask = defineTask('verify-warning-removal', (args, taskCtx) => ({
|
||||
kind: 'shell',
|
||||
title: 'Verify requested warnings are gone',
|
||||
shell: {
|
||||
command: [
|
||||
'set -euo pipefail',
|
||||
`echo '== static checks =='`,
|
||||
`! grep -RIn --include='*.nix' -E 'packages[.]\\$\\{pkgs[.]system\\}|packages[.]\\$\\{prev[.]system\\}|packages[.]\\$\\{final[.]system\\}' ${q(`${args.m3taHomeDir}/profiles`)} || { echo 'Found deprecated package system selector' >&2; exit 1; }`,
|
||||
`! grep -n 'matchBlocks' ${q(`${args.m3taHomeDir}/users/m3tam3re/identities/private.nix`)} || { echo 'private.nix still uses matchBlocks' >&2; exit 1; }`,
|
||||
`grep -n 'settings = {' ${q(`${args.m3taHomeDir}/users/m3tam3re/identities/private.nix`)}`,
|
||||
`echo`,
|
||||
`echo '== nix eval m3-ares =='`,
|
||||
`cd ${q(args.nixosConfigDir)}`,
|
||||
`eval_stdout=$(mktemp)`,
|
||||
`eval_stderr=$(mktemp)`,
|
||||
`set +e`,
|
||||
`nix eval .#nixosConfigurations.m3-ares.config.system.build.toplevel.drvPath --show-trace >"$eval_stdout" 2>"$eval_stderr"`,
|
||||
`status=$?`,
|
||||
`set -e`,
|
||||
`cat "$eval_stdout"`,
|
||||
`cat "$eval_stderr" >&2`,
|
||||
`if [ "$status" -ne 0 ]; then exit "$status"; fi`,
|
||||
`if grep -F "'system' has been renamed" "$eval_stderr"; then echo 'Deprecated system warning still present' >&2; exit 1; fi`,
|
||||
`if grep -F 'programs.ssh.matchBlocks' "$eval_stderr"; then echo 'Deprecated SSH matchBlocks warning still present' >&2; exit 1; fi`,
|
||||
`if grep -F 'programs.nh.clean.enable and nix.gc.automatic' "$eval_stderr" >/dev/null; then echo 'Allowed nh/gc warning remains by request.'; fi`,
|
||||
].join('\n'),
|
||||
expectedExitCode: 0,
|
||||
timeout: 300000,
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['verification', 'shell', 'nix'],
|
||||
}));
|
||||
|
||||
export const collectArtifactsTask = defineTask('collect-artifacts', (args, taskCtx) => ({
|
||||
kind: 'shell',
|
||||
title: 'Collect diffs and verification output',
|
||||
shell: {
|
||||
command: [
|
||||
'set -euo pipefail',
|
||||
`echo '== m3ta-home diff =='`,
|
||||
`cd ${q(args.m3taHomeDir)} && git diff -- users/m3tam3re/identities/private.nix profiles/sets/coding/agents/agents.nix profiles/contexts/desktop/default.nix`,
|
||||
`echo`,
|
||||
`echo '== nixos-config diff (should not include warning fix unless needed) =='`,
|
||||
`cd ${q(args.nixosConfigDir)} && git diff -- overlays/default.nix flake.nix flake.lock || true`,
|
||||
`echo`,
|
||||
`echo '== verification stdout =='`,
|
||||
`cat <<'VERIFY_STDOUT'`,
|
||||
args.verifyStdout || '',
|
||||
`VERIFY_STDOUT`,
|
||||
`echo`,
|
||||
`echo '== verification stderr =='`,
|
||||
`cat <<'VERIFY_STDERR'`,
|
||||
args.verifyStderr || '',
|
||||
`VERIFY_STDERR`,
|
||||
].join('\n'),
|
||||
expectedExitCode: 0,
|
||||
timeout: 30000,
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['artifacts', 'shell'],
|
||||
}));
|
||||
|
||||
export const acceptanceReviewTask = defineTask('acceptance-review', (args, taskCtx) => ({
|
||||
kind: 'agent',
|
||||
title: 'Review changes against requested warning fixes',
|
||||
agent: {
|
||||
name: 'reviewer',
|
||||
prompt: {
|
||||
role: 'Acceptance reviewer for a Nix/Home Manager warning fix',
|
||||
task: 'Compare SPEC to ARTIFACTS directly and decide whether the requested warnings were fixed without touching the excluded nh/gc warning.',
|
||||
instructions: [
|
||||
'Ignore any narrative in your context about how ARTIFACTS were built.',
|
||||
'Do not ask for additional changes unless they are required by the SPEC.',
|
||||
'Accept if the system deprecation warning and private SSH matchBlocks warning are addressed, and the nh/gc conflict remains untouched.',
|
||||
'',
|
||||
'SPEC (verbatim):',
|
||||
'---',
|
||||
args.spec,
|
||||
'---',
|
||||
'',
|
||||
'ARTIFACTS (verbatim):',
|
||||
'---',
|
||||
args.artifacts,
|
||||
'---',
|
||||
'',
|
||||
'Compare SPEC to ARTIFACTS directly. Ignore any narrative in your context about how ARTIFACTS were built.',
|
||||
],
|
||||
outputFormat: 'JSON with accepted boolean, reason string, and checkedCriteria array.',
|
||||
},
|
||||
outputSchema: {
|
||||
type: 'object',
|
||||
required: ['accepted', 'reason', 'checkedCriteria'],
|
||||
properties: {
|
||||
accepted: { type: 'boolean' },
|
||||
reason: { type: 'string' },
|
||||
checkedCriteria: { type: 'array', items: { type: 'string' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
io: {
|
||||
inputJsonPath: `tasks/${taskCtx.effectId}/input.json`,
|
||||
outputJsonPath: `tasks/${taskCtx.effectId}/output.json`,
|
||||
},
|
||||
labels: ['acceptance', 'agent', 'review'],
|
||||
}));
|
||||
Generated
+35
-35
@@ -50,11 +50,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1780736323,
|
||||
"narHash": "sha256-b4CfjbWTT+5Z0XBI2/W2DnybwkYVwLxghCwXVmw9+Iw=",
|
||||
"lastModified": 1781348569,
|
||||
"narHash": "sha256-1BJtmKSqtD0CD753ZE37RgxvCJK6Iw3iKLDDaS8trY4=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "b0c832c9e02d8b3d8ad091f022c859382a037afd",
|
||||
"revCount": 26,
|
||||
"rev": "75a2ed2533b4d6d8e4a34acd37e83d98d81a5fb0",
|
||||
"revCount": 30,
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@code.m3ta.dev/m3tam3re/agent-lib"
|
||||
},
|
||||
@@ -344,11 +344,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781147591,
|
||||
"narHash": "sha256-ZdD4KNeFjIfdCT3J2eRgCiYBucJsQTXMT5+XssstbOY=",
|
||||
"lastModified": 1781317940,
|
||||
"narHash": "sha256-uMVOhV6pVPgm2hn1WGEbIcJRWjnsyWKy8PHCUn0++iI=",
|
||||
"owner": "AvengeMedia",
|
||||
"repo": "dms-plugin-registry",
|
||||
"rev": "bb7f6f61189121435e7b9724ca4f49d904aaa112",
|
||||
"rev": "4ab59f3da3df33bf106045b856db8de875cc42c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -501,11 +501,11 @@
|
||||
"uv2nix": "uv2nix_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781150804,
|
||||
"narHash": "sha256-SDccCmUejmY/tROZRduFejEmsXEZvOA399zOv2Q2m/k=",
|
||||
"lastModified": 1781346807,
|
||||
"narHash": "sha256-ytT4ojx0qFW4b/oYeW+MkmaA3b/BZ9pqkPmpAg8j1gg=",
|
||||
"owner": "NousResearch",
|
||||
"repo": "hermes-agent",
|
||||
"rev": "3e74f75e41ecd5a3b937d692ba7dcffbf77304f6",
|
||||
"rev": "2a5dc0ef3df433a36abed9ee544ea067d807c438",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -585,11 +585,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781129616,
|
||||
"narHash": "sha256-Hl0Pz/QIKpePSU7SdK3BMe5VNmUhFvfWyg57GyawxzE=",
|
||||
"lastModified": 1781305496,
|
||||
"narHash": "sha256-g8Vv4Qfc7n+lgov97REu3X6BeJtvYY0hlSUZR1GrGQQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "7dbd305f8b81050f223f00bcfbc8a6b74e048806",
|
||||
"rev": "c87a39aa979acc4848016d2220c6238390d84779",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -630,11 +630,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781140202,
|
||||
"narHash": "sha256-hEIq258CpHUlpCjk4gDf8rTXxWaTEvH30oEWf5BrTFg=",
|
||||
"lastModified": 1781330261,
|
||||
"narHash": "sha256-2fFAGel2VVXr5mwrTXldqXva2ng3T3HHxyuBKRIxauI=",
|
||||
"owner": "numtide",
|
||||
"repo": "llm-agents.nix",
|
||||
"rev": "bb53759b44fff85eea34903064abe14085e31317",
|
||||
"rev": "24ec6b7b1ddf8896ac8df3b65dc564575e0a1928",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -660,11 +660,11 @@
|
||||
"nur": "nur"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781155207,
|
||||
"narHash": "sha256-ZY8Cw5t8omijjYYm7akn3B2qir+ascwBQzER2Ps1DrQ=",
|
||||
"lastModified": 1781348716,
|
||||
"narHash": "sha256-viUQs4x2KGYNKDbcZJAb48EnJAgMD2ENDHajPUn5lN0=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "1265dea16a6ab5c227113fe5fe02ddef3696524f",
|
||||
"revCount": 56,
|
||||
"rev": "d1494476b864173592c6dc4a1f0645189cdca192",
|
||||
"revCount": 61,
|
||||
"type": "git",
|
||||
"url": "ssh://gitea@code.m3ta.dev/m3tam3re/m3ta-home"
|
||||
},
|
||||
@@ -920,11 +920,11 @@
|
||||
},
|
||||
"nixpkgs-master_3": {
|
||||
"locked": {
|
||||
"lastModified": 1781153468,
|
||||
"narHash": "sha256-ZBRmjFtJn/XmHBV230OSabKQqxOoOJunJmBtSt1sLs0=",
|
||||
"lastModified": 1781160346,
|
||||
"narHash": "sha256-fYh977TEG3NQN8sAQRMVtyuidoiqKuRRgrMWLD+s01A=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "cd265fd6b43f2ec1257c2e400f648895d2ad7ccd",
|
||||
"rev": "9e70637b2cb27f7d49c852f9fb7e0080ae953adb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -984,11 +984,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1780930886,
|
||||
"narHash": "sha256-rppURzHviaQN131F+nLiLdGfcb0uCd9gGP0E5+iw9MI=",
|
||||
"lastModified": 1781268102,
|
||||
"narHash": "sha256-Zn5KTggEmUB3lXn/ccERNcBdddE6IaOFber9dWViWDg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8c3cede7ddc26bd659d2d383b5610efbd2c7a16e",
|
||||
"rev": "49a4bd0573c376468dd7996ddb6f9fa31d8c4d97",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1032,11 +1032,11 @@
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1780749050,
|
||||
"narHash": "sha256-3av0pIjlOWQ6rDbNOmpUSvbNnJkGORQKKjb4LtCZsIY=",
|
||||
"lastModified": 1781074563,
|
||||
"narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a799d3e3886da994fa307f817a6bc705ae538eeb",
|
||||
"rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1143,11 +1143,11 @@
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781153862,
|
||||
"narHash": "sha256-inru9e3OUY4xIf9xZjjNdEQsO3hq9qP6sc0IzxO4m10=",
|
||||
"lastModified": 1781346642,
|
||||
"narHash": "sha256-o92OOSMAB08HQgG7pW2BZVIO53Pkv4oAjLk4Iol3Iko=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "693d3fb2b087955a22098417dbbfd5b0020be50a",
|
||||
"rev": "6e4e8d731fbb3831296607d5f88de727cf7bf6de",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1164,11 +1164,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781153862,
|
||||
"narHash": "sha256-inru9e3OUY4xIf9xZjjNdEQsO3hq9qP6sc0IzxO4m10=",
|
||||
"lastModified": 1781158001,
|
||||
"narHash": "sha256-cg+genglm+qSyQ0nvu6cvpTuxkpYMw1Oi9GrtXPy6cI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "693d3fb2b087955a22098417dbbfd5b0020be50a",
|
||||
"rev": "e2af4a27c10f1ed1e6b55fb2de40cefe3f4a55e6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -18,66 +18,6 @@
|
||||
vercel = [];
|
||||
};
|
||||
|
||||
agentLibSharedSkillsDir = ".agents/skills";
|
||||
|
||||
agentLibHomeManagerStub = {lib, ...}: {
|
||||
options.home.homeDirectory = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/hermes";
|
||||
};
|
||||
options.home.file = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
executable = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.bool;
|
||||
default = null;
|
||||
};
|
||||
force = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
ignorelinks = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
onChange = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
};
|
||||
recursive = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
source = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
};
|
||||
target = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
};
|
||||
text = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
}));
|
||||
default = {};
|
||||
};
|
||||
options.home.packages = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [];
|
||||
};
|
||||
options.assertions = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [];
|
||||
};
|
||||
};
|
||||
|
||||
agentLibSourceSelections =
|
||||
lib.mapAttrs (_sourceName: exclude: {
|
||||
skills = {
|
||||
@@ -87,63 +27,15 @@
|
||||
})
|
||||
agentSkillExclusions;
|
||||
|
||||
# Evaluate agent-lib's Hermes target renderer with a minimal Home Manager
|
||||
# surface, then expose its selected shared-skill outputs as a single Nix store
|
||||
# directory for hermes-agent's native `skills.external_dirs` setting. The full
|
||||
# Home Manager module is not imported into this NixOS host because Hermes runs
|
||||
# as a system service user rather than a managed login user's Home Manager
|
||||
# generation.
|
||||
agentLibEval = lib.evalModules {
|
||||
specialArgs = {inherit pkgs;};
|
||||
modules = [
|
||||
agentLibHomeManagerStub
|
||||
inputs.agent-lib.homeManagerModules.default
|
||||
{
|
||||
home.homeDirectory = "/var/lib/hermes";
|
||||
programs.agent-lib = {
|
||||
enable = true;
|
||||
lockFile = ../../../agent-sources.lock.json;
|
||||
shared.skillsDir = agentLibSharedSkillsDir;
|
||||
targets.hermes.enable = true;
|
||||
profiles.default.sources = agentLibSourceSelections;
|
||||
};
|
||||
}
|
||||
];
|
||||
# Deterministic store renderer consumed directly by Hermes. m3ta-home
|
||||
# re-exports the focused helper so nixos-config does not need a direct
|
||||
# agent-lib flake input.
|
||||
hermesSkills = inputs.m3ta-home.lib.mkHermesSkillsDir {
|
||||
system = pkgs.stdenv.hostPlatform.system;
|
||||
name = "hermes-agent-lib-skills";
|
||||
lockFile = ../../../agent-sources.lock.json;
|
||||
sources = agentLibSourceSelections;
|
||||
};
|
||||
|
||||
agentLibFailedAssertions = lib.filter (assertion: !assertion.assertion) agentLibEval.config.assertions;
|
||||
|
||||
agentLibHomeFiles =
|
||||
if agentLibFailedAssertions != []
|
||||
then throw (builtins.head agentLibFailedAssertions).message
|
||||
else agentLibEval.config.home.file;
|
||||
|
||||
hermesSkillHomeFiles =
|
||||
lib.filterAttrs (
|
||||
targetPath: file:
|
||||
lib.hasPrefix "${agentLibSharedSkillsDir}/" targetPath
|
||||
&& file ? source
|
||||
&& file.source != null
|
||||
)
|
||||
agentLibHomeFiles;
|
||||
|
||||
linkHermesSkill = targetPath: file: let
|
||||
skillName = lib.removePrefix "${agentLibSharedSkillsDir}/" targetPath;
|
||||
in ''
|
||||
ln -s ${file.source} "$out"/${lib.escapeShellArg skillName}
|
||||
'';
|
||||
|
||||
# Deterministic store renderer consumed directly by Hermes. Each entry is a
|
||||
# symlink to the immutable skill directory selected by agent-lib, so
|
||||
# `$out/<skill>/SKILL.md` exists without a mutable copy service.
|
||||
hermesSkills =
|
||||
if hermesSkillHomeFiles == {}
|
||||
then throw "agent-lib: Hermes skill selection produced no skills"
|
||||
else
|
||||
pkgs.runCommand "hermes-agent-lib-skills" {} ''
|
||||
mkdir -p $out
|
||||
${lib.concatMapAttrsStringSep "\n" linkHermesSkill hermesSkillHomeFiles}
|
||||
'';
|
||||
in {
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
@@ -179,6 +71,7 @@ in {
|
||||
];
|
||||
|
||||
extraPackages = with pkgs; [
|
||||
basecamp
|
||||
docker
|
||||
git
|
||||
curl
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
# m3ta-home via the profile mapping in hosts/common/users/m3tam3re.nix.
|
||||
{
|
||||
config,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
@@ -15,6 +14,8 @@ with lib; {
|
||||
config = mkMerge [
|
||||
# ── XDG / MIME defaults ──
|
||||
{
|
||||
qt.platformTheme.name = mkForce "qtct";
|
||||
|
||||
xdg = {
|
||||
enable = true;
|
||||
configFile."mimeapps.list".force = true;
|
||||
@@ -58,6 +59,22 @@ with lib; {
|
||||
"6, monitor:DP-2"
|
||||
"7, monitor:DP-2"
|
||||
];
|
||||
# m3ta-home sets QT_QPA_PLATFORMTHEME=gtk3 globally for Hyprland.
|
||||
# ksnip crashes with duplicate GDK type registration under that Qt GTK
|
||||
# platform theme, so use qtct for Qt apps on this host instead.
|
||||
env = mkForce [
|
||||
"XCURSOR_SIZE,32"
|
||||
"HYPRCURSOR_THEME,Bibata-Modern-Ice"
|
||||
"WLR_NO_HARDWARE_CURSORS,1"
|
||||
"XDG_CURRENT_DESKTOP,Hyprland"
|
||||
"XDG_SESSION_TYPE,wayland"
|
||||
"XDG_SESSION_DESKTOP,Hyprland"
|
||||
"XKB_DEFAULT_LAYOUT,de"
|
||||
"NIXOS_OZONE_WL,1"
|
||||
"QT_QPA_PLATFORM,wayland;xcb"
|
||||
"QT_QPA_PLATFORMTHEME,qt5ct"
|
||||
"QT_QPA_PLATFORMTHEME_QT6,qt6ct"
|
||||
];
|
||||
windowrule = [
|
||||
"match:class dev.zed.Zed, workspace 1"
|
||||
"match:class ^(com.obsproject.Studio)$, workspace 2"
|
||||
|
||||
Reference in New Issue
Block a user