@homericintelligence/athena-opencode 0.5.0 → 0.5.2
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/README.md +30 -17
- package/package.json +2 -2
- package/plugin.js +20 -5
- package/skills/TECHNICAL_ENGLISH.md +78 -0
- package/skills/_cli.py +33 -22
- package/skills/_plugin.json +1 -0
- package/skills/_support/docs/dependency-resolution.md +203 -0
- package/skills/_support/docs/policies/development.md +131 -0
- package/skills/_support/docs/policies/evidence-integrity.md +40 -0
- package/skills/_support/docs/principles/README.md +565 -0
- package/skills/_support/docs/principles/details/p001-kiss.md +114 -0
- package/skills/_support/docs/principles/details/p002-yagni.md +109 -0
- package/skills/_support/docs/principles/details/p003-dry.md +126 -0
- package/skills/_support/docs/principles/details/p004-solid.md +165 -0
- package/skills/_support/docs/principles/details/p005-modularity.md +123 -0
- package/skills/_support/docs/principles/details/p006-principle-of-least-astonishment.md +115 -0
- package/skills/_support/docs/principles/details/p007-subtraction-over-addition.md +113 -0
- package/skills/_support/docs/principles/details/p008-understand-before-subtracting.md +115 -0
- package/skills/_support/docs/principles/details/p009-general-mechanisms-over-special-cases.md +108 -0
- package/skills/_support/docs/principles/details/p010-scope-fidelity.md +117 -0
- package/skills/_support/docs/principles/details/p011-minimal-coherent-change.md +128 -0
- package/skills/_support/docs/principles/details/p012-evidence-before-modification.md +115 -0
- package/skills/_support/docs/principles/details/p013-avoid-hasty-abstractions.md +112 -0
- package/skills/_support/docs/principles/details/p014-preserve-unrequested-behavior.md +110 -0
- package/skills/_support/docs/principles/details/p015-architecture-conformance.md +124 -0
- package/skills/_support/docs/principles/details/p016-separation-of-concerns.md +125 -0
- package/skills/_support/docs/principles/details/p017-high-cohesion-low-coupling.md +130 -0
- package/skills/_support/docs/principles/details/p018-information-hiding.md +128 -0
- package/skills/_support/docs/principles/details/p019-explicit-contracts.md +134 -0
- package/skills/_support/docs/principles/details/p020-executable-architecture.md +130 -0
- package/skills/_support/docs/principles/details/p021-evolutionary-and-reversible-design.md +126 -0
- package/skills/_support/docs/principles/details/p022-test-behavior-not-implementation.md +129 -0
- package/skills/_support/docs/principles/details/p023-parameterized-table-driven-testing.md +129 -0
- package/skills/_support/docs/principles/details/p024-boundary-value-testing.md +128 -0
- package/skills/_support/docs/principles/details/p025-property-based-testing-for-invariants.md +133 -0
- package/skills/_support/docs/principles/details/p026-regression-before-repair.md +134 -0
- package/skills/_support/docs/principles/details/p027-deterministic-and-hermetic-tests.md +128 -0
- package/skills/_support/docs/principles/details/p028-test-failure-paths.md +133 -0
- package/skills/_support/docs/principles/details/p029-generalize-error-policy-preserve-specific-cause.md +131 -0
- package/skills/_support/docs/principles/details/p030-nearest-responsible-error-boundary.md +133 -0
- package/skills/_support/docs/principles/details/p031-propagate-rather-than-swallow.md +131 -0
- package/skills/_support/docs/principles/details/p032-handle-once-preserve-causality.md +137 -0
- package/skills/_support/docs/principles/details/p033-state-safe-failure-semantics.md +140 -0
- package/skills/_support/docs/principles/details/p034-fail-fast.md +132 -0
- package/skills/_support/docs/principles/details/p035-fail-secure-fail-closed.md +137 -0
- package/skills/_support/docs/principles/details/p036-graceful-degradation.md +137 -0
- package/skills/_support/docs/principles/details/p037-idempotency-before-retry.md +139 -0
- package/skills/_support/docs/principles/details/p038-bounded-retry.md +145 -0
- package/skills/_support/docs/principles/details/p039-bounded-waiting.md +151 -0
- package/skills/_support/docs/principles/details/p040-bounded-resources.md +138 -0
- package/skills/_support/docs/principles/details/p041-backpressure-and-load-shedding.md +141 -0
- package/skills/_support/docs/principles/details/p042-fault-isolation-bulkheads.md +140 -0
- package/skills/_support/docs/principles/details/p043-circuit-breakers.md +148 -0
- package/skills/_support/docs/principles/details/p044-atomicity-where-possible.md +141 -0
- package/skills/_support/docs/principles/details/p045-compensation-where-atomicity-is-impossible.md +163 -0
- package/skills/_support/docs/principles/details/p046-resumability.md +138 -0
- package/skills/_support/docs/principles/details/p047-observability-is-part-of-correctness.md +134 -0
- package/skills/_support/docs/principles/details/p048-secure-by-design.md +132 -0
- package/skills/_support/docs/principles/details/p049-secure-by-default.md +126 -0
- package/skills/_support/docs/principles/details/p050-least-privilege.md +123 -0
- package/skills/_support/docs/principles/details/p051-complete-mediation.md +124 -0
- package/skills/_support/docs/principles/details/p052-separation-of-duties.md +129 -0
- package/skills/_support/docs/principles/details/p053-validate-at-trust-boundaries.md +126 -0
- package/skills/_support/docs/principles/details/p054-defense-in-depth.md +135 -0
- package/skills/_support/docs/principles/details/p055-minimize-attack-surface.md +133 -0
- package/skills/_support/docs/principles/details/p056-secrets-stay-out-of-code-and-context.md +137 -0
- package/skills/_support/docs/principles/details/p057-supply-chain-integrity.md +135 -0
- package/skills/_support/docs/principles/details/p058-bounded-agent-authority.md +137 -0
- package/skills/_support/docs/principles/details/p059-data-is-not-instruction.md +130 -0
- package/skills/_support/docs/principles/details/p060-constrain-sub-agents.md +136 -0
- package/skills/_support/docs/principles/details/p061-separate-decision-from-high-impact-execution.md +131 -0
- package/skills/_support/docs/principles/details/p062-human-approval-for-irreversible-or-high-risk-actions.md +129 -0
- package/skills/_support/docs/principles/details/p063-requirement-to-code-traceability.md +116 -0
- package/skills/_support/docs/principles/details/p064-requirement-to-test-traceability.md +116 -0
- package/skills/_support/docs/principles/details/p065-verify-before-claiming-completion.md +131 -0
- package/skills/_support/docs/principles/details/p066-preserve-existing-work.md +114 -0
- package/skills/_support/docs/principles/details/p067-no-test-cheating.md +126 -0
- package/skills/_support/docs/principles/details/p068-no-validation-bypass.md +119 -0
- package/skills/_support/docs/principles/details/p069-independent-review-for-high-risk-changes.md +129 -0
- package/skills/_support/docs/principles/details/p070-code-health-must-not-regress.md +116 -0
- package/skills/_support/docs/principles/details/p071-consistency-over-personal-preference.md +117 -0
- package/skills/_support/docs/principles/details/p072-technical-evidence-over-preference.md +122 -0
- package/skills/_support/docs/principles/details/p073-optimize-only-with-evidence.md +123 -0
- package/skills/_support/docs/principles/details/p074-prefer-existing-mechanisms.md +121 -0
- package/skills/_support/docs/principles/details/p075-make-invalid-states-hard-to-represent.md +128 -0
- package/skills/_support/docs/principles/details/p076-parse-then-validate-then-operate.md +133 -0
- package/skills/_support/docs/principles/details/p077-separate-policy-from-mechanism.md +112 -0
- package/skills/_support/docs/principles/details/p078-single-source-of-truth.md +131 -0
- package/skills/_support/docs/principles/details/p079-explicit-ownership-and-lifetimes.md +124 -0
- package/skills/_support/docs/principles/details/p080-make-concurrency-deliberate.md +122 -0
- package/skills/_support/docs/principles/details/p081-forward-progress-with-safety.md +125 -0
- package/skills/_support/docs/principles/details/p082-design-for-cancellation.md +133 -0
- package/skills/_support/docs/principles/details/p083-irreversible-actions-last.md +124 -0
- package/skills/_support/docs/principles/details/p084-prefer-local-reasoning.md +131 -0
- package/skills/_support/docs/principles/details/p085-explicit-is-better-than-implicit.md +123 -0
- package/skills/_support/docs/principles/details/p086-readability-counts.md +113 -0
- package/skills/_support/docs/principles/details/p087-comments-explain-why-code-explains-what.md +120 -0
- package/skills/_support/docs/principles/details/p088-delete-dead-code.md +125 -0
- package/skills/_support/docs/principles/details/p089-delete-obsolete-configuration-and-dependencies.md +125 -0
- package/skills/_support/docs/principles/details/p090-prefer-negative-code.md +134 -0
- package/skills/_support/docs/principles/details/p091-test-driven-development.md +149 -0
- package/skills/_support/docs/review/README.md +63 -0
- package/skills/_support/docs/review/behavior-first-testing.md +78 -0
- package/skills/_support/docs/review/common.md +400 -0
- package/skills/_support/docs/review/design-docs.md +74 -0
- package/skills/_support/docs/review/issue-planning.md +247 -0
- package/skills/_support/docs/review/language-routing.md +141 -0
- package/skills/_support/docs/review/repository-scorecard.md +170 -0
- package/skills/advise/SKILL.md +108 -74
- package/skills/advise/scripts/list_retrievable_skills.py +20 -8
- package/skills/advise/scripts/resolve_knowledge_checkout.py +533 -0
- package/skills/brainstorm/SKILL.md +163 -127
- package/skills/change-review/SKILL.md +91 -71
- package/skills/change-review/references/scope-resolution.md +69 -46
- package/skills/change-review/scripts/resolve_scope.py +144 -84
- package/skills/finalize-plan/SKILL.md +205 -139
- package/skills/git-worktrees/SKILL.md +100 -80
- package/skills/git-worktrees/scripts/prepare_worktree.py +34 -15
- package/skills/issue-review/SKILL.md +136 -79
- package/skills/learn/SKILL.md +359 -192
- package/skills/myrmidon-swarm/SKILL.md +126 -86
- package/skills/plan-issue/SKILL.md +122 -81
- package/skills/pr-review/SKILL.md +184 -116
- package/skills/pr-review/references/criteria.md +61 -37
- package/skills/pr-review/references/delivery.md +277 -101
- package/skills/pr-review/references/evidence.md +346 -149
- package/skills/pr-review/references/prevalidated.md +93 -61
- package/skills/pr-review/scripts/collect_evidence.py +312 -162
- package/skills/pr-review/scripts/deliver_go.py +701 -0
- package/skills/pr-review/scripts/diff_context.py +34 -15
- package/skills/pr-review/scripts/materialize_snapshot.py +141 -130
- package/skills/pr-review/scripts/pr_identity.py +27 -15
- package/skills/pr-review/scripts/resolve_pr.py +77 -41
- package/skills/realign/SKILL.md +516 -0
- package/skills/realign/references/aislop-integration.md +215 -0
- package/skills/realign/references/architecture-and-structure.md +271 -0
- package/skills/realign/references/control-flow-and-errors.md +344 -0
- package/skills/realign/references/tests-dependencies-and-security.md +261 -0
- package/skills/realign/scripts/resolve_assessment.py +1525 -0
- package/skills/repo-review/SKILL.md +202 -131
- package/skills/simplify/SKILL.md +174 -0
- package/skills/systematic-debugging/SKILL.md +212 -192
- package/skills/systematic-debugging/scripts/repository_evidence.py +26 -8
- package/skills/test-driven-development/SKILL.md +126 -96
- package/skills/tidy/SKILL.md +104 -59
- package/skills/tidy/scripts/run_tidy.py +54 -6
package/README.md
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
# athena-opencode
|
|
2
2
|
|
|
3
|
-
[Athena](https://github.com/HomericIntelligence/Athena) workflow skills
|
|
4
|
-
[opencode](https://opencode.ai) plugin.
|
|
5
|
-
corpus
|
|
3
|
+
[Athena](https://github.com/HomericIntelligence/Athena) packages its workflow skills as an
|
|
4
|
+
[opencode](https://opencode.ai) plugin. The plugin contains the full canonical skill corpus. It puts
|
|
5
|
+
the corpus in the opencode configuration directory. Opencode finds and loads the corpus there.
|
|
6
|
+
|
|
7
|
+
Athena uses the
|
|
8
|
+
[ASD-STE100 technical-English policy](skills/TECHNICAL_ENGLISH.md)
|
|
9
|
+
for its English technical prose.
|
|
6
10
|
|
|
7
11
|
## Install
|
|
8
12
|
|
|
9
|
-
Add the package to the `plugin` array
|
|
10
|
-
|
|
13
|
+
Add the package to the `plugin` array in the opencode configuration. Use one of these configuration
|
|
14
|
+
files:
|
|
15
|
+
|
|
16
|
+
- `~/.config/opencode/opencode.json`; or
|
|
17
|
+
- a project `opencode.json`.
|
|
11
18
|
|
|
12
19
|
```json
|
|
13
20
|
{
|
|
@@ -16,29 +23,35 @@ Add the package to the `plugin` array of your opencode configuration
|
|
|
16
23
|
}
|
|
17
24
|
```
|
|
18
25
|
|
|
19
|
-
Quit
|
|
26
|
+
Quit opencode. Then, restart opencode. During startup, the plugin copies the bundled `skills/` corpus
|
|
27
|
+
to this location:
|
|
20
28
|
|
|
21
29
|
```
|
|
22
30
|
$XDG_CONFIG_HOME/opencode/skills/athena/
|
|
23
31
|
```
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
skills.
|
|
33
|
+
If `XDG_CONFIG_HOME` does not have a value, the target is
|
|
34
|
+
`~/.config/opencode/skills/athena/`. The plugin writes only in the `athena/` namespace. It does not
|
|
35
|
+
change other skills in your configuration. At each restart, the plugin makes the namespace agree
|
|
36
|
+
with the installed plugin version. Thus, a package update also updates the skills.
|
|
29
37
|
|
|
30
38
|
## Use
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
`
|
|
34
|
-
[`README.md`](https://github.com/HomericIntelligence/Athena#readme) for
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
Use the native opencode skill mechanism. For example, ask opencode to use the `repo-review`,
|
|
41
|
+
`pr-review`, or `plan-issue` skill. See the root
|
|
42
|
+
[`README.md`](https://github.com/HomericIntelligence/Athena#readme) for this information:
|
|
43
|
+
|
|
44
|
+
- the full skill catalog;
|
|
45
|
+
- dependency requirements for Git and Python 3.13;
|
|
46
|
+
- the authenticated GitHub CLI (`gh`) requirement for forge routes; and
|
|
47
|
+
- capability fallbacks.
|
|
37
48
|
|
|
38
49
|
## Uninstall
|
|
39
50
|
|
|
40
|
-
Remove `"@homericintelligence/athena-opencode"` from the `plugin` array
|
|
41
|
-
|
|
51
|
+
1. Remove `"@homericintelligence/athena-opencode"` from the `plugin` array.
|
|
52
|
+
2. Restart opencode.
|
|
53
|
+
3. To remove the files immediately, delete `opencode/skills/athena/` from your configuration
|
|
54
|
+
directory.
|
|
42
55
|
|
|
43
56
|
## License
|
|
44
57
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homericintelligence/athena-opencode",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Athena workflow skills
|
|
3
|
+
"version": "0.5.2",
|
|
4
|
+
"description": "Athena provides workflow skills as an opencode plugin.",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "plugin.js",
|
package/plugin.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
cpSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
readdirSync,
|
|
6
|
+
rmSync,
|
|
7
|
+
statSync,
|
|
8
|
+
} from "node:fs";
|
|
2
9
|
import { homedir } from "node:os";
|
|
3
10
|
import { dirname, join, resolve } from "node:path";
|
|
4
11
|
import { fileURLToPath } from "node:url";
|
|
@@ -26,7 +33,7 @@ export function syncSkills() {
|
|
|
26
33
|
const target = installTarget();
|
|
27
34
|
if (!existsSync(join(source, "_cli.py"))) {
|
|
28
35
|
throw new Error(
|
|
29
|
-
`
|
|
36
|
+
`The plugin cannot find the Athena skills next to plugin.js: '${source}'.`,
|
|
30
37
|
);
|
|
31
38
|
}
|
|
32
39
|
mkdirSync(dirname(target), { recursive: true });
|
|
@@ -39,7 +46,9 @@ async function athenaPlugin() {
|
|
|
39
46
|
try {
|
|
40
47
|
syncSkills();
|
|
41
48
|
} catch (error) {
|
|
42
|
-
console.warn(
|
|
49
|
+
console.warn(
|
|
50
|
+
`[athena-opencode] The plugin could not install the skills: ${error}`,
|
|
51
|
+
);
|
|
43
52
|
}
|
|
44
53
|
return {};
|
|
45
54
|
}
|
|
@@ -47,8 +56,14 @@ async function athenaPlugin() {
|
|
|
47
56
|
export default athenaPlugin;
|
|
48
57
|
|
|
49
58
|
export function bundledSkillNames() {
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
const root = bundledSkillsRoot();
|
|
60
|
+
return readdirSync(root, { withFileTypes: true })
|
|
61
|
+
.filter(
|
|
62
|
+
(entry) =>
|
|
63
|
+
entry.isDirectory() &&
|
|
64
|
+
existsSync(join(root, entry.name, "SKILL.md")) &&
|
|
65
|
+
statSync(join(root, entry.name, "SKILL.md")).isFile(),
|
|
66
|
+
)
|
|
52
67
|
.map((entry) => entry.name)
|
|
53
68
|
.sort();
|
|
54
69
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ASD-STE100 technical-English policy
|
|
2
|
+
|
|
3
|
+
All Athena English technical prose must follow
|
|
4
|
+
[ASD-STE100 Simplified Technical English](https://www.asd-ste100.org/). This requirement applies to
|
|
5
|
+
skills, agent directions, public documents, user messages that a skill produces, and text in a user
|
|
6
|
+
interface.
|
|
7
|
+
|
|
8
|
+
The literal text that this policy identifies does not have to obey it.
|
|
9
|
+
|
|
10
|
+
## Authority
|
|
11
|
+
|
|
12
|
+
Use the current official issue of ASD-STE100 as the authority. Request a copy from the
|
|
13
|
+
[official download page](https://www.asd-ste100.org/STE_downloads.html).
|
|
14
|
+
|
|
15
|
+
This repository policy does not copy or replace the standard. It does not replace approved
|
|
16
|
+
training. Repository checks can find Markdown errors, broken package contracts, and some style
|
|
17
|
+
risks. The checks do not certify conformance to ASD-STE100.
|
|
18
|
+
|
|
19
|
+
## Required method
|
|
20
|
+
|
|
21
|
+
Use these steps when you write or change technical prose:
|
|
22
|
+
|
|
23
|
+
1. Read the applicable technical source before you write.
|
|
24
|
+
2. Use approved words with their approved meanings and parts of speech.
|
|
25
|
+
3. Use a technical noun or a technical verb when the approved dictionary has no necessary term.
|
|
26
|
+
4. Use one term for one meaning.
|
|
27
|
+
5. Do not use a different synonym for the same item or action.
|
|
28
|
+
6. Use American English spelling unless an exact external name uses a different spelling.
|
|
29
|
+
7. Use active voice when you know the actor.
|
|
30
|
+
8. Use the imperative form for a direct instruction.
|
|
31
|
+
9. Put a condition before the related action when the reader must know the condition first.
|
|
32
|
+
10. Give one primary instruction in each numbered step.
|
|
33
|
+
11. Keep sentences short.
|
|
34
|
+
12. Split a sentence when it contains more than one independent idea.
|
|
35
|
+
13. Use a vertical list when it makes complex information easier to identify.
|
|
36
|
+
14. Avoid an `-ing` form when an approved, unambiguous form gives the same meaning.
|
|
37
|
+
15. Define each abbreviation at its first use unless the intended readers always know it.
|
|
38
|
+
16. Keep the technical meaning.
|
|
39
|
+
17. Do not remove a necessary safety, evidence, permission, or failure condition to make a sentence
|
|
40
|
+
shorter.
|
|
41
|
+
18. Review the result against the current official standard.
|
|
42
|
+
|
|
43
|
+
## Literal text
|
|
44
|
+
|
|
45
|
+
Do not change literal text only to make it conform to this policy. Literal text includes:
|
|
46
|
+
|
|
47
|
+
- programming-language syntax and generated code;
|
|
48
|
+
- commands, options, identifiers, paths, URLs, and API field names;
|
|
49
|
+
- machine-readable markers, schemas, and data values;
|
|
50
|
+
- legal text, licenses, and required notices;
|
|
51
|
+
- attributed quotations; and
|
|
52
|
+
- historical records that must preserve their original text.
|
|
53
|
+
|
|
54
|
+
A message for a user or an agent is technical prose even when source code contains it. This rule
|
|
55
|
+
applies to command help, error messages, status messages, prompts, and user-interface labels.
|
|
56
|
+
|
|
57
|
+
Write the prose around literal text in accordance with ASD-STE100.
|
|
58
|
+
|
|
59
|
+
Use code formatting or a quotation format to make the literal boundary clear.
|
|
60
|
+
|
|
61
|
+
## Conflict and verification
|
|
62
|
+
|
|
63
|
+
Technical accuracy, safety controls, security controls, evidence rules, and higher-authority
|
|
64
|
+
instructions take precedence. If simplified wording changes the required meaning, use these steps:
|
|
65
|
+
|
|
66
|
+
1. Keep the required meaning.
|
|
67
|
+
2. Rewrite the sentence.
|
|
68
|
+
|
|
69
|
+
Ask for a technical review when you cannot remove the ambiguity.
|
|
70
|
+
|
|
71
|
+
If you cannot use the current official standard:
|
|
72
|
+
|
|
73
|
+
- Apply this policy.
|
|
74
|
+
- Report the verification gap.
|
|
75
|
+
|
|
76
|
+
Do not state that the text conforms to ASD-STE100.
|
|
77
|
+
|
|
78
|
+
Do not state that a person or tool certified or verified ASD-STE100 conformance.
|
package/skills/_cli.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""This module provides shared command-line support for Athena helpers."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -16,26 +16,29 @@ PLUGIN_ROOT = Path(__file__).resolve().parent.parent
|
|
|
16
16
|
def run_command(
|
|
17
17
|
arguments: Sequence[str], **kwargs: Any
|
|
18
18
|
) -> subprocess.CompletedProcess[str]:
|
|
19
|
-
"""Run an external command
|
|
19
|
+
"""Run an external command and report a missing required capability."""
|
|
20
20
|
if not arguments:
|
|
21
|
-
raise RuntimeError("required command is empty")
|
|
21
|
+
raise RuntimeError("The required command is empty.")
|
|
22
22
|
try:
|
|
23
23
|
check = kwargs.pop("check", False)
|
|
24
24
|
return subprocess.run(arguments, check=check, **kwargs)
|
|
25
25
|
except FileNotFoundError as error:
|
|
26
26
|
command = error.filename or arguments[0]
|
|
27
|
-
raise RuntimeError(
|
|
27
|
+
raise RuntimeError(
|
|
28
|
+
f"The required command is not available: '{command}'."
|
|
29
|
+
) from error
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def git_read_environment() -> dict[str, str]:
|
|
31
|
-
"""Return
|
|
33
|
+
"""Return an isolated environment for immutable, non-interactive Git reads."""
|
|
32
34
|
environment = {
|
|
33
35
|
key: value for key, value in os.environ.items() if not key.startswith("GIT_")
|
|
34
36
|
}
|
|
35
37
|
# `--no-replace-objects` does not disable deprecated graft files. Force Git
|
|
36
|
-
# to read an empty graft source.
|
|
37
|
-
#
|
|
38
|
-
#
|
|
38
|
+
# to read an empty graft source. First, remove each inherited `GIT_*`
|
|
39
|
+
# setting. These settings can redirect or change an immutable read. They
|
|
40
|
+
# include location, object, index, configuration, attribute, pathspec, and
|
|
41
|
+
# transport settings.
|
|
39
42
|
environment.update(
|
|
40
43
|
{
|
|
41
44
|
"GIT_ATTR_NOSYSTEM": "1",
|
|
@@ -58,7 +61,7 @@ def git_read_arguments() -> tuple[str, ...]:
|
|
|
58
61
|
|
|
59
62
|
|
|
60
63
|
def require_complete_git_history(*, cwd: Path | None = None) -> None:
|
|
61
|
-
"""Reject shallow history before
|
|
64
|
+
"""Reject shallow history before calculation of immutable ancestry evidence."""
|
|
62
65
|
result = run_command(
|
|
63
66
|
["git", *git_read_arguments(), "rev-parse", "--is-shallow-repository"],
|
|
64
67
|
capture_output=True,
|
|
@@ -69,20 +72,21 @@ def require_complete_git_history(*, cwd: Path | None = None) -> None:
|
|
|
69
72
|
)
|
|
70
73
|
if result.returncode != 0:
|
|
71
74
|
message = (
|
|
72
|
-
result.stderr.strip()
|
|
75
|
+
result.stderr.strip()
|
|
76
|
+
or "The git rev-parse --is-shallow-repository command failed."
|
|
73
77
|
)
|
|
74
78
|
raise RuntimeError(message)
|
|
75
79
|
if result.stdout.strip() != "false":
|
|
76
80
|
raise RuntimeError(
|
|
77
|
-
"immutable review evidence
|
|
78
|
-
"
|
|
81
|
+
"The immutable review evidence needs a non-shallow repository. "
|
|
82
|
+
"Use a complete source snapshot."
|
|
79
83
|
)
|
|
80
84
|
|
|
81
85
|
|
|
82
86
|
def require_unambiguous_git_merge_base(
|
|
83
87
|
base_oid: str, head_oid: str, *, cwd: Path | None = None
|
|
84
88
|
) -> str:
|
|
85
|
-
"""Return the
|
|
89
|
+
"""Return the only immutable merge base or reject an ambiguous history."""
|
|
86
90
|
result = run_command(
|
|
87
91
|
[
|
|
88
92
|
"git",
|
|
@@ -99,23 +103,28 @@ def require_unambiguous_git_merge_base(
|
|
|
99
103
|
check=False,
|
|
100
104
|
)
|
|
101
105
|
if result.returncode != 0:
|
|
102
|
-
message = result.stderr.strip() or "git merge-base failed"
|
|
106
|
+
message = result.stderr.strip() or "The git merge-base command failed."
|
|
103
107
|
raise RuntimeError(message)
|
|
104
108
|
merge_bases = result.stdout.splitlines()
|
|
105
109
|
if len(merge_bases) != 1 or not merge_bases[0]:
|
|
106
110
|
raise RuntimeError(
|
|
107
|
-
"immutable review evidence requires one unambiguous merge base"
|
|
111
|
+
"The immutable review evidence requires one unambiguous merge base."
|
|
108
112
|
)
|
|
109
113
|
return merge_bases[0]
|
|
110
114
|
|
|
111
115
|
|
|
112
116
|
def plugin_version() -> str:
|
|
113
|
-
"""Return
|
|
114
|
-
|
|
117
|
+
"""Return this corpus's generated version or its adjacent canonical manifest."""
|
|
118
|
+
corpus = Path(__file__).resolve().parent
|
|
119
|
+
manifest = corpus / "_plugin.json"
|
|
120
|
+
if not manifest.exists() and corpus.name == "skills":
|
|
121
|
+
manifest = PLUGIN_ROOT / ".codex-plugin" / "plugin.json"
|
|
115
122
|
document = json.loads(manifest.read_text(encoding="utf-8"))
|
|
116
123
|
version = document.get("version") if isinstance(document, dict) else None
|
|
117
|
-
if not isinstance(version, str):
|
|
118
|
-
raise TypeError(
|
|
124
|
+
if not isinstance(version, str) or not version.strip():
|
|
125
|
+
raise TypeError(
|
|
126
|
+
f"The plugin manifest does not contain a string version: '{manifest}'."
|
|
127
|
+
)
|
|
119
128
|
return version
|
|
120
129
|
|
|
121
130
|
|
|
@@ -132,9 +141,11 @@ class _PluginVersionAction(argparse.Action):
|
|
|
132
141
|
del namespace, values, option_string
|
|
133
142
|
try:
|
|
134
143
|
version = plugin_version()
|
|
135
|
-
except (OSError, TypeError, json.JSONDecodeError) as error:
|
|
144
|
+
except (OSError, TypeError, UnicodeError, json.JSONDecodeError) as error:
|
|
136
145
|
parser.exit(
|
|
137
|
-
1,
|
|
146
|
+
1,
|
|
147
|
+
f"{parser.prog}: error: The tool cannot read the plugin version: "
|
|
148
|
+
f"{error}\n",
|
|
138
149
|
)
|
|
139
150
|
print(f"{parser.prog} {version}")
|
|
140
151
|
parser.exit(0)
|
|
@@ -147,6 +158,6 @@ def argument_parser(*, description: str | None = None) -> argparse.ArgumentParse
|
|
|
147
158
|
"--version",
|
|
148
159
|
action=_PluginVersionAction,
|
|
149
160
|
nargs=0,
|
|
150
|
-
help="
|
|
161
|
+
help="Show the Athena plugin version and exit.",
|
|
151
162
|
)
|
|
152
163
|
return parser
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version": "0.5.2"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Repository resolution
|
|
2
|
+
|
|
3
|
+
Apply the [ASD-STE100 technical-English policy](../../TECHNICAL_ENGLISH.md) to all English technical prose
|
|
4
|
+
in this document.
|
|
5
|
+
|
|
6
|
+
**Why:** Athena must use trusted and current repositories when it changes Mnemosyne or executes
|
|
7
|
+
Hephaestus. Read-only knowledge can use a validated local checkout and then try a best-effort
|
|
8
|
+
refresh. Athena must not report an unverified remote or stale checkout as current.
|
|
9
|
+
|
|
10
|
+
## At a glance
|
|
11
|
+
|
|
12
|
+
During normal resolution for a write or automation execution, Athena does these steps:
|
|
13
|
+
|
|
14
|
+
1. It resolves a trusted owner.
|
|
15
|
+
2. It synchronizes an exact checkout.
|
|
16
|
+
3. It binds use to the reported revision.
|
|
17
|
+
|
|
18
|
+
A trust, authentication, checkout, or update failure stops that write or automation execution.
|
|
19
|
+
|
|
20
|
+
All read-only Mnemosyne paths validate the local checkout first. If `gh`, authentication, and
|
|
21
|
+
network access are available, Athena then tries a best-effort refresh. If the refresh cannot run
|
|
22
|
+
or fails, Athena keeps the validated local checkout and reports the freshness limit. This path
|
|
23
|
+
must do these actions:
|
|
24
|
+
|
|
25
|
+
- bind use to the current `HEAD`;
|
|
26
|
+
- report the current `HEAD` or the refreshed revision;
|
|
27
|
+
- report the freshness and trust limits;
|
|
28
|
+
- never substitute a different repository; and
|
|
29
|
+
- never make a durable write from that checked state.
|
|
30
|
+
|
|
31
|
+
If local knowledge is unavailable, stop only knowledge retrieval. Continue the primary task. The
|
|
32
|
+
`learn` skill can classify a candidate, but it must complete normal resolution and duplicate checks
|
|
33
|
+
before a durable write.
|
|
34
|
+
|
|
35
|
+
```mermaid
|
|
36
|
+
flowchart LR
|
|
37
|
+
A["Resolve dependency"] --> B{"Read-only Mnemosyne use?"}
|
|
38
|
+
B -->|yes| C{"Is a local checkout readable?"}
|
|
39
|
+
C -->|no| E["Report no local guidance; continue primary task"]
|
|
40
|
+
C -->|yes| D["Bind local HEAD and report limits"]
|
|
41
|
+
D --> F{"Can gh auth and discovery run?"}
|
|
42
|
+
F -->|yes| G["Try refresh, then report the updated revision or the local fallback"]
|
|
43
|
+
F -->|no| H["Keep the validated local revision and report the freshness limit"]
|
|
44
|
+
B -->|no| I{"Is there an explicit owner?"}
|
|
45
|
+
I -->|yes| J["Validate override"]
|
|
46
|
+
I -->|no| K{"Is there a trusted organization fork?"}
|
|
47
|
+
K -->|yes| L["Use maintained fork"]
|
|
48
|
+
K -->|no| M["Use canonical upstream"]
|
|
49
|
+
J --> N["Verify origin and clean checkout"]
|
|
50
|
+
L --> N
|
|
51
|
+
M --> N
|
|
52
|
+
N --> O["Fetch, fast-forward, and bind SHA"]
|
|
53
|
+
O --> P["Revalidate automatic-fork trust before use"]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Component details
|
|
57
|
+
|
|
58
|
+
### Owner selection
|
|
59
|
+
|
|
60
|
+
For a route that needs normal resolution of dependency `<Repository>` with environment override
|
|
61
|
+
`<OWNER_VARIABLE>`, use these steps:
|
|
62
|
+
|
|
63
|
+
1. If `<OWNER_VARIABLE>` is not empty, select `<value>/<Repository>`.
|
|
64
|
+
|
|
65
|
+
- Before you use the owner in a path or command, validate it as a GitHub owner name.
|
|
66
|
+
- If the explicit override is not valid, report an error.
|
|
67
|
+
- If the explicit override is not valid, stop.
|
|
68
|
+
- If the explicit override is not valid, do not use a fallback.
|
|
69
|
+
- The owner name must meet these requirements:
|
|
70
|
+
|
|
71
|
+
- It contains 1 through 39 characters.
|
|
72
|
+
- It contains only ASCII letters, digits, or single hyphens.
|
|
73
|
+
- It does not start or end with a hyphen.
|
|
74
|
+
|
|
75
|
+
2. If `<OWNER_VARIABLE>` is empty, get the current repository owner with this command:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
gh repo view --json owner --jq .owner.login
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Use `<current-owner>/<Repository>` only when all these automatic-fork trust gates pass:
|
|
82
|
+
|
|
83
|
+
- The `owner.type` of the current repository is `Organization` and not `User`.
|
|
84
|
+
- The `viewerPermission` of the authenticated viewer on the current repository is `WRITE` (push),
|
|
85
|
+
`MAINTAIN`, or `ADMIN`.
|
|
86
|
+
- GitHub confirms that the candidate is a fork. Its `parent.full_name` must be
|
|
87
|
+
`HomericIntelligence/<Repository>`.
|
|
88
|
+
- Athena can resolve and report the candidate repository and the tip SHA of its remote default
|
|
89
|
+
branch.
|
|
90
|
+
|
|
91
|
+
3. If no trusted override or automatic fork applies, use `HomericIntelligence/<Repository>`.
|
|
92
|
+
|
|
93
|
+
Do not automatically select a repository with the same name in these conditions:
|
|
94
|
+
|
|
95
|
+
- The owner of the current repository is a user.
|
|
96
|
+
- The viewer has read, triage, or no permission.
|
|
97
|
+
- Athena cannot prove canonical ancestry.
|
|
98
|
+
|
|
99
|
+
Use repository metadata to make the fork decision. Do not use only the repository name:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
current_owner=$(gh repo view --json owner --jq '.owner.login')
|
|
103
|
+
gh api "repos/${current_owner}/<Repository>" \
|
|
104
|
+
--jq '.fork == true and .parent.full_name == "HomericIntelligence/<Repository>"'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Only the literal result `true` passes the ancestry check. Use structured application programming
|
|
108
|
+
interface (API) output. Quote each derived value. Resolve these values:
|
|
109
|
+
|
|
110
|
+
- the `owner.type` of the current repository;
|
|
111
|
+
- the `viewerPermission` of the authenticated viewer;
|
|
112
|
+
- the `.default_branch` of the candidate; and
|
|
113
|
+
- the exact tip `.sha` of that branch.
|
|
114
|
+
|
|
115
|
+
The fork can contain modified content after all automatic trust gates pass. If the same-owner
|
|
116
|
+
candidate is missing or not eligible, use the canonical upstream repository. If an API or
|
|
117
|
+
authentication error prevents a trustworthy decision, treat the error as fatal and stop.
|
|
118
|
+
|
|
119
|
+
An explicit owner override is an explicit trust decision. It can select custom fork content without
|
|
120
|
+
the organization and viewer-permission gate. Before you use a resolved dependency, report this
|
|
121
|
+
information:
|
|
122
|
+
|
|
123
|
+
- the exact repository;
|
|
124
|
+
- the commit SHA; and
|
|
125
|
+
- the trust basis: `explicit override`, `maintained organization fork`, or `canonical upstream`.
|
|
126
|
+
|
|
127
|
+
### Dependency map
|
|
128
|
+
|
|
129
|
+
| Purpose | Repository | Override | Checkout |
|
|
130
|
+
| --- | --- | --- | --- |
|
|
131
|
+
| Knowledge | `Mnemosyne` | `HOMERIC_INTELLIGENCE_MNEMOSYNE_OWNER` | `$HOME/.agent_brain/knowledge` |
|
|
132
|
+
| Automation | `Hephaestus` | `HOMERIC_INTELLIGENCE_HEPHAESTUS_OWNER` | `$HOME/.agent_brain/automation` |
|
|
133
|
+
|
|
134
|
+
### Checkout and revalidation
|
|
135
|
+
|
|
136
|
+
Normal resolution applies to Mnemosyne delivery and Hephaestus execution. It requires these
|
|
137
|
+
capabilities:
|
|
138
|
+
|
|
139
|
+
- authenticated GitHub CLI (`gh`);
|
|
140
|
+
- `git`; and
|
|
141
|
+
- network access.
|
|
142
|
+
|
|
143
|
+
Create `$HOME/.agent_brain` when it is necessary. If the checkout is absent, clone the resolved
|
|
144
|
+
repository. For an existing checkout, do these checks and actions:
|
|
145
|
+
|
|
146
|
+
- Require `origin` to identify the resolved `owner/repository`.
|
|
147
|
+
- Do not overwrite local changes or silently change the remote.
|
|
148
|
+
- Fetch `origin`.
|
|
149
|
+
- Resolve the default branch of `origin`.
|
|
150
|
+
- Fast-forward that branch.
|
|
151
|
+
- Report the resolved repository and commit SHA.
|
|
152
|
+
|
|
153
|
+
For an automatically selected same-owner fork, repeat the trust checks immediately before use. Do
|
|
154
|
+
this before you write knowledge or execute automation. Re-query these values:
|
|
155
|
+
|
|
156
|
+
- the Organization owner of the current repository;
|
|
157
|
+
- the permission of the viewer;
|
|
158
|
+
- the `parent.full_name` of the candidate;
|
|
159
|
+
- the resolved repository identity;
|
|
160
|
+
- the default branch; and
|
|
161
|
+
- the tip SHA.
|
|
162
|
+
|
|
163
|
+
Require these values to agree with the reported trust decision. Require the checked-out commit to
|
|
164
|
+
agree with the re-queried tip SHA. Stop if a value does not agree. This check closes the race between
|
|
165
|
+
resolution and use.
|
|
166
|
+
|
|
167
|
+
### Read-only knowledge access
|
|
168
|
+
|
|
169
|
+
Use this path for all read-only Mnemosyne retrieval. Inspect the existing checkout first. Bind use
|
|
170
|
+
to the current `HEAD`. If `gh`, authentication, and network access are available, try a refresh. If
|
|
171
|
+
the refresh cannot run or fails, keep the validated local checkout and report the freshness limit.
|
|
172
|
+
|
|
173
|
+
Do not require the local checkout to have the newest Mnemosyne revision. Do not require its
|
|
174
|
+
revision to agree with the installed Athena revision. The installed skill supplies its own
|
|
175
|
+
retrieval contract.
|
|
176
|
+
|
|
177
|
+
Report this information:
|
|
178
|
+
|
|
179
|
+
- the checkout;
|
|
180
|
+
- the revision;
|
|
181
|
+
- the trust basis or trust uncertainty; and
|
|
182
|
+
- the freshness limit.
|
|
183
|
+
|
|
184
|
+
If the checkout is missing or inspection fails, stop the dependent knowledge retrieval. Continue the
|
|
185
|
+
primary task. `learn` can classify an undelivered candidate, but it cannot make a duplicate decision
|
|
186
|
+
or publish a write until normal resolution succeeds.
|
|
187
|
+
|
|
188
|
+
For Hephaestus execution and the `learn` delivery boundary, these conditions are fatal:
|
|
189
|
+
|
|
190
|
+
- an authentication failure;
|
|
191
|
+
- a missing repository;
|
|
192
|
+
- a fork relationship that is not valid;
|
|
193
|
+
- an unexpected `origin`;
|
|
194
|
+
- conflicting local state;
|
|
195
|
+
- a clone failure;
|
|
196
|
+
- a fetch failure; or
|
|
197
|
+
- a fast-forward failure.
|
|
198
|
+
|
|
199
|
+
Read-only local access never permits pull-request creation before upstream synchronization.
|
|
200
|
+
|
|
201
|
+
Mnemosyne writes use isolated worktrees and always end in a pull request. Athena reads or executes
|
|
202
|
+
Hephaestus from its canonical checkout. Athena never edits Hephaestus unless the user explicitly asks
|
|
203
|
+
for a Hephaestus change.
|