v1.91.317.0 feat(harness): trigger-first skill descriptions, hybrid OpenClaw layout, opt-in --context block (GSTA-135) (#3555)

* test(harness): pin the GSTACK_SESSION_KIND=spawned marker and its readers (GSTA-135)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(harness): trigger-first skill descriptions, hybrid OpenClaw layout, opt-in --context block (GSTA-135)

Router lines and Hermes leads open with the skill's triggers; OpenClaw
defaults to hybrid (five task skills plus the router); --context writes the
routing block only into a named file, refusing SOUL.md and any new Hermes
rules file that would outrank one Hermes loads now.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs(harness): skill-use layout, --context and HARNESS_CONTEXT_REFUSED (GSTA-135)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
Garry Tanandcapy-ai[bot] authored and GitHub committed 2026-10-29 13:28:08 +00:00
1 parent c85dd0a799
commit 9f44f188d1
20 files changed
+772 -106

No files matched your search

+3 -1
View File
@@ -29,6 +29,7 @@ import type { ModuleFilter } from './resolvers/types';
import { insertRuntimePreludes } from './resolvers/runtime-root';
import { generateSharedPreambleFile, hoistsPreamble, SHARED_PREAMBLE_FILE } from './resolvers/preamble-hoist';
import { extractVoiceTriggers } from './resolvers/voice-triggers';
import { frontmatterList, withTriggerLead } from '../lib/skill-triggers';
import { ALL_HOST_NAMES, resolveHostArg, getHostConfig } from '../hosts/index';
import type { HostConfig } from './host-config';
@@ -510,7 +511,8 @@ function transformFrontmatter(content: string, host: Host): string {
if (fmEnd === -1) return content;
const frontmatter = content.slice(fmStart + 4, fmEnd);
const body = content.slice(fmEnd + 4);
const { name, description } = extractNameAndDescription(content);
const { name, description: fullDescription } = extractNameAndDescription(content);
const description = fm.descriptionLead ? withTriggerLead(fullDescription, frontmatterList(content, 'triggers'), fm.descriptionLead) : fullDescription;
// Description limit enforcement
if (fm.descriptionLimit) {
+6
View File
@@ -81,6 +81,12 @@ export interface HostConfig {
descriptionLimit?: number | null;
/** What to do when description exceeds limit. Default: 'error'. */
descriptionLimitBehavior?: 'error' | 'truncate' | 'warn';
/**
* Put a trigger-first lead of at most this many chars on the first line of
* the description (lib/skill-triggers.ts withTriggerLead), for hosts whose
* skills index shows only the start of a description.
*/
descriptionLead?: number;
/** Additional frontmatter fields to inject (host-wide). */
extraFields?: Record<string, unknown>;
/**