Class: Lemans::TaskDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/lemans/task_definition.rb

Overview

A single task definition: an instruction, an environment, tests, a solution — plus the task's projection of the bench config (setup and verifier sections with per-task overrides applied). Anything lemans does not understand belongs under metadata, copied untouched.

Constant Summary collapse

INSTRUCTION =
"instruction.md"
ENVIRONMENT_DIR =
"environment"
TESTS_DIR =
"tests"
SOLUTION_DIR =
"solution"
FLAT_TEST =
"verification_test.rb"
FLAT_SOLUTION =
"solution.patch"
FLAT_SEED =
"environment.patch"
FRONTMATTER =
/\A---\n(.*?)\n---\n/m

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, name, dir: nil) ⇒ TaskDefinition

Returns a new instance of TaskDefinition.



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/lemans/task_definition.rb', line 108

def initialize(config, name, dir: nil)
  @config = config
  @name = name

  @difficulty = :easy
  @tags = []
  @description = ""
  @metadata = {}

  @dir = dir || config.tasks_dir.join(name)
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



104
105
106
# File 'lib/lemans/task_definition.rb', line 104

def config
  @config
end

#descriptionObject

Returns the value of attribute description.



106
107
108
# File 'lib/lemans/task_definition.rb', line 106

def description
  @description
end

#difficultyObject

Returns the value of attribute difficulty.



106
107
108
# File 'lib/lemans/task_definition.rb', line 106

def difficulty
  @difficulty
end

#dirObject (readonly)

Returns the value of attribute dir.



104
105
106
# File 'lib/lemans/task_definition.rb', line 104

def dir
  @dir
end

#metadataObject

Returns the value of attribute metadata.



106
107
108
# File 'lib/lemans/task_definition.rb', line 106

def 
  @metadata
end

#nameObject (readonly)

Returns the value of attribute name.



104
105
106
# File 'lib/lemans/task_definition.rb', line 104

def name
  @name
end

#tagsObject

Returns the value of attribute tags.



106
107
108
# File 'lib/lemans/task_definition.rb', line 106

def tags
  @tags
end

Class Method Details

.load_from_directory(config, dir) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/lemans/task_definition.rb', line 24

def load_from_directory(config, dir)
  dir = Pathname(dir)
  data = frontmatter(dir)

  task = new(config, data["name"] || dir.basename.to_s, dir:)
  task.description = data["description"].to_s if data["description"]
  task.difficulty = data["difficulty"].to_sym if data["difficulty"]
  task.tags = Array(data["tags"]).map(&:to_s) if data["tags"]
  task. = data["metadata"] if data["metadata"]

  declared_setup = Config::Setup.from_config(data["setup"], root: dir)
  refuse_config_collisions!(task, declared_setup, config.setup)
  task.setup = declared_setup

  task.verifier.restore_paths = Config::Verifier.restore_paths!(data["restore"]) if data.key?("restore")
  if (declared = Config::Setup.from_config(data.dig("verifier", "setup"), root: dir))
    refuse_config_collisions!(task, declared, config.verifier.setup)
    task.verifier.setup = config.verifier.setup.merge(declared)
  end

  validate!(task, data)
  task
end

Instance Method Details

#digestObject



125
126
127
# File 'lib/lemans/task_definition.rb', line 125

def digest
  @digest ||= Config::TreeDigest.call(dir)[0, 16]
end

#environmentObject



144
# File 'lib/lemans/task_definition.rb', line 144

def environment = config.environment

#environment_dockerfileObject



164
# File 'lib/lemans/task_definition.rb', line 164

def environment_dockerfile = dir.join(ENVIRONMENT_DIR, "Dockerfile")

#environment_imageObject



166
167
168
169
170
171
172
173
174
# File 'lib/lemans/task_definition.rb', line 166

def environment_image
  if environment_dockerfile.file?
    Config::ImageSpec.dockerfile(environment_dockerfile, slug: name)
  elsif environment.image
    Config::ImageSpec.registry(environment.image)
  else
    Config::ImageSpec.dockerfile(environment.dockerfile, slug: "shared")
  end
end

#instructionObject

The story alone: frontmatter is for the harness, never for the agent.



121
122
123
# File 'lib/lemans/task_definition.rb', line 121

def instruction
  @instruction ||= dir.join(INSTRUCTION).read.sub(FRONTMATTER, "")
end

#seed?Boolean

Returns:

  • (Boolean)


146
# File 'lib/lemans/task_definition.rb', line 146

def seed? = dir.join(FLAT_SEED).file?

#setupObject

The task's projection of the config sections: bench-wide values with the task's own overrides applied. Phase machinery reads these, never the global config.



132
133
134
# File 'lib/lemans/task_definition.rb', line 132

def setup
  @setup ||= config.setup.merge(own_setup_with_seed)
end

#setup=(declared) ⇒ Object



136
137
138
# File 'lib/lemans/task_definition.rb', line 136

def setup=(declared)
  @declared_setup = declared
end

#solution?Boolean

Returns:

  • (Boolean)


158
# File 'lib/lemans/task_definition.rb', line 158

def solution? = solution_files.any?

#solution_dirObject



162
# File 'lib/lemans/task_definition.rb', line 162

def solution_dir = dir.join(SOLUTION_DIR)

#solution_filesObject



154
155
156
# File 'lib/lemans/task_definition.rb', line 154

def solution_files
  solution_dir.directory? ? expand(solution_dir) : flat(FLAT_SOLUTION)
end

#test_filesObject

[absolute, remote-relative] pairs. Tests stay on the harness side while the agent works; uploaded into the sandbox only at verification.



150
151
152
# File 'lib/lemans/task_definition.rb', line 150

def test_files
  tests_dir.directory? ? expand(tests_dir) : flat(FLAT_TEST)
end

#tests_dirObject



160
# File 'lib/lemans/task_definition.rb', line 160

def tests_dir = dir.join(TESTS_DIR)

#verifierObject



140
141
142
# File 'lib/lemans/task_definition.rb', line 140

def verifier
  @verifier ||= config.verifier.dup
end