@event4u/agent-config 1.12.0 → 1.14.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.
- package/.agent-src/commands/agent-handoff.md +3 -0
- package/.agent-src/commands/agent-status.md +3 -0
- package/.agent-src/commands/agents-audit.md +4 -0
- package/.agent-src/commands/agents-cleanup.md +6 -1
- package/.agent-src/commands/agents-prepare.md +3 -0
- package/.agent-src/commands/analyze-reference-repo.md +4 -0
- package/.agent-src/commands/bug-fix.md +5 -1
- package/.agent-src/commands/bug-investigate.md +4 -0
- package/.agent-src/commands/chat-history-checkpoint.md +126 -0
- package/.agent-src/commands/chat-history-clear.md +5 -0
- package/.agent-src/commands/chat-history-resume.md +5 -0
- package/.agent-src/commands/chat-history.md +5 -0
- package/.agent-src/commands/check-current-md.md +126 -0
- package/.agent-src/commands/commit-in-chunks.md +98 -0
- package/.agent-src/commands/commit.md +4 -0
- package/.agent-src/commands/compress.md +3 -0
- package/.agent-src/commands/context-create.md +4 -0
- package/.agent-src/commands/context-refactor.md +4 -0
- package/.agent-src/commands/copilot-agents-init.md +3 -0
- package/.agent-src/commands/copilot-agents-optimize.md +3 -0
- package/.agent-src/commands/create-pr-description.md +4 -0
- package/.agent-src/commands/create-pr.md +4 -0
- package/.agent-src/commands/do-and-judge.md +4 -1
- package/.agent-src/commands/do-in-steps.md +3 -0
- package/.agent-src/commands/e2e-heal.md +4 -0
- package/.agent-src/commands/e2e-plan.md +4 -0
- package/.agent-src/commands/estimate-ticket.md +4 -1
- package/.agent-src/commands/feature-dev.md +4 -0
- package/.agent-src/commands/feature-explore.md +4 -0
- package/.agent-src/commands/feature-plan.md +4 -0
- package/.agent-src/commands/feature-refactor.md +4 -0
- package/.agent-src/commands/feature-roadmap.md +6 -0
- package/.agent-src/commands/fix-ci.md +4 -0
- package/.agent-src/commands/fix-portability.md +3 -0
- package/.agent-src/commands/fix-pr-bot-comments.md +4 -0
- package/.agent-src/commands/fix-pr-comments.md +4 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +4 -0
- package/.agent-src/commands/fix-references.md +3 -0
- package/.agent-src/commands/fix-seeder.md +4 -0
- package/.agent-src/commands/implement-ticket.md +39 -13
- package/.agent-src/commands/jira-ticket.md +4 -0
- package/.agent-src/commands/judge.md +3 -0
- package/.agent-src/commands/memory-add.md +5 -3
- package/.agent-src/commands/memory-full.md +5 -2
- package/.agent-src/commands/memory-promote.md +7 -6
- package/.agent-src/commands/mode.md +3 -0
- package/.agent-src/commands/module-create.md +4 -0
- package/.agent-src/commands/module-explore.md +4 -0
- package/.agent-src/commands/onboard.md +24 -0
- package/.agent-src/commands/optimize-agents.md +4 -0
- package/.agent-src/commands/optimize-augmentignore.md +3 -0
- package/.agent-src/commands/optimize-rtk-filters.md +3 -0
- package/.agent-src/commands/optimize-skills.md +4 -0
- package/.agent-src/commands/override-create.md +4 -0
- package/.agent-src/commands/override-manage.md +4 -0
- package/.agent-src/commands/package-reset.md +3 -0
- package/.agent-src/commands/package-test.md +3 -0
- package/.agent-src/commands/prepare-for-review.md +4 -0
- package/.agent-src/commands/project-analyze.md +4 -0
- package/.agent-src/commands/project-health.md +4 -0
- package/.agent-src/commands/propose-memory.md +6 -8
- package/.agent-src/commands/quality-fix.md +4 -0
- package/.agent-src/commands/refine-ticket.md +4 -1
- package/.agent-src/commands/review-changes.md +4 -0
- package/.agent-src/commands/review-routing.md +4 -0
- package/.agent-src/commands/roadmap-create.md +7 -0
- package/.agent-src/commands/roadmap-execute.md +12 -1
- package/.agent-src/commands/rule-compliance-audit.md +4 -0
- package/.agent-src/commands/set-cost-profile.md +3 -0
- package/.agent-src/commands/sync-agent-settings.md +3 -0
- package/.agent-src/commands/sync-gitignore.md +3 -0
- package/.agent-src/commands/tests-create.md +4 -0
- package/.agent-src/commands/tests-execute.md +4 -0
- package/.agent-src/commands/threat-model.md +4 -0
- package/.agent-src/commands/update-form-request-messages.md +4 -0
- package/.agent-src/commands/upstream-contribute.md +4 -0
- package/.agent-src/commands/work.md +161 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +2 -6
- package/.agent-src/guidelines/agent-infra/layered-settings.md +0 -1
- package/.agent-src/guidelines/agent-infra/memory-access.md +0 -7
- package/.agent-src/guidelines/agent-infra/role-contracts.md +2 -4
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +0 -1
- package/.agent-src/guidelines/php/patterns/strategy.md +180 -2
- package/.agent-src/personas/README.md +0 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +7 -2
- package/.agent-src/rules/artifact-engagement-recording.md +133 -0
- package/.agent-src/rules/ask-when-uncertain.md +18 -13
- package/.agent-src/rules/augment-portability.md +8 -0
- package/.agent-src/rules/autonomous-execution.md +158 -0
- package/.agent-src/rules/chat-history.md +147 -118
- package/.agent-src/rules/cli-output-handling.md +26 -3
- package/.agent-src/rules/command-suggestion.md +133 -0
- package/.agent-src/rules/commit-policy.md +99 -0
- package/.agent-src/rules/direct-answers.md +114 -0
- package/.agent-src/rules/docs-sync.md +36 -0
- package/.agent-src/rules/downstream-changes.md +10 -9
- package/.agent-src/rules/improve-before-implement.md +9 -6
- package/.agent-src/rules/language-and-tone.md +81 -6
- package/.agent-src/rules/non-destructive-by-default.md +117 -0
- package/.agent-src/rules/package-ci-checks.md +4 -0
- package/.agent-src/rules/preservation-guard.md +20 -0
- package/.agent-src/rules/roadmap-progress-sync.md +103 -30
- package/.agent-src/rules/scope-control.md +42 -1
- package/.agent-src/rules/size-enforcement.md +1 -3
- package/.agent-src/rules/skill-quality.md +3 -8
- package/.agent-src/rules/ui-audit-before-build.md +106 -0
- package/.agent-src/rules/user-interaction.md +81 -3
- package/.agent-src/scripts/update_roadmap_progress.py +48 -6
- package/.agent-src/skills/blade-ui/SKILL.md +30 -5
- package/.agent-src/skills/command-routing/SKILL.md +32 -0
- package/.agent-src/skills/command-writing/SKILL.md +41 -2
- package/.agent-src/skills/description-assist/SKILL.md +21 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
- package/.agent-src/skills/existing-ui-audit/SKILL.md +187 -0
- package/.agent-src/skills/fe-design/SKILL.md +72 -60
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
- package/.agent-src/skills/flux/SKILL.md +31 -4
- package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
- package/.agent-src/skills/livewire/SKILL.md +30 -4
- package/.agent-src/skills/md-language-check/SKILL.md +103 -0
- package/.agent-src/skills/php-coder/SKILL.md +24 -0
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
- package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +2 -4
- package/.agent-src/skills/roadmap-management/SKILL.md +10 -3
- package/.agent-src/skills/rule-writing/SKILL.md +23 -1
- package/.agent-src/skills/skill-writing/SKILL.md +1 -3
- package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
- package/.agent-src/templates/AGENTS.md +24 -6
- package/.agent-src/templates/agent-settings.md +149 -0
- package/.agent-src/templates/github-workflows/roadmap-progress-check.yml +63 -0
- package/.agent-src/templates/hooks/pre-commit-roadmap-progress +60 -0
- package/.agent-src/templates/roadmaps.md +8 -2
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
- package/.agent-src/templates/scripts/memory_lookup.py +382 -21
- package/.agent-src/templates/scripts/memory_status.py +110 -9
- package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
- package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
- package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
- package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
- package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
- package/.agent-src/templates/scripts/telemetry_record.py +166 -0
- package/.agent-src/templates/scripts/telemetry_report.py +161 -0
- package/.agent-src/templates/scripts/telemetry_status.py +142 -0
- package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
- package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
- package/.agent-src/templates/scripts/work_engine/cli.py +592 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +7 -0
- package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
- package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +1 -1
- package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +36 -4
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
- package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
- package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
- package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
- package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
- package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
- package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
- package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
- package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
- package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
- package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +199 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
- package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
- package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
- package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
- package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
- package/.agent-src/templates/scripts/work_engine/state.py +641 -0
- package/.claude-plugin/marketplace.json +105 -2
- package/AGENTS.md +36 -8
- package/CHANGELOG.md +558 -0
- package/README.md +146 -4
- package/composer.json +3 -0
- package/config/agent-settings.template.yml +45 -0
- package/config/gitignore-block.txt +4 -0
- package/docs/architecture.md +28 -1
- package/docs/development.md +1 -1
- package/docs/getting-started.md +3 -2
- package/docs/installation.md +86 -0
- package/docs/showcase.md +204 -0
- package/package.json +9 -1
- package/scripts/agent-config +274 -0
- package/scripts/audit_cloud_compatibility.py +288 -0
- package/scripts/build_cloud_bundle.py +458 -0
- package/scripts/build_linear_digest.py +263 -0
- package/scripts/chat_history.py +796 -7
- package/scripts/check_compression.py +139 -0
- package/scripts/check_iron_law_prominence.py +143 -0
- package/scripts/check_md_language.py +159 -0
- package/scripts/check_portability.py +36 -0
- package/scripts/check_reply_consistency.py +140 -0
- package/scripts/command_suggester/__init__.py +51 -0
- package/scripts/command_suggester/cooldown.py +132 -0
- package/scripts/command_suggester/loader.py +70 -0
- package/scripts/command_suggester/match.py +180 -0
- package/scripts/command_suggester/rank.py +120 -0
- package/scripts/command_suggester/render.py +86 -0
- package/scripts/command_suggester/sanitize.py +113 -0
- package/scripts/command_suggester/settings.py +125 -0
- package/scripts/command_suggester/types.py +78 -0
- package/scripts/hooks/augment-chat-history.sh +56 -0
- package/scripts/install-hooks.sh +67 -0
- package/scripts/install.py +150 -33
- package/scripts/lint_marketplace.py +27 -0
- package/scripts/memory_lookup.py +143 -7
- package/scripts/memory_status.py +76 -14
- package/scripts/migrate_command_suggestions.py +151 -0
- package/scripts/postinstall.sh +16 -0
- package/scripts/schemas/command.schema.json +41 -0
- package/scripts/skill_linter.py +67 -0
- package/scripts/sync_agent_settings.py +42 -12
- package/templates/consumer-settings/augment-cli-hooks.json +54 -0
- package/templates/consumer-settings/claude-settings.json +55 -1
- package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
- package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +0 -140
- /package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +0 -0
|
@@ -10,6 +10,8 @@ shape used by anthropics/skills:
|
|
|
10
10
|
- metadata must have description + version
|
|
11
11
|
- metadata.version must match package.json (single source of truth)
|
|
12
12
|
- every plugins[].skills[] entry must exist on disk and carry a SKILL.md
|
|
13
|
+
- every SKILL.md on disk under .claude/skills/ must be listed in some
|
|
14
|
+
plugin's skills[] (drift detection)
|
|
13
15
|
|
|
14
16
|
Exit codes: 0 = clean, 1 = problems found, 3 = internal error.
|
|
15
17
|
"""
|
|
@@ -23,6 +25,7 @@ from pathlib import Path
|
|
|
23
25
|
ROOT = Path(".")
|
|
24
26
|
MARKETPLACE = ROOT / ".claude-plugin" / "marketplace.json"
|
|
25
27
|
PACKAGE_JSON = ROOT / "package.json"
|
|
28
|
+
CLAUDE_SKILLS_DIR = ROOT / ".claude" / "skills"
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
def fail(errors: list[str]) -> int:
|
|
@@ -121,6 +124,30 @@ def main() -> int:
|
|
|
121
124
|
if not skill_md.exists():
|
|
122
125
|
errors.append(f"{entry} has no SKILL.md: `{path}`")
|
|
123
126
|
|
|
127
|
+
# Reverse-completeness: every SKILL.md on disk under .claude/skills/
|
|
128
|
+
# must appear in some plugin's skills[]. Catches the drift where new
|
|
129
|
+
# skills are generated but never added to the marketplace manifest.
|
|
130
|
+
listed: set[str] = set()
|
|
131
|
+
for plugin in plugins:
|
|
132
|
+
if not isinstance(plugin, dict):
|
|
133
|
+
continue
|
|
134
|
+
for path in plugin.get("skills", []):
|
|
135
|
+
if isinstance(path, str):
|
|
136
|
+
listed.add(path.removeprefix("./"))
|
|
137
|
+
|
|
138
|
+
if CLAUDE_SKILLS_DIR.exists():
|
|
139
|
+
for skill_dir in sorted(CLAUDE_SKILLS_DIR.iterdir()):
|
|
140
|
+
if not skill_dir.is_dir():
|
|
141
|
+
continue
|
|
142
|
+
if not (skill_dir / "SKILL.md").exists():
|
|
143
|
+
continue
|
|
144
|
+
rel = f".claude/skills/{skill_dir.name}"
|
|
145
|
+
if rel not in listed:
|
|
146
|
+
errors.append(
|
|
147
|
+
f"skill exists on disk but is not listed in marketplace.json: "
|
|
148
|
+
f"`./{rel}`"
|
|
149
|
+
)
|
|
150
|
+
|
|
124
151
|
if errors:
|
|
125
152
|
return fail(errors)
|
|
126
153
|
|
package/scripts/memory_lookup.py
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""Hybrid retrieval — file-first with optional package augmentation.
|
|
3
3
|
|
|
4
4
|
Implements the shared `retrieve(types, keys, limit)` abstraction used
|
|
5
5
|
by skills. Reads YAML under `agents/memory/<type>/` (curated, hand-
|
|
6
6
|
reviewed) and JSONL under `agents/memory/intake/*.jsonl` (agent-written,
|
|
7
7
|
append-only, supersede-chain aware).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
When the `@event4u/agent-memory` package is present (see
|
|
10
|
+
`scripts/memory_status.py`), callers can pass the result of
|
|
11
|
+
:func:`package_operational_provider` to route additional retrieval
|
|
12
|
+
through the package's semantic CLI. Repo entries always win on
|
|
13
|
+
conflict — see `_apply_conflict_rule`.
|
|
11
14
|
|
|
12
15
|
Usage:
|
|
13
16
|
python3 scripts/memory_lookup.py --types domain-invariants,ownership \\
|
|
14
17
|
--key "app/Http/Controllers/Foo" --limit 5
|
|
15
18
|
python3 scripts/memory_lookup.py --types incident-learnings --format json
|
|
19
|
+
python3 scripts/memory_lookup.py --types ownership --key billing --auto
|
|
16
20
|
|
|
17
|
-
from scripts.memory_lookup import retrieve
|
|
18
|
-
hits = retrieve(
|
|
21
|
+
from scripts.memory_lookup import retrieve, package_operational_provider
|
|
22
|
+
hits = retrieve(
|
|
23
|
+
types=["ownership"], keys=["app/Http"], limit=3,
|
|
24
|
+
operational_provider=package_operational_provider(),
|
|
25
|
+
)
|
|
19
26
|
"""
|
|
20
27
|
|
|
21
28
|
from __future__ import annotations
|
|
@@ -23,6 +30,8 @@ from __future__ import annotations
|
|
|
23
30
|
import argparse
|
|
24
31
|
import fnmatch
|
|
25
32
|
import json
|
|
33
|
+
import os
|
|
34
|
+
import subprocess
|
|
26
35
|
import sys
|
|
27
36
|
from dataclasses import dataclass, asdict, field
|
|
28
37
|
from pathlib import Path
|
|
@@ -229,6 +238,125 @@ def _apply_conflict_rule(
|
|
|
229
238
|
return merged, shadows
|
|
230
239
|
|
|
231
240
|
|
|
241
|
+
# ---------------------------------------------------------------------------
|
|
242
|
+
# Package-backed operational provider (the `present` path)
|
|
243
|
+
# ---------------------------------------------------------------------------
|
|
244
|
+
#
|
|
245
|
+
# When `memory_status.status() == "present"` the consumer-facing contract
|
|
246
|
+
# says retrieval should route through `@event4u/agent-memory`. The package
|
|
247
|
+
# CLI is purely **semantic** (`memory retrieve <query> --type T …`); the
|
|
248
|
+
# shared `retrieve(types, keys, …)` API is **key-based**. The hybrid
|
|
249
|
+
# resolution agreed in `agents/contexts/agent-memory-contract.md` synthesises
|
|
250
|
+
# `keys` into a single natural-language query for the package call, while
|
|
251
|
+
# the file fallback continues to do glob/substring matching on the same
|
|
252
|
+
# keys. Both legs land in the same `Hit` shape so the conflict rule can
|
|
253
|
+
# merge them transparently.
|
|
254
|
+
|
|
255
|
+
_CLI_TIMEOUT_SECONDS = 5.0
|
|
256
|
+
_CLI_RETRIEVE_LIMIT_DEFAULT = 20
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _synthesize_query(keys: list[str]) -> str:
|
|
260
|
+
"""Turn a list of retrieval keys into one natural-language query.
|
|
261
|
+
|
|
262
|
+
Keys are typically file paths (`app/Http/Controllers/Foo`), feature
|
|
263
|
+
names (`billing`), or short identifiers — joining them with spaces
|
|
264
|
+
gives the package's semantic search enough surface to score against
|
|
265
|
+
without inventing structure. Empty or whitespace-only keys are
|
|
266
|
+
dropped; if nothing remains the caller falls back to the file path.
|
|
267
|
+
"""
|
|
268
|
+
cleaned = [k.strip() for k in keys if isinstance(k, str) and k.strip()]
|
|
269
|
+
return " ".join(cleaned)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _cli_operational_provider(
|
|
273
|
+
types: list[str],
|
|
274
|
+
keys: list[str],
|
|
275
|
+
*,
|
|
276
|
+
cli_path: str = "memory",
|
|
277
|
+
timeout: float = _CLI_TIMEOUT_SECONDS,
|
|
278
|
+
limit: int = _CLI_RETRIEVE_LIMIT_DEFAULT,
|
|
279
|
+
) -> Iterable[Hit]:
|
|
280
|
+
"""Run `memory retrieve` and yield operational `Hit` objects.
|
|
281
|
+
|
|
282
|
+
Pino structured logs from the package go to stderr; stdout is a
|
|
283
|
+
clean v1 retrieval envelope. Any non-zero exit, timeout, or parse
|
|
284
|
+
failure degrades to "no operational hits" — `retrieve()` already
|
|
285
|
+
treats provider exceptions as a soft warning, so the caller still
|
|
286
|
+
gets the file-fallback result.
|
|
287
|
+
"""
|
|
288
|
+
query = _synthesize_query(keys)
|
|
289
|
+
if not query:
|
|
290
|
+
return
|
|
291
|
+
cmd: list[str] = [cli_path, "retrieve", query, "--limit", str(limit)]
|
|
292
|
+
for t in types:
|
|
293
|
+
cmd.extend(["--type", t])
|
|
294
|
+
try:
|
|
295
|
+
out = subprocess.run(
|
|
296
|
+
cmd,
|
|
297
|
+
capture_output=True, text=True, timeout=timeout,
|
|
298
|
+
)
|
|
299
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
|
300
|
+
return
|
|
301
|
+
if out.returncode != 0:
|
|
302
|
+
return
|
|
303
|
+
try:
|
|
304
|
+
envelope = json.loads(out.stdout)
|
|
305
|
+
except (ValueError, TypeError):
|
|
306
|
+
return
|
|
307
|
+
entries = envelope.get("entries") if isinstance(envelope, dict) else None
|
|
308
|
+
if not isinstance(entries, list):
|
|
309
|
+
return
|
|
310
|
+
for e in entries:
|
|
311
|
+
if not isinstance(e, dict):
|
|
312
|
+
continue
|
|
313
|
+
eid = e.get("id")
|
|
314
|
+
etype = e.get("type")
|
|
315
|
+
if not isinstance(eid, str) or not isinstance(etype, str):
|
|
316
|
+
continue
|
|
317
|
+
# The package returns `confidence` (0..1) per the v1 envelope;
|
|
318
|
+
# map it onto our internal `score` field so the conflict rule
|
|
319
|
+
# and ranking work uniformly across providers.
|
|
320
|
+
try:
|
|
321
|
+
score = float(e.get("confidence", 0.0))
|
|
322
|
+
except (TypeError, ValueError):
|
|
323
|
+
score = 0.0
|
|
324
|
+
body = e.get("body") if isinstance(e.get("body"), dict) else {}
|
|
325
|
+
yield Hit(
|
|
326
|
+
id=eid,
|
|
327
|
+
type=etype,
|
|
328
|
+
source="operational",
|
|
329
|
+
path=f"agent-memory:{eid}",
|
|
330
|
+
score=score,
|
|
331
|
+
entry=body,
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def package_operational_provider() -> Optional[OperationalProvider]:
|
|
336
|
+
"""Return a CLI-backed provider when the package is `present`, else None.
|
|
337
|
+
|
|
338
|
+
Callers who want automatic backend routing pass the result directly
|
|
339
|
+
to :func:`retrieve` — `None` is a safe value that yields file-only
|
|
340
|
+
retrieval, so this is the recommended one-liner for skills:
|
|
341
|
+
|
|
342
|
+
retrieve(types, keys, operational_provider=package_operational_provider())
|
|
343
|
+
|
|
344
|
+
The status probe is bounded (≤ 2s, cached per process) — see
|
|
345
|
+
`scripts/memory_status.py`. We import lazily so pure file-fallback
|
|
346
|
+
callers never pay for the probe.
|
|
347
|
+
"""
|
|
348
|
+
# Late import: keeps `memory_lookup` importable even when
|
|
349
|
+
# `memory_status` is missing in stripped consumer installs.
|
|
350
|
+
try:
|
|
351
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
352
|
+
import memory_status # type: ignore[import-not-found]
|
|
353
|
+
except ImportError:
|
|
354
|
+
return None
|
|
355
|
+
if memory_status.status().status != "present":
|
|
356
|
+
return None
|
|
357
|
+
return _cli_operational_provider
|
|
358
|
+
|
|
359
|
+
|
|
232
360
|
def retrieve(
|
|
233
361
|
types: list[str],
|
|
234
362
|
keys: list[str],
|
|
@@ -402,16 +530,24 @@ def main() -> int:
|
|
|
402
530
|
ap.add_argument("--with-shadows", action="store_true",
|
|
403
531
|
help="Include shadowed-operational entries in the output "
|
|
404
532
|
"(no-op until an operational backend is wired)")
|
|
533
|
+
ap.add_argument("--auto", action="store_true",
|
|
534
|
+
help="Auto-route to the @event4u/agent-memory package "
|
|
535
|
+
"when memory_status.status() == 'present'; "
|
|
536
|
+
"falls through to file-only retrieval otherwise")
|
|
405
537
|
args = ap.parse_args()
|
|
406
538
|
types = [t.strip() for t in args.types.split(",") if t.strip()]
|
|
407
539
|
if not types:
|
|
408
540
|
print("error: --types is required", file=sys.stderr)
|
|
409
541
|
return 2
|
|
542
|
+
op_provider = package_operational_provider() if args.auto else None
|
|
410
543
|
if args.envelope == "v1":
|
|
411
|
-
envelope = retrieve_v1(types, args.key, args.limit
|
|
544
|
+
envelope = retrieve_v1(types, args.key, args.limit,
|
|
545
|
+
operational_provider=op_provider)
|
|
412
546
|
print(json.dumps(envelope, indent=2, default=str))
|
|
413
547
|
return 0
|
|
414
|
-
result = retrieve(types, args.key, args.limit,
|
|
548
|
+
result = retrieve(types, args.key, args.limit,
|
|
549
|
+
operational_provider=op_provider,
|
|
550
|
+
with_shadows=args.with_shadows)
|
|
415
551
|
if args.with_shadows:
|
|
416
552
|
assert isinstance(result, RetrievalResult)
|
|
417
553
|
hits, shadows = result.hits, result.shadows
|
package/scripts/memory_status.py
CHANGED
|
@@ -35,7 +35,7 @@ from typing import Literal
|
|
|
35
35
|
|
|
36
36
|
Status = Literal["absent", "misconfigured", "present"]
|
|
37
37
|
|
|
38
|
-
_CLI_CANDIDATES = ("agent-memory", "agentmem")
|
|
38
|
+
_CLI_CANDIDATES = ("memory", "agent-memory", "agentmem")
|
|
39
39
|
_HEALTH_TIMEOUT_SECONDS = 2.0
|
|
40
40
|
_CACHE_ENV = "AGENT_MEMORY_STATUS"
|
|
41
41
|
_CACHE_FILE = Path(".agent-memory") / "status.cache"
|
|
@@ -54,6 +54,11 @@ class Result:
|
|
|
54
54
|
reason: str # short explanation
|
|
55
55
|
elapsed_ms: int # time spent probing (0 if cached)
|
|
56
56
|
cli_path: str = "" # resolved CLI path, if any
|
|
57
|
+
# Populated only when status == "present" — sourced from the
|
|
58
|
+
# `health` CLI envelope so the v1 health() reports real package
|
|
59
|
+
# capabilities instead of file-fallback placeholders.
|
|
60
|
+
backend_version: str = ""
|
|
61
|
+
features: tuple = ()
|
|
57
62
|
|
|
58
63
|
|
|
59
64
|
def _find_cli() -> str:
|
|
@@ -64,8 +69,45 @@ def _find_cli() -> str:
|
|
|
64
69
|
return ""
|
|
65
70
|
|
|
66
71
|
|
|
67
|
-
def
|
|
68
|
-
"""
|
|
72
|
+
def _parse_health_envelope(stdout: str) -> dict | None:
|
|
73
|
+
"""Extract the v1 health envelope from `memory health` stdout.
|
|
74
|
+
|
|
75
|
+
The package emits a single JSON object on stdout (pino structured
|
|
76
|
+
logs go to stderr). We tolerate older builds that may have leaked
|
|
77
|
+
log lines into stdout by scanning for the first top-level object
|
|
78
|
+
that carries ``contract_version``.
|
|
79
|
+
"""
|
|
80
|
+
text = (stdout or "").strip()
|
|
81
|
+
if not text:
|
|
82
|
+
return None
|
|
83
|
+
try:
|
|
84
|
+
obj = json.loads(text)
|
|
85
|
+
except ValueError:
|
|
86
|
+
obj = None
|
|
87
|
+
if isinstance(obj, dict) and obj.get("contract_version"):
|
|
88
|
+
return obj
|
|
89
|
+
# Fallback: line-by-line scan for an envelope-shaped object — covers
|
|
90
|
+
# the case where structured logs accidentally share stdout.
|
|
91
|
+
for line in text.splitlines():
|
|
92
|
+
line = line.strip()
|
|
93
|
+
if not line.startswith("{"):
|
|
94
|
+
continue
|
|
95
|
+
try:
|
|
96
|
+
cand = json.loads(line)
|
|
97
|
+
except ValueError:
|
|
98
|
+
continue
|
|
99
|
+
if isinstance(cand, dict) and cand.get("contract_version"):
|
|
100
|
+
return cand
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _probe_health(cli_path: str) -> tuple[bool, str, dict | None]:
|
|
105
|
+
"""Returns (healthy, reason, envelope).
|
|
106
|
+
|
|
107
|
+
On success ``envelope`` is the parsed v1 health envelope (may still
|
|
108
|
+
be ``None`` for very old CLIs that don't emit one). On failure it
|
|
109
|
+
is always ``None``.
|
|
110
|
+
"""
|
|
69
111
|
try:
|
|
70
112
|
out = subprocess.run(
|
|
71
113
|
[cli_path, "health"],
|
|
@@ -73,15 +115,16 @@ def _probe_health(cli_path: str) -> tuple[bool, str]:
|
|
|
73
115
|
timeout=_HEALTH_TIMEOUT_SECONDS,
|
|
74
116
|
)
|
|
75
117
|
except subprocess.TimeoutExpired:
|
|
76
|
-
return False, f"health() timed out after {_HEALTH_TIMEOUT_SECONDS}s"
|
|
118
|
+
return False, f"health() timed out after {_HEALTH_TIMEOUT_SECONDS}s", None
|
|
77
119
|
except FileNotFoundError:
|
|
78
|
-
return False, "CLI vanished between which() and invoke"
|
|
120
|
+
return False, "CLI vanished between which() and invoke", None
|
|
79
121
|
if out.returncode != 0:
|
|
80
122
|
# First line of combined output, capped, for the reason field.
|
|
81
123
|
msg = (out.stderr or out.stdout or "exit != 0").strip().splitlines()
|
|
82
124
|
head = msg[0][:120] if msg else "exit != 0"
|
|
83
|
-
return False, f"health() returned {out.returncode}: {head}"
|
|
84
|
-
|
|
125
|
+
return False, f"health() returned {out.returncode}: {head}", None
|
|
126
|
+
envelope = _parse_health_envelope(out.stdout)
|
|
127
|
+
return True, "ok", envelope
|
|
85
128
|
|
|
86
129
|
|
|
87
130
|
def _read_cache() -> Result | None:
|
|
@@ -131,10 +174,23 @@ def status(refresh: bool = False) -> Result:
|
|
|
131
174
|
result = Result("absent", "file",
|
|
132
175
|
"agent-memory CLI not on PATH", 0)
|
|
133
176
|
else:
|
|
134
|
-
healthy, reason = _probe_health(cli)
|
|
177
|
+
healthy, reason, envelope = _probe_health(cli)
|
|
135
178
|
elapsed = int((time.monotonic() - t0) * 1000)
|
|
136
179
|
if healthy:
|
|
137
|
-
|
|
180
|
+
backend_version = ""
|
|
181
|
+
features: tuple = ()
|
|
182
|
+
if isinstance(envelope, dict):
|
|
183
|
+
bv = envelope.get("backend_version")
|
|
184
|
+
if isinstance(bv, str):
|
|
185
|
+
backend_version = bv
|
|
186
|
+
feats = envelope.get("features")
|
|
187
|
+
if isinstance(feats, list) and all(
|
|
188
|
+
isinstance(f, str) for f in feats
|
|
189
|
+
):
|
|
190
|
+
features = tuple(feats)
|
|
191
|
+
result = Result("present", "package", reason, elapsed, cli,
|
|
192
|
+
backend_version=backend_version,
|
|
193
|
+
features=features)
|
|
138
194
|
else:
|
|
139
195
|
result = Result("misconfigured", "file", reason, elapsed, cli)
|
|
140
196
|
_write_cache(result)
|
|
@@ -148,6 +204,11 @@ def health(refresh: bool = False) -> dict:
|
|
|
148
204
|
Maps the three-state :func:`status` result onto the contract's
|
|
149
205
|
``ok | degraded | error`` so consumers can read
|
|
150
206
|
``contract_version`` without caring about the file-vs-package split.
|
|
207
|
+
|
|
208
|
+
When the package backs the call (``status == "present"``), the
|
|
209
|
+
envelope reports the package's own ``backend_version`` and
|
|
210
|
+
``features`` so consumers can feature-detect against real
|
|
211
|
+
capabilities. Otherwise the file-fallback markers are returned.
|
|
151
212
|
"""
|
|
152
213
|
r = status(refresh=refresh)
|
|
153
214
|
envelope_status = {
|
|
@@ -155,11 +216,12 @@ def health(refresh: bool = False) -> dict:
|
|
|
155
216
|
"misconfigured": "degraded",
|
|
156
217
|
"absent": "ok",
|
|
157
218
|
}[r.status]
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
219
|
+
if r.status == "present" and (r.backend_version or r.features):
|
|
220
|
+
backend_version = r.backend_version or _FILE_BACKEND_VERSION
|
|
221
|
+
features = list(r.features) if r.features else list(_FILE_BACKEND_FEATURES)
|
|
222
|
+
else:
|
|
223
|
+
backend_version = _FILE_BACKEND_VERSION
|
|
224
|
+
features = list(_FILE_BACKEND_FEATURES)
|
|
163
225
|
return {
|
|
164
226
|
"contract_version": CONTRACT_VERSION,
|
|
165
227
|
"status": envelope_status,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""One-shot migration: inject the `suggestion:` frontmatter block into every
|
|
3
|
+
command under `.agent-src.uncompressed/commands/`.
|
|
4
|
+
|
|
5
|
+
Source-of-truth table: `agents/contexts/command-suggestion-eligibility.md`
|
|
6
|
+
(locked at end of road-to-context-aware-command-suggestion Phase 1).
|
|
7
|
+
|
|
8
|
+
Idempotent: if `suggestion:` is already present for a command, the file is
|
|
9
|
+
left untouched. Re-runnable.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
import sys
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
18
|
+
COMMANDS_DIR = ROOT / ".agent-src.uncompressed" / "commands"
|
|
19
|
+
|
|
20
|
+
INELIGIBLE: dict[str, str] = {
|
|
21
|
+
"agent-handoff": "Explicit fresh-chat handoff — must be deliberate, never inferred from prose.",
|
|
22
|
+
"agent-status": "Pure status display; no natural-language trigger distinct from idle small-talk.",
|
|
23
|
+
"agents-cleanup": "Consumes prior audit output; only meaningful right after /agents-audit.",
|
|
24
|
+
"agents-prepare": "One-shot project scaffolding; only run during initial setup.",
|
|
25
|
+
"chat-history": "Status display only; no NL trigger distinct from 'show status'.",
|
|
26
|
+
"chat-history-clear": "Destructive log wipe — must be deliberate.",
|
|
27
|
+
"chat-history-resume": "Explicit resume mechanic with foreign/returning state machine.",
|
|
28
|
+
"compress": "Package-internal tooling; only the event4u/agent-config repo runs this.",
|
|
29
|
+
"copilot-agents-init": "Project init — only deliberately during onboarding.",
|
|
30
|
+
"copilot-agents-optimize": "Maintenance refactor; only when the maintainer chooses to run it.",
|
|
31
|
+
"do-and-judge": "Subagent orchestration — overlaps /work and judge skills; keep explicit.",
|
|
32
|
+
"do-in-steps": "Subagent orchestration — overlaps /work and /roadmap-execute; keep explicit.",
|
|
33
|
+
"fix-portability": "Package-internal — only the event4u/agent-config repo runs this.",
|
|
34
|
+
"fix-references": "Package-internal — only the event4u/agent-config repo runs this.",
|
|
35
|
+
"judge": "Sibling of /review-changes — eligibility routed there; keep this explicit.",
|
|
36
|
+
"memory-full": "Description states 'never auto-triggered' — opt-in deep-load only.",
|
|
37
|
+
"memory-promote": "Curation pipeline — overlaps /memory-add; keep explicit.",
|
|
38
|
+
"mode": "Role-mode switch is a deliberate context change.",
|
|
39
|
+
"onboard": "Gated by the onboarding-gate rule already; never inferred from prose.",
|
|
40
|
+
"optimize-augmentignore": "Niche maintenance tool with no recurring NL trigger.",
|
|
41
|
+
"optimize-rtk-filters": "Niche maintenance tool with no recurring NL trigger.",
|
|
42
|
+
"package-reset": "Package-internal destructive reset.",
|
|
43
|
+
"package-test": "Package-internal — only the event4u/agent-config repo runs this.",
|
|
44
|
+
"propose-memory": "Programmatic intake fallback — overlaps /memory-add; keep explicit.",
|
|
45
|
+
"set-cost-profile": "Settings mutation — must be deliberate.",
|
|
46
|
+
"sync-agent-settings": "Settings sync — must be deliberate.",
|
|
47
|
+
"sync-gitignore": "Settings sync — must be deliberate.",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# (trigger_description, trigger_context)
|
|
51
|
+
ELIGIBLE: dict[str, tuple[str, str]] = {
|
|
52
|
+
"agents-audit": ("audit my agent docs, check the state of the agents/ directory", "stale files under agents/ or recent edits to .augment/ without doc updates"),
|
|
53
|
+
"analyze-reference-repo": ("look at how X does this, compare with that other repo, study this competitor's approach", "external repo URL or path mentioned in the prompt"),
|
|
54
|
+
"bug-fix": ("fix this bug, patch the issue, resolve this error", "branch name matches fix/* or bug/*"),
|
|
55
|
+
"bug-investigate": ("why is this broken, investigate this error, trace the root cause", "Sentry URL, Jira bug ticket key, or stack trace pasted in the prompt"),
|
|
56
|
+
"commit": ("commit my changes, save this to git, create commits for these changes", "git status shows uncommitted changes"),
|
|
57
|
+
"commit-in-chunks": ("commit everything autonomously, split and commit without confirmation", "autonomous mode active and uncommitted changes present"),
|
|
58
|
+
"context-create": ("document this part of the codebase, create a context doc for X", "working in a module without an agents/contexts/ doc"),
|
|
59
|
+
"context-refactor": ("update the context doc, refresh this context document", "existing agents/contexts/*.md referenced in the prompt"),
|
|
60
|
+
"create-pr": ("open a PR, create a pull request, make a PR for this branch", "branch is ahead of base and not yet on a PR"),
|
|
61
|
+
"create-pr-description": ("write a PR description, draft the PR text", "PR exists or branch ready for review without description"),
|
|
62
|
+
"e2e-heal": ("fix the failing E2E tests, playwright tests are red", "failing test output from tests/e2e/"),
|
|
63
|
+
"e2e-plan": ("plan E2E tests for this feature, what should we cover in playwright", "new feature or page added without tests/e2e/ coverage"),
|
|
64
|
+
"estimate-ticket": ("how big is this ticket, estimate PROJ-123, should we split this", "ticket key matching [A-Z]+-[0-9]+ in the prompt and no plan yet"),
|
|
65
|
+
"feature-dev": ("build this feature end-to-end, run the full feature workflow", "long-form feature description spanning multiple components"),
|
|
66
|
+
"feature-explore": ("brainstorm this idea, explore this feature concept", "open-ended feature idea without acceptance criteria"),
|
|
67
|
+
"feature-plan": ("plan this feature, create a feature spec for X", "feature idea referenced and no plan doc exists"),
|
|
68
|
+
"feature-refactor": ("update the feature plan, refine the feature spec", "existing agents/features/*.md referenced in the prompt"),
|
|
69
|
+
"feature-roadmap": ("turn this feature into a roadmap, generate the implementation roadmap", "existing feature plan without linked roadmap"),
|
|
70
|
+
"fix-ci": ("CI is failing, fix the GitHub Actions errors, the pipeline is red", "open PR with failing checks"),
|
|
71
|
+
"fix-pr-bot-comments": ("address the Copilot/Greptile comments, fix the bot review feedback", "open PR with bot review comments unresolved"),
|
|
72
|
+
"fix-pr-comments": ("fix all PR review comments, resolve the review feedback", "open PR with unresolved comments (bot + human)"),
|
|
73
|
+
"fix-pr-developer-comments": ("fix the human reviewer comments, address the developer feedback", "open PR with unresolved human-reviewer comments"),
|
|
74
|
+
"fix-seeder": ("the seeder is broken, foreign key errors in seeders", "seeder error output or recent edits in database/seeders/"),
|
|
75
|
+
"implement-ticket": ("implement this ticket, setze ticket X um, build PROJ-123", "ticket key matching [A-Z]+-[0-9]+ in branch name or prompt"),
|
|
76
|
+
"jira-ticket": ("implement the ticket on this branch, work on the Jira ticket from the branch", "branch name matching feat/PROJ-123-* or similar"),
|
|
77
|
+
"memory-add": ("remember this for later, add this to engineering memory, capture this learning", "post-incident or post-decision conversation"),
|
|
78
|
+
"module-create": ("create a new module, scaffold a module for X", "prompt mentions a new domain area without an existing module"),
|
|
79
|
+
"module-explore": ("show me the X module, load the module context", "existing Modules/<Name>/ referenced in the prompt"),
|
|
80
|
+
"optimize-agents": ("audit agent infrastructure, tune the agent setup", "maintainer working on .augment/ files"),
|
|
81
|
+
"optimize-skills": ("audit my skills, find duplicate skills", "maintainer working on .augment/skills/ files"),
|
|
82
|
+
"override-create": ("override this skill for the project, customize this rule locally", "prompt names a shared skill/rule needing project-specific behavior"),
|
|
83
|
+
"override-manage": ("review my overrides, update the project overrides", "existing entries under agents/overrides/"),
|
|
84
|
+
"prepare-for-review": ("get this branch ready for review, rebase and prep for PR", "branch behind base or part of a PR chain"),
|
|
85
|
+
"project-analyze": ("analyze the project structure, do a full project audit", "new project or after a major refactor"),
|
|
86
|
+
"project-health": ("check project health, what's the state of my docs and modules", "routine health check, no destructive intent"),
|
|
87
|
+
"quality-fix": ("fix the quality errors, run PHPStan and fix issues, fix code style", "PHPStan/Rector/ECS output in recent tool results"),
|
|
88
|
+
"refine-ticket": ("refine PROJ-123, tighten the acceptance criteria, is this ticket clear", "ticket key in prompt with vague acceptance criteria"),
|
|
89
|
+
"review-changes": ("self-review my changes, judge this diff before PR", "uncommitted or staged changes pre-PR"),
|
|
90
|
+
"review-routing": ("who should review this, suggest reviewers for this PR", "PR open without assigned reviewers"),
|
|
91
|
+
"roadmap-create": ("create a roadmap for X, plan this work as a roadmap", "multi-phase work without an existing agents/roadmaps/*.md"),
|
|
92
|
+
"roadmap-execute": ("execute the roadmap, work through the roadmap step by step", "existing agents/roadmaps/*.md referenced in the prompt"),
|
|
93
|
+
"rule-compliance-audit": ("audit my rules, check rule trigger quality", "maintainer working on .augment/rules/ files"),
|
|
94
|
+
"tests-create": ("write tests for these changes, add tests for this branch", "code changes on the branch without matching test changes"),
|
|
95
|
+
"tests-execute": ("run the tests, execute the test suite", "code changes pending verification"),
|
|
96
|
+
"threat-model": ("threat model this change, what could go wrong security-wise", "changes touching auth, webhooks, uploads, secrets, or public endpoints"),
|
|
97
|
+
"update-form-request-messages": ("sync the form request messages, update the validation messages", "edits to app/Http/Requests/*.php referencing rules without messages"),
|
|
98
|
+
"upstream-contribute": ("contribute this back to agent-config, upstream this learning", "project-local skill/rule that fits the shared package"),
|
|
99
|
+
"work": ("build this, implement this, drive this end-to-end", "free-form prompt without a ticket key"),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
FRONTMATTER_RE = re.compile(r"^(---\n)(.*?)(\n---\n)", re.DOTALL)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def build_block(name: str) -> str:
|
|
106
|
+
if name in INELIGIBLE:
|
|
107
|
+
rationale = INELIGIBLE[name].replace('"', '\\"')
|
|
108
|
+
return f'suggestion:\n eligible: false\n rationale: "{rationale}"'
|
|
109
|
+
if name in ELIGIBLE:
|
|
110
|
+
td, tc = ELIGIBLE[name]
|
|
111
|
+
td_e = td.replace('"', '\\"')
|
|
112
|
+
tc_e = tc.replace('"', '\\"')
|
|
113
|
+
return (f'suggestion:\n eligible: true\n'
|
|
114
|
+
f' trigger_description: "{td_e}"\n'
|
|
115
|
+
f' trigger_context: "{tc_e}"')
|
|
116
|
+
raise SystemExit(f"command not classified: {name}")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def migrate_one(path: Path) -> str:
|
|
120
|
+
name = path.stem
|
|
121
|
+
text = path.read_text(encoding="utf-8")
|
|
122
|
+
if "\nsuggestion:" in text.split("\n---\n", 1)[0]:
|
|
123
|
+
return "skip"
|
|
124
|
+
m = FRONTMATTER_RE.search(text)
|
|
125
|
+
if not m:
|
|
126
|
+
return "no-frontmatter"
|
|
127
|
+
body = m.group(2)
|
|
128
|
+
block = build_block(name)
|
|
129
|
+
new_body = body.rstrip() + "\n" + block
|
|
130
|
+
new_text = text[: m.start()] + m.group(1) + new_body + m.group(3) + text[m.end():]
|
|
131
|
+
path.write_text(new_text, encoding="utf-8")
|
|
132
|
+
return "ok"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def main() -> int:
|
|
136
|
+
files = sorted(COMMANDS_DIR.glob("*.md"))
|
|
137
|
+
counts = {"ok": 0, "skip": 0, "no-frontmatter": 0}
|
|
138
|
+
for f in files:
|
|
139
|
+
status = migrate_one(f)
|
|
140
|
+
counts[status] += 1
|
|
141
|
+
print(f"migrated {counts['ok']}, skipped {counts['skip']}, "
|
|
142
|
+
f"no-frontmatter {counts['no-frontmatter']}, total {len(files)}")
|
|
143
|
+
expected = len(INELIGIBLE) + len(ELIGIBLE)
|
|
144
|
+
if len(files) != expected:
|
|
145
|
+
print(f"WARNING: file count {len(files)} != table count {expected}", file=sys.stderr)
|
|
146
|
+
return 1
|
|
147
|
+
return 0
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
sys.exit(main())
|
package/scripts/postinstall.sh
CHANGED
|
@@ -33,6 +33,22 @@ trap 'rm -f "$LOG"' EXIT
|
|
|
33
33
|
bash "$INSTALLER" --quiet >"$LOG" 2>&1
|
|
34
34
|
CODE=$?
|
|
35
35
|
if [[ $CODE -eq 0 ]]; then
|
|
36
|
+
# Optional companion: @event4u/agent-memory. Suggest it once, only if
|
|
37
|
+
# the consumer hasn't already installed it (locally or on PATH). The
|
|
38
|
+
# hint is purely informational; agent-config falls back to file-based
|
|
39
|
+
# memory when the backend is absent.
|
|
40
|
+
if ! command -v memory >/dev/null 2>&1 \
|
|
41
|
+
&& ! command -v agent-memory >/dev/null 2>&1 \
|
|
42
|
+
&& [[ ! -d "$SCRIPT_DIR/../../@event4u/agent-memory" ]]; then
|
|
43
|
+
cat >&2 <<'HINT'
|
|
44
|
+
💡 agent-config tip: install @event4u/agent-memory for persistent agent
|
|
45
|
+
learnings across sessions (optional, dev-only):
|
|
46
|
+
|
|
47
|
+
npm install --save-dev @event4u/agent-memory
|
|
48
|
+
|
|
49
|
+
Skip if you don't need it — agent-config falls back to file-based memory.
|
|
50
|
+
HINT
|
|
51
|
+
fi
|
|
36
52
|
exit 0
|
|
37
53
|
fi
|
|
38
54
|
|
|
@@ -27,6 +27,47 @@
|
|
|
27
27
|
"type": "string",
|
|
28
28
|
"pattern": "^[a-z][a-z0-9-]*$"
|
|
29
29
|
}
|
|
30
|
+
},
|
|
31
|
+
"suggestion": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"required": ["eligible"],
|
|
35
|
+
"description": "Context-aware command-suggestion metadata. The suggestion layer is read-only and never auto-executes; see road-to-context-aware-command-suggestion.",
|
|
36
|
+
"properties": {
|
|
37
|
+
"eligible": {
|
|
38
|
+
"type": "boolean",
|
|
39
|
+
"description": "true → suggestion layer may surface this command; false → never suggest (still works when typed explicitly)."
|
|
40
|
+
},
|
|
41
|
+
"rationale": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 0,
|
|
44
|
+
"maxLength": 240,
|
|
45
|
+
"description": "Why the command is ineligible. Required when eligible: false (enforced by linter)."
|
|
46
|
+
},
|
|
47
|
+
"trigger_description": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 0,
|
|
50
|
+
"maxLength": 240,
|
|
51
|
+
"description": "Natural-language pattern trigger. Required when eligible: true (enforced by linter)."
|
|
52
|
+
},
|
|
53
|
+
"trigger_context": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"minLength": 0,
|
|
56
|
+
"maxLength": 240,
|
|
57
|
+
"description": "Concrete signal trigger (branch name, file pattern, recent tool output). Required when eligible: true (enforced by linter)."
|
|
58
|
+
},
|
|
59
|
+
"confidence_floor": {
|
|
60
|
+
"type": "number",
|
|
61
|
+
"minimum": 0,
|
|
62
|
+
"description": "Optional per-command override of the global confidence floor (0.0–1.0). Defaults to settings."
|
|
63
|
+
},
|
|
64
|
+
"cooldown": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"minLength": 0,
|
|
67
|
+
"maxLength": 16,
|
|
68
|
+
"description": "Optional per-command override of the global cooldown duration (e.g. '10m'). Defaults to settings."
|
|
69
|
+
}
|
|
70
|
+
}
|
|
30
71
|
}
|
|
31
72
|
}
|
|
32
73
|
}
|